简单的方法...
在gdb 中尝试find 命令。
例如,我猜字符串在共享库的.rodata 部分,所以我们将使用info target 来查找该部分的地址边界,并在该范围内进行搜索:
$ gdb a.out
(gdb) start
Temporary breakpoint 1 at 0x401136
Starting program: /scratch/a.out
Temporary breakpoint 1, 0x0000000000401136 in main ()
(gdb) info target
...
0x00007f5049f0c000 - 0x00007f5049f0c020 is .rodata in ./lib.so
...
(gdb) find 0x00007f5049f0c000,0x00007f5049f0c020,"test string"
0x7f5049f0c000 <foo1>
0x7f5049f0c014
2 patterns found.
如果你的字符串被声明为初始化的字符数组,那应该可以工作,比如
static const char foo1[] = "test string";
如果它们被声明为指针,比如
static const char *foo2 = "another test string";
这会有点困难。字符串本身不会被标记,您要查找的符号将是指向该字符串的指针。然后你需要再次使用find 命令来搜索那个指针值,我猜它在.data 部分。
(gdb) find 0x00007f5049f0c000,0x00007f5049f0c020,"another test string"
0x7f5049f0c00c
1 pattern found.
(gdb) info target
...
0x00007f5049f0e018 - 0x00007f5049f0e028 is .data in ./foo.so
...
(gdb) find 0x00007f5049f0e018,0x00007f5049f0e028,0x7f5049f0c00c
0x7f5049f0e020 <foo2>
1 pattern found.
学习经历...
使用strings --radix=x,找到你的字符串。将列出文件中的偏移量(以十六进制表示);例如:
$ strings --radix=x lib.so | grep "test string"
5ad740 test string
现在您需要将该文件偏移量转换为虚拟地址。
使用readelf -lW列出库的段;你会看到这样的东西:
$ readelf -lW lib.so | grep -e Type -e LOAD
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x004dc0 0x004dc0 R 0x1000
LOAD 0x005000 0x0000000000405000 0x0000000000405000 0x53a989 0x53a989 R E 0x1000
LOAD 0x540000 0x0000000000940000 0x0000000000940000 0x28f7c2 0x28f7c2 R 0x1000
LOAD 0x7cfc70 0x0000000000bd0c70 0x0000000000bd0c70 0x0014b0 0x00d518 RW 0x1000
您对Offset、VirtAddr 和FileSiz 列感兴趣。找到包含文件偏移量X 的 LOAD 段,其中Offset <= X < Offset + FileSiz。在此示例中,偏移量 0x5ad740 位于第三段(从偏移量 0x540000 开始)。通过减去段的起始偏移量并添加段的起始虚拟地址,将您的偏移量转换为虚拟地址:
offset - starting offset + starting virtual address = virtual address
0x5ad740 - 0x540000 + 0x940000 = 0x9ad740
现在使用nm -n 按地址顺序扫描符号表。如果幸运的话,您会找到完全匹配的:
$ nm -n lib.so | grep 9ad740
00000000009ad740 R foo1
否则,您将需要查找最近的具有较低地址的符号。应该就是这样,如果字符串被声明为数组。
如果字符串被声明为指针,那么这些指针将需要动态重定位(我们正在查看共享库,对吗?)——很可能是R_xxx_RELATIVE 重定位。寻找一个 RELATIVE 重定位,它的加数与你的字符串的虚拟地址匹配:
$ readelf -rW lib.so
Relocation section '.rela.dyn' at offset 0xc00000 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000c00018 0000000000000008 R_X86_64_RELATIVE 9ad740
这表明您的指针位于 0xc00018。再次使用nm,您可以找到该虚拟地址的符号:
$ nm -n lib.so | grep c00018
0000000000c00018 R foo2