1. 解决什么问题

在C++模块编译过程中,总是会遇到undefined symbol xxx,短时间内又不知道从哪里找起,本文解决的就是找符号的问题。

2. 实践步骤 & 案例分析

假设在当前编译过程中,遇到如下错误:

ld.lld: error: undefined symbol: android::content::pm::IPackageManagerNative::asInterface(android::sp<android::IBinder> const&)

现在需要查找以上符号在哪个库中。

首先我们需要知道给了一个so库,里面都定义了哪些符号给外部调用?可以使用Linux下的nm命令:

ubuntu@ubuntu:~$ nm --help
Usage: nm [option(s)] [file(s)]
 List symbols in [file(s)] (a.out by default).
 The options are:
  -a, --debug-syms       Display debugger-only symbols
  -A, --print-file-name  Print name of the input file before every symbol
  -B                     Same as --format=bsd
  -C, --demangle[=STYLE] Decode low-level symbol names into user-level names
                          The STYLE, if specified, can be `auto' (the default),
                          `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'
                          or `gnat'
      --no-demangle      Do not demangle low-level symbol names
      --recurse-limit    Enable a demangling recursion limit.  This is the default.
      --no-recurse-limit Disable a demangling recursion limit.
  -D, --dynamic          Display dynamic symbols instead of normal symbols
      --defined-only     Display only defined symbols
  -e                     (ignored)
  -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',
                           `sysv' or `posix'.  The default is `bsd'
  -g, --extern-only      Display only external symbols
  -l, --line-numbers     Use debugging information to find a filename and
                           line number for each symbol
  -n, --numeric-sort     Sort symbols numerically by address
  -o                     Same as -A
  -p, --no-sort          Do not sort the symbols
  -P, --portability      Same as --format=posix
  -r, --reverse-sort     Reverse the sense of the sort
      --plugin NAME      Load the specified plugin
  -S, --print-size       Print size of defined symbols
  -s, --print-armap      Include index for symbols from archive members
      --size-sort        Sort symbols by size
      --special-syms     Include special symbols in the output
      --synthetic        Display synthetic symbols as well
  -t, --radix=RADIX      Use RADIX for printing symbol values
      --target=BFDNAME   Specify the target object format as BFDNAME
  -u, --undefined-only   Display only undefined symbols
      --with-symbol-versions  Display version strings after symbol names
  -X 32_64               (ignored)
  @FILE                  Read options from FILE
  -h, --help             Display this information
  -V, --version          Display this program's version number

nm: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 srec symbolsrec verilog tekhex binary ihex plugin
Report bugs to <http://www.sourceware.org/bugzilla/>.

常用的选项参数如下:

$ nm -D -g -C --defined-only vendor/lib64/hw/android.hardware.sensors@1.0-impl.so
000000000000fcb8 B full_to_global
000000000000fca0 B global_to_full
000000000000886c T HIDL_FETCH_ISensors
000000000000fb88 D HMI
000000000000fb78 D next_global_handle
000000000000fc98 B waiting_for_data
0000000000009620 T writerTask(void*)
0000000000009ae8 T apiNumToStr(int)
000000000000ae98 T get_multi_hal_module_info()
000000000000d40c T SensorEventQueue::waitForSpace(pthread_mutex_t*)
000000000000d378 T SensorEventQueue::markAsWritten(int)
000000000000d314 T SensorEventQueue::getWritableRegion(int, sensors_event_t**)
000000000000d390 T SensorEventQueue::peek()
000000000000d3b4 T SensorEventQueue::dequeue()
000000000000d388 T SensorEventQueue::getSize()
000000000000d294 T SensorEventQueue::SensorEventQueue(int)
000000000000d294 T SensorEventQueue::SensorEventQueue(int)
000000000000d2e4 T SensorEventQueue::~SensorEventQueue()
000000000000d2e4 T SensorEventQueue::~SensorEventQueue()
0000000000009704 T sensors_poll_context_t::addSubHwDevice(hw_device_t*)
000000000000a5f8 T sensors_poll_context_t::inject_sensor_data(sensors_event_t const*)
000000000000a8ac T sensors_poll_context_t::config_direct_report(int, int, sensors_direct_cfg_t const*)
0000000000009aa4 T sensors_poll_context_t::get_primary_v1_device()
0000000000009e64 T sensors_poll_context_t::copy_event_remap_handle(sensors_event_t*, sensors_event_t*, int)
0000000000009824 T sensors_poll_context_t::get_v0_device_by_handle(int)
0000000000009964 T sensors_poll_context_t::get_v1_device_by_handle(int)
000000000000a834 T sensors_poll_context_t::register_direct_channel(sensors_direct_mem_t const*, int)
0000000000009ac0 T sensors_poll_context_t::get_device_version_by_handle(int)
000000000000a108 T sensors_poll_context_t::poll(sensors_event_t*, int)
000000000000a2a8 T sensors_poll_context_t::batch(int, int, long, long)
000000000000aa5c T sensors_poll_context_t::close()
000000000000a468 T sensors_poll_context_t::flush(int)
0000000000009b18 T sensors_poll_context_t::activate(int, int)
0000000000009cc0 T sensors_poll_context_t::setDelay(int, long)
0000000000008dd0 T android::hardware::sensors::V1_0::implementation::convertToSensor(android::hardware::sensors::V1_0::SensorInfo const&, sensor_t*)
0000000000008d24 T android::hardware::sensors::V1_0::implementation::convertFromSensor(sensor_t const&, android::hardware::sensors::V1_0::SensorInfo*)
0000000000009604 T android::hardware::sensors::V1_0::implementation::convertFromRateLevel(android::hardware::sensors::V1_0::RateLevel)
00000000000091fc T android::hardware::sensors::V1_0::implementation::convertToSensorEvent(android::hardware::sensors::V1_0::Event const&, sensors_event_t*)
0000000000008e8c T android::hardware::sensors::V1_0::implementation::convertFromSensorEvent(sensors_event_t const&, android::hardware::sensors::V1_0::Event*)
0000000000009584 T android::hardware::sensors::V1_0::implementation::convertFromSharedMemInfo(android::hardware::sensors::V1_0::SharedMemInfo const&, sensors_direct_mem_t*)
000000000000796c T android::hardware::sensors::V1_0::implementation::Sensors::getSensorsList(std::__1::function<void (android::hardware::hidl_vec<android::hardware::sensors::V1_0::SensorInfo> const&)>)
0000000000008458 T android::hardware::sensors::V1_0::implementation::Sensors::injectSensorData(android::hardware::sensors::V1_0::Event const&)
0000000000007c78 T android::hardware::sensors::V1_0::implementation::Sensors::setOperationMode(android::hardware::sensors::V1_0::OperationMode)
00000000000086f0 T android::hardware::sensors::V1_0::implementation::Sensors::configDirectReport(int, int, android::hardware::sensors::V1_0::RateLevel, std::__1::function<void (android::hardware::sensors::V1_0::Result, int)>)
0000000000008554 T android::hardware::sensors::V1_0::implementation::Sensors::registerDirectChannel(android::hardware::sensors::V1_0::SharedMemInfo const&, std::__1::function<void (android::hardware::sensors::V1_0::Result, int)>)
0000000000008338 T android::hardware::sensors::V1_0::implementation::Sensors::convertFromSensorEvents(unsigned long, sensors_event_t const*, android::hardware::hidl_vec<android::hardware::sensors::V1_0::Event>*)
0000000000008698 T android::hardware::sensors::V1_0::implementation::Sensors::unregisterDirectChannel(int)
0000000000007d60 T android::hardware::sensors::V1_0::implementation::Sensors::poll(int, std::__1::function<void (android::hardware::sensors::V1_0::Result, android::hardware::hidl_vec<android::hardware::sensors::V1_0::Event> const&, android::hardware::hidl_vec<android::hardware::sensors::V1_0::SensorInfo> const&)>)
000000000000838c T android::hardware::sensors::V1_0::implementation::Sensors::batch(int, long, long)
00000000000083f8 T android::hardware::sensors::V1_0::implementation::Sensors::flush(int)
0000000000007cfc T android::hardware::sensors::V1_0::implementation::Sensors::activate(int, bool)
00000000000074d8 T android::hardware::sensors::V1_0::implementation::Sensors::Sensors()
0000000000007014 T android::hardware::sensors::V1_0::implementation::Sensors::Sensors()
00000000000074c0 T android::hardware::sensors::V1_0::implementation::Sensors::getHalDeviceVersion() const
0000000000007964 T android::hardware::sensors::V1_0::implementation::Sensors::initCheck() const
000000000000c874 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::swap(std::__1::basic_filebuf<char, std::__1::char_traits<char> >&)
000000000000c178 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::sync()
000000000000be60 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::imbue(std::__1::locale const&)
000000000000bf50 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::setbuf(char*, long)
000000000000c048 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::seekoff(long long, std::__1::ios_base::seekdir, unsigned int)
000000000000c108 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::seekpos(std::__1::fpos<mbstate_t>, unsigned int)
000000000000c658 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::overflow(int)
000000000000c5f8 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::pbackfail(int)
000000000000c36c W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::underflow()
000000000000bb88 W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::basic_filebuf()
000000000000be3c W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::~basic_filebuf()
000000000000bdac W std::__1::basic_filebuf<char, std::__1::char_traits<char> >::~basic_filebuf()
0000000000008a54 W std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long)
000000000000af24 W void std::__1::__tree_balance_after_insert<std::__1::__tree_node_base<void*>*>(std::__1::__tree_node_base<void*>*, std::__1::__tree_node_base<void*>*)
000000000000aee4 W std::__1::__tree<std::__1::__value_type<FullHandle, int>, std::__1::__map_value_compare<FullHandle, std::__1::__value_type<FullHandle, int>, std::__1::less<FullHandle>, true>, std::__1::allocator<std::__1::__value_type<FullHandle, int> > >::destroy(std::__1::__tree_node<std::__1::__value_type<FullHandle, int>, void*>*)
000000000000aea4 W std::__1::__tree<std::__1::__value_type<int, FullHandle>, std::__1::__map_value_compare<int, std::__1::__value_type<int, FullHandle>, std::__1::less<int>, true>, std::__1::allocator<std::__1::__value_type<int, FullHandle> > >::destroy(std::__1::__tree_node<std::__1::__value_type<int, FullHandle>, void*>*)
000000000000d134 W void std::__1::vector<long, std::__1::allocator<long> >::__push_back_slow_path<long const&>(long const&)
000000000000cc0c W void std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::__push_back_slow_path<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
000000000000cf4c W void std::__1::vector<hw_device_t*, std::__1::allocator<hw_device_t*> >::__push_back_slow_path<hw_device_t* const&>(hw_device_t* const&)
000000000000cd64 W void std::__1::vector<hw_module_t*, std::__1::allocator<hw_module_t*> >::__push_back_slow_path<hw_module_t* const&>(hw_module_t* const&)
000000000000d040 W void std::__1::vector<SensorEventQueue*, std::__1::allocator<SensorEventQueue*> >::__push_back_slow_path<SensorEventQueue* const&>(SensorEventQueue* const&)
000000000000ce58 W void std::__1::vector<void*, std::__1::allocator<void*> >::__push_back_slow_path<void* const&>(void* const&)
000000000000cac8 W std::__1::basic_istream<char, std::__1::char_traits<char> >& std::__1::getline<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_istream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, char)
000000000000e170 D construction vtable for android::hardware::sensors::V1_0::ISensors-in-android::hardware::sensors::V1_0::implementation::Sensors
000000000000e2a8 D construction vtable for android::hidl::base::V1_0::IBase-in-android::hardware::sensors::V1_0::implementation::Sensors
000000000000e400 V construction vtable for std::__1::basic_istream<char, std::__1::char_traits<char> >-in-std::__1::basic_ifstream<char, std::__1::char_traits<char> >
000000000000e140 D VTT for android::hardware::sensors::V1_0::implementation::Sensors
000000000000e3e0 V VTT for std::__1::basic_ifstream<char, std::__1::char_traits<char> >
000000000000e008 D vtable for android::hardware::sensors::V1_0::implementation::Sensors
000000000000e450 V vtable for std::__1::basic_filebuf<char, std::__1::char_traits<char> >
000000000000e390 V vtable for std::__1::basic_ifstream<char, std::__1::char_traits<char> >

其次我们在编写C++模块中,需要引用的库来自哪里?安卓标准库可以通过如下方式得到:

mkdir system
adb pull /system/lib64 system
adb pull /system/lib system

mkdir vendor
adb pull /vendor/lib64 vendor
adb pull /vendor/lib vendor

对于自己编写生成的库,则可以在如下目录找到:

$(android)/out/target/product/roc_rk3588s_pc_mipi

有了以上知识,我们就知道了大概怎么完成这个事情,以下是我编写的shell脚本用于完成这一任务:

# ubuntu20
library_root_dir=/data/code/android_library
toolchain_nm=nm

###### start search symbol

function print_simplied_libs {
    local -n _all_libs=$1
    local basename_libs=()
    declare -A unique_libs

    for lib in ${_all_libs[@]}; do
        lib_name=$(basename $lib)
        lib_name_no_suffix=${lib_name%.so}
        basename_libs+=($lib_name_no_suffix)
    done

    for lib in ${basename_libs[@]}; do
        unique_libs["$lib"]=1
    done

    for lib in ${!unique_libs[@]}; do
        echo -e "\t$lib"
    done
}

extra_flags="-w"
find_symbol=(
    "android::content::pm::IPackageManagerNative::asInterface"
)

all_libs=()
libraries=$(find $library_root_dir -type f -name "*.so")
for symbol in ${find_symbol[@]}; do
    echo "START search symbol $symbol"
    _current_symbol_all_libs=()

    for library in ${libraries[@]}; do
        result=$($toolchain_nm -D -g -C --defined-only $library 2>/dev/null | grep $extra_flags $symbol)
        if [ "$result" ]; then
            echo -e "\t current library is $library"
            echo -e "\t $result" | grep --color $symbol
            all_libs+=($library)
            _current_symbol_all_libs+=($library)
        fi
    done

    echo -e "\n"
    print_simplied_libs _current_symbol_all_libs
    echo -e "\n"

    echo "END search symbol $symbol"
    echo -e "\n"
done

echo "Summary, you should add these libs: "
print_simplied_libs all_libs

运行上述shell脚本如下:

run.sh

以上就是全部内容。


马师傅777
1 声望0 粉丝