【问题标题】:How to tell where a shared library is loaded in process address space?如何判断共享库在进程地址空间中的加载位置?
【发布时间】:2014-09-15 09:31:35
【问题描述】:


我正在尝试调试一个共享库,我拥有使用 gdb 的源代码和调试符号。
对于实际使用这个共享库的进程,我没有调试符号或代码(我自己编译它,所以我可以拥有一切,但生成的二进制文件被剥离,以模拟我没有代码的情况)。
该过程打印我正在尝试调试的目标函数 foo 的地址,以测试 gdb 是否知道共享库中符号的正确位置。 foo 存在我的共享库。 我的打印方法是将以下行添加到使用我的共享库的二进制文件中:

printf("%p\n", foo)

...为了增加复杂性,这是我正在远程调试的 Android 系统。

我正在尝试的场景如下:
目标:

root@phone:/proc/23806 # gdbserver --attach :5555 23806                        
Attached; pid = 23806
Listening on port 5555
Remote debugging from host 127.0.0.1

在主机上:

[build@build-machine shared]$ /home/build/shared/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-gdb
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
(gdb) target remote :5555
Remote debugging using :5555
0xb6f17fa0 in ?? ()
(gdb) add-symbol-file out/target/product/armv7-a-neon/symbols/system/lib/libShared.so 
The address where out/target/product/armv7-a-neon/symbols/system/lib/libShared.so has been loaded is missing

现在我知道我需要什么了——这个共享库在进程地址空间中重新定位的 .text 部分,但我不知道如何找到它。 我试过/proc/23806/smaps:

root@phone:/proc/23806 # cat maps  | grep Shared                                  
b6ea0000-b6edb000 r-xp 00000000 b3:10 3337       /system/lib/libShared.so
b6edc000-b6ede000 r--p 0003b000 b3:10 3337       /system/lib/libShared.so
b6ede000-b6edf000 rw-p 0003d000 b3:10 3337       /system/lib/libShared.so

而.text部分位于.so文件中的0x0003ff00处:

[build@build-machine shared]$ objdump -h out/target/product/armv7-a-neon/symbols/system/lib/libShared.so | grep text
  7 .text         0002835c  00003ff0  00003ff0  00003ff0  2**3

所以现在我应该知道我的共享库所在的地址: 0xb6ea0000+0x00003ff0=0xb6ea3ff0(加载库的地方+.text从开始的偏移量) 所以我做了:

(gdb) add-symbol-file out/target/product/armv7-a-neon/symbols/system/lib/libShared.so 0xb6ea3ff0
add symbol table from file "out/target/product/armv7-a-neon/symbols/system/lib/libShared.so" at 
.text_addr = 0xb6ea3ff0
(y or n) y

现在我尝试从我的共享库中为 foo 函数设置断点:

(gdb) b F10
Breakpoint 1 at 0xb6ea41de: file frameworks/native/test/shared/src/shared, line 122.

而且它与我的二进制值 0xb6ea4217(打印在屏幕上)不匹配。

看来我没有为共享库提供正确的内存位置,但我不知道为什么。

感谢任何帮助!

【问题讨论】:

    标签: android c++ c gdb shared-libraries


    【解决方案1】:

    好的,所以在这个问题上摸索了一段时间后,我终于发现出了什么问题。

    解决方案来自不同的角度,我最近不得不调试一些我有部分源代码的代码,所以我进行了混合源代码/汇编调试,并注意到在调试源代码时,事情开始出现偏差 - 我无法使用下一条指令,因为它会崩溃 - 但是当我调试指令时,一切都很好!

    然后我在 AOSP 树中添加并编译了以下短代码:

    int main(int argc, char** argv)
    {
        int first,second;
        first=1;
        second=2;
        return first+second;
    }
    

    而且,正如预期的那样,它无法正确调试(汇编调试有效,源代码调试无效)。

    然后我注意到 argc 已被优化!

    所以...这里真正发生的是编译器优化,它阻止了源代码的调试,因为生成的指令和实际源代码之间没有 1:1 的关系。由于我将默认的构建标志留在了 AOSP 构建脚本中,所以我遇到了这些奇怪的调试问题...

    感谢@EmpyloyedRussian 的帮助!

    【讨论】:

      【解决方案2】:

      最好的办法是运行(gdb) x/10i 0xb6ea41de(gdb) x/10i 0xb6ea4217

      我猜要么是 GDB,要么是你的程序打印了 PLT 条目的地址,而不是 foo 的真实地址。

      附:您调用add-symbol-file 的方法似乎是正确的。

      【讨论】:

      • 不一样的汇编指令......我真的被这个难住了,它在 Linux 机器上完美运行。还有一件事,第二眼我注意到共享库被映射到一个非连续的内存位置,而在我的 Linux 测试中它总是连续的......
      • @IshayPeled“不是同一个程序集”——当然它们不一样——它们怎么可能——它们引用不同的地址。但其中一个可能看起来像一个 PLT 存根。您应该使用x/10i 结果更新您的问题。
      • 地址不一样,这与PLT无关,因为它在Linux机器上完美运行(相同的gdb服务器和gdb版本)。为什么Linux版本和Android版本之间会有任何区别?两者之间的唯一区别是非连续内存映射,我敢打赌这是造成这种混乱的原因,但我无法弄清楚为什么它的映射方式不同以及如何计算符号地址。
      猜你喜欢
      • 1970-01-01
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多