gdb add-symbol-file所有部分和加载地址

时间:2015-10-10 01:07:01

标签: gdb debug-symbols

我正在使用gdb和qemu的gdb-stub调试引导加载程序(syslinux)。在某些时候,主文件加载共享对象ldlinux.elf

我想在gdb中为该文件添加符号。命令add-symbol-file似乎是要走的路。但是,作为可重定位文件,我必须指定它已加载的内存地址。这就是问题所在。

虽然我知道加载LOAD段的基地址,add-symbol-file按部分工作,并且要我指定每个部分加载的地址。

我可以告诉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     
There are 29 section headers, starting at offset 0x78618:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .gnu.hash         GNU_HASH        00000094 000094 0007e0 04   A  2   0  4
  [ 2] .dynsym           DYNSYM          00000874 000874 0015c0 10   A  3   1  4
  [ 3] .dynstr           STRTAB          00001e34 001e34 0010f4 00   A  0   0  1
  [ 4] .rel.dyn          REL             00002f28 002f28 000ce8 08   A  2   0  4
  [ 5] .rel.plt          REL             00003c10 003c10 000568 08  AI  2   6  4
  [ 6] .plt              PROGBITS        00004180 004180 000ae0 04  AX  0   0 16
  [ 7] .text             PROGBITS        00004c60 004c60 013816 00  AX  0   0  4
  [ 8] .rodata           PROGBITS        00018480 018480 00462f 00   A  0   0 32
  [ 9] .ctors            INIT_ARRAY      0001cab0 01cab0 000010 00  WA  0   0  4
  [10] .dtors            FINI_ARRAY      0001cac0 01cac0 000004 00  WA  0   0  4
  [11] .data.rel.ro      PROGBITS        0001cae0 01cae0 000b38 00  WA  0   0 32
  [12] .dynamic          DYNAMIC         0001d618 01d618 000098 08  WA  3   0  4
  [13] .got              PROGBITS        0001d6b0 01d6b0 0000d0 04  WA  0   0  4
  [14] .got.plt          PROGBITS        0001d780 01d780 0002c0 04  WA  0   0  4
  [15] .data             PROGBITS        0001da40 01da40 0000d0 00  WA  0   0 32
  [16] .bss              NOBITS          0001db20 01db10 0030dc 00  WA  0   0 32
  [17] .comment          PROGBITS        00000000 01db10 000026 01  MS  0   0  1
  [18] .debug_aranges    PROGBITS        00000000 01db38 0010c0 00      0   0  8
  [19] .debug_info       PROGBITS        00000000 01ebf8 021ada 00      0   0  1
  [20] .debug_abbrev     PROGBITS        00000000 0406d2 009647 00      0   0  1
  [21] .debug_line       PROGBITS        00000000 049d19 00bd3a 00      0   0  1
  [22] .debug_frame      PROGBITS        00000000 055a54 004574 00      0   0  4
  [23] .debug_str        PROGBITS        00000000 059fc8 00538c 01  MS  0   0  1
  [24] .debug_loc        PROGBITS        00000000 05f354 01312d 00      0   0  1
  [25] .debug_ranges     PROGBITS        00000000 072481 0005d0 00      0   0  1
  [26] .shstrtab         STRTAB          00000000 072a51 000101 00      0   0  1
  [27] .symtab           SYMTAB          00000000 072b54 003530 10     28 504  4
  [28] .strtab           STRTAB          00000000 076084 002593 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

如果我尝试在地址0x7fab000加载文件,那么它将重新定位符号,以便.text部分从0x7fab000开始。

(gdb) add-symbol-file bios/com32/elflink/ldlinux/ldlinux.elf 0x7fab000
add symbol table from file "bios/com32/elflink/ldlinux/ldlinux.elf" at
        .text_addr = 0x7fab000
(y or n) y
Reading symbols from bios/com32/elflink/ldlinux/ldlinux.elf...done.

然后所有符号都被0x4c60字节关闭。

1 个答案:

答案 0 :(得分:7)

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

它使用节头来生成并运行add-symbol-file命令,并正确地重新定位所有节。用法很简单,你给它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 import subprocess import re def relocatesections(filename, addr): p = subprocess.Popen(["readelf", "-S", filename], stdout = subprocess.PIPE) sections = [] textaddr = '0' for line in p.stdout.readlines(): line = line.decode("utf-8").strip() if not line.startswith('[') or line.startswith('[Nr]'): continue line = re.sub(r' +', ' ', line) line = re.sub(r'\[ *(\d+)\]', '\g<1>', line) fieldsvalue = line.split(' ') fieldsname = ['number', 'name', 'type', 'addr', 'offset', 'size', 'entsize', 'flags', 'link', 'info', 'addralign'] sec = dict(zip(fieldsname, fieldsvalue)) if sec['number'] == '0': continue sections.append(sec) if sec['name'] == '.text': textaddr = sec['addr'] return (textaddr, sections) class AddSymbolFileAll(gdb.Command): """The right version for add-symbol-file""" def __init__(self): super(AddSymbolFileAll, self).__init__("add-symbol-file-all", gdb.COMMAND_USER) self.dont_repeat() def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) filename = argv[0] if len(argv) > 1: offset = int(str(gdb.parse_and_eval(argv[1])), 0) else: offset = 0 (textaddr, sections) = relocatesections(filename, offset) cmd = "add-symbol-file %s 0x%08x" % (filename, int(textaddr, 16) + offset) for s in sections: addr = int(s['addr'], 16) if s['name'] == '.text' or addr == 0: continue cmd += " -s %s 0x%08x" % (s['name'], addr + offset) gdb.execute(cmd) class RemoveSymbolFileAll(gdb.Command): """The right version for remove-symbol-file""" def __init__(self): super(RemoveSymbolFileAll, self).__init__("remove-symbol-file-all", gdb.COMMAND_USER) self.dont_repeat() def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) filename = argv[0] if len(argv) > 1: offset = int(str(gdb.parse_and_eval(argv[1])), 0) else: offset = 0 (textaddr, _) = relocatesections(filename, offset) cmd = "remove-symbol-file -a 0x%08x" % (int(textaddr, 16) + offset) gdb.execute(cmd) AddSymbolFileAll() RemoveSymbolFileAll() end 文件中的代码。

protected override void Seed(Tpsc.EDI.EDIContext context)
{
    try
    {
        //EDI.Seed.DoSeed(context);
    }
    catch (DbEntityValidationException e)
    {
        ...
    }
}