gdb添加符号文件所有部分和加载地址

gdb添加符号文件所有部分和加载地址,gdb,debug-symbols,Gdb,Debug Symbols,我正在用gdb和qemu的gdb存根调试引导加载程序(syslinux)。在某个点上,主文件加载一个共享对象ldlinux.elf 我想在gdb中为该文件添加符号。命令addsymbolfile似乎是一个不错的选择。但是,作为一个可重定位文件,我必须指定它加载的内存地址。问题来了 虽然我知道加载段加载的基址,添加符号文件按节工作,并希望我指定每个节加载的地址 如果我在内存中指定文件的基址,我可以告诉gdb加载所有部分的所有符号吗 gdb的行为有意义吗?节标题不用于运行ELF,甚至是可选的。我看不

我正在用gdb和qemu的gdb存根调试引导加载程序(syslinux)。在某个点上,主文件加载一个共享对象
ldlinux.elf

我想在gdb中为该文件添加符号。命令
addsymbolfile
似乎是一个不错的选择。但是,作为一个可重定位文件,我必须指定它加载的内存地址。问题来了

虽然我知道
加载
段加载的基址,
添加符号文件
按节工作,并希望我指定每个节加载的地址

如果我在内存中指定文件的基址,我可以告诉gdb加载所有部分的所有符号吗

gdb的行为有意义吗?节标题不用于运行ELF,甚至是可选的。我看不出指定节的加载地址会有用的用例


例子 以下是共享对象的程序头和节头

Elf file type is DYN (Shared object file) Entry point 0x4c60 There are 3 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x00000000 0x00000000 0x1db10 0x20bfc RWE 0x1000 DYNAMIC 0x01d618 0x0001d618 0x0001d618 0x00098 0x00098 RW 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10 Section to Segment mapping: Segment Sections... 00 .gnu.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text .rodata .ctors .dtors .data.rel.ro .dynamic .got .got.plt .data .bss 01 .dynamic 02 然后所有符号都被0x4c60字节关闭

如果我在内存中指定文件的基址,我可以告诉gdb加载所有部分的所有符号吗

是的,但您需要提供
.text
部分的地址,即
0x7fab000+0x00004c60
。我同意:要找出
.text
的地址是很烦人的,我想多次修复它,所以例如

(gdb) add-symbol-file foo.so @0x7abc0000
只是工作而已。请随时在中提交功能请求

gdb的行为有意义吗


我猜这是源于GDB如何用于调试嵌入式ROM,其中每个部分可以位于任意内存地址。

因此,最后,我使用python和
readelf
工具生成了自己的命令。它不是很干净,因为它在子进程中运行
readelf
,并解析其输出,而不是直接解析ELF文件,但它可以工作(仅适用于32位ELF)

它使用节标题生成并运行
添加符号文件
命令,所有节都正确重新定位。用法非常简单,您可以给它elf文件和文件的基址。由于只给
remove symbol file
文件名,它无法正常工作,因此我制作了一个
remove symbol file all
,它生成并运行了正确的
remove symbol file-a address
命令

(gdb) add-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
add symbol table from file "bios/com32/elflink/ldlinux/ldlinux.elf" at
        .text_addr = 0x7fafc50
        .gnu.hash_addr = 0x7fab094
        .dynsym_addr = 0x7fab874
        .dynstr_addr = 0x7face34
        .rel.dyn_addr = 0x7fadf28
        .rel.plt_addr = 0x7faec08
        .plt_addr = 0x7faf170
        .rodata_addr = 0x7fc34e0
        .ctors_addr = 0x7fc7af0
        .dtors_addr = 0x7fc7b00
        .data.rel.ro_addr = 0x7fc7b20
        .dynamic_addr = 0x7fc8658
        .got_addr = 0x7fc86f0
        .got.plt_addr = 0x7fc87bc
        .data_addr = 0x7fc8a80
        .bss_addr = 0x7fc8b60
(gdb) remove-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
下面是要添加到
.gdbinit
文件中的代码

