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脚本如下:
以上就是全部内容。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。