python
导入子流程
进口稀土
def重新定位分区(文件名、地址):
p=subprocess.Popen([“readelf”,“-S”,filename],stdout=subprocess.PIPE)
节=[]
textaddr='0'
对于p.stdout.readlines()中的行:
行=行解码(“utf-8”).strip()
如果不是line.startswith('[')或line.startswith('[Nr]'):
持续
直线=再分段(r'+','',直线)
line=re.sub(r'\[*(\d+)\]','\g',行)
fieldsvalue=行分割(“”)
fieldsname=['number'、'name'、'type'、'addr'、'offset'、'size'、'entsize'、'flags'、'link'、'info'、'addralign']
sec=dict(zip(fieldsname,fieldsvalue))
如果秒['number']='0':
持续
章节。附加(第二节)
如果sec['name']=='text':
textaddr=sec['addr']
返回(textaddr,节)
类AddSymbolFileAll(gdb.Command):
“”“添加符号文件的正确版本”“”
定义初始化(自):
super(AddSymbolFileAll,self)。\uuuu初始化(AddSymbolFileAll,gdb.COMMAND\u用户)
self.不要重复
def调用(self、arg、from_tty):
argv=gdb.string_到_argv(arg)
filename=argv[0]
如果len(argv)>1:
offset=int(str(gdb.parse_和_eval(argv[1])),0)
其他:
偏移量=0
(textaddr,sections)=重定位分区(文件名,偏移量)
cmd=“添加符号文件%s 0x%08x”%(文件名,int(textaddr,16)+偏移量)
对于分段的s:
地址=int(s['addr'],16)
如果s['name']='.text'或addr==0:
持续
cmd+=“-s%s 0x%08x”%(s['name'],地址+偏移量)
执行(cmd)
类RemoveSymbolFileAll(gdb.Command):
“”“删除符号文件的正确版本”“”
定义初始化(自):
super(RemoveSymbolFileAll,self)。\uuuu init\uuuuu(“删除符号文件全部”,gdb.COMMAND\u用户)
self.不要重复
def调用(self、arg、from_tty):
argv=gdb.string_到_argv(arg)
filename=argv[0]
如果len(argv)>1:
offset=int(str(gdb.parse_和_eval(argv[1])),0)
其他:
偏移量=0
(textaddr,u)=重新定位分区(文件名,偏移量)
cmd=“删除符号文件-0x%08x”%(int(textaddr,16)+偏移量)
执行(cmd)
AddSymbolFileAll()
RemoveSymbolFileAll()
结束

如果我想添加数据符号,我必须添加
.data
.rodata
.bss
部分的选项和地址。如果我有特定的东西要调试,可能还会添加更多。我现在正在编写一个pythong脚本来生成正确的gdb命令。@Celelibi否:通常添加
foo。所以用add
.text
的ress代替加载地址是
.text
.data
所需的全部内容。GDB抱怨:
表达式中的语法错误,在“0x7abc000”附近。
@Yorkwar你抱怨我想要修复的功能缺失。我还没有修复它,所以GDB当然会抱怨。@EmployedRussian你有吗是否添加过此功能?您可以做一个非常小的改进:在调用readelf时添加
-W
,因为有些库的大节名会被截断(例如/lib/x86\u 64-linux-gnu/libnss\u compat-2.27.so->.note.gnu.build id)。
(gdb) add-symbol-file foo.so @0x7abc0000
(gdb) add-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
add symbol table from file "bios/com32/elflink/ldlinux/ldlinux.elf" at
        .text_addr = 0x7fafc50
        .gnu.hash_addr = 0x7fab094
        .dynsym_addr = 0x7fab874
        .dynstr_addr = 0x7face34
        .rel.dyn_addr = 0x7fadf28
        .rel.plt_addr = 0x7faec08
        .plt_addr = 0x7faf170
        .rodata_addr = 0x7fc34e0
        .ctors_addr = 0x7fc7af0
        .dtors_addr = 0x7fc7b00
        .data.rel.ro_addr = 0x7fc7b20
        .dynamic_addr = 0x7fc8658
        .got_addr = 0x7fc86f0
        .got.plt_addr = 0x7fc87bc
        .data_addr = 0x7fc8a80
        .bss_addr = 0x7fc8b60
(gdb) remove-symbol-file-all bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000