diff options
author | Mark Harmstone <mark@harmstone.com> | 2022-12-09 01:52:34 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-12-23 19:57:56 +1030 |
commit | 598c1ae610f7fd6352ed5445ab38f99a21062f21 (patch) | |
tree | 1224187635903a4f2d84e346ea3605dcdb628995 | |
parent | 8b182dc3c6e7f763504c0f0e9cf699da36d499dd (diff) | |
download | binutils-598c1ae610f7fd6352ed5445ab38f99a21062f21.zip binutils-598c1ae610f7fd6352ed5445ab38f99a21062f21.tar.gz binutils-598c1ae610f7fd6352ed5445ab38f99a21062f21.tar.bz2 |
ld: Write DEBUG_S_LINES entries in PDB file
-rw-r--r-- | ld/pdb.c | 111 | ||||
-rw-r--r-- | ld/pdb.h | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb.exp | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb3-c13-info1.d | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb3a.s | 88 |
5 files changed, 204 insertions, 6 deletions
@@ -624,7 +624,8 @@ parse_string_table (bfd_byte *data, size_t size, static bool handle_debugs_section (asection *s, bfd *mod, struct string_table *strings, uint8_t **dataptr, uint32_t *sizeptr, - struct mod_source_files *mod_source) + struct mod_source_files *mod_source, + bfd *abfd) { bfd_byte *data = NULL; size_t off; @@ -638,6 +639,59 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings, if (!data) return false; + /* Resolve relocations. Addresses are stored within the .debug$S section as + a .secidx, .secrel32 pair. */ + + if (s->flags & SEC_RELOC) + { + struct internal_reloc *relocs; + struct internal_syment *symbols; + asection **sectlist; + unsigned int syment_count; + int sect_num; + struct external_syment *ext; + + syment_count = obj_raw_syment_count (mod); + + relocs = + _bfd_coff_read_internal_relocs (mod, s, false, NULL, true, NULL); + + symbols = xmalloc (sizeof (struct internal_syment) * syment_count); + sectlist = xmalloc (sizeof (asection *) * syment_count); + + ext = (struct external_syment *) (coff_data (mod)->external_syms); + + for (unsigned int i = 0; i < syment_count; i++) + { + bfd_coff_swap_sym_in (mod, &ext[i], &symbols[i]); + } + + sect_num = 1; + + for (asection *sect = mod->sections; sect; sect = sect->next) + { + for (unsigned int i = 0; i < syment_count; i++) + { + if (symbols[i].n_scnum == sect_num) + sectlist[i] = sect; + } + + sect_num++; + } + + if (!bfd_coff_relocate_section (abfd, coff_data (abfd)->link_info, mod, + s, data, relocs, symbols, sectlist)) + { + free (sectlist); + free (symbols); + free (data); + return false; + } + + free (sectlist); + free (symbols); + } + if (bfd_getl32 (data) != CV_SIGNATURE_C13) { free (data); @@ -690,6 +744,32 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings, string_table = (char *) data + off; break; + + case DEBUG_S_LINES: + { + uint16_t sect; + + if (size < sizeof (uint32_t) + sizeof (uint16_t)) + { + free (data); + bfd_set_error (bfd_error_bad_value); + return false; + } + + sect = bfd_getl16 (data + off + sizeof (uint32_t)); + + /* Skip GC'd symbols. */ + if (sect != 0) + { + c13_size += sizeof (uint32_t) + sizeof (uint32_t) + size; + + if (c13_size % sizeof (uint32_t)) + c13_size += + sizeof (uint32_t) - (c13_size % sizeof (uint32_t)); + } + + break; + } } off += size; @@ -734,6 +814,28 @@ handle_debugs_section (asection *s, bfd *mod, struct string_table *strings, bufptr += sizeof (uint32_t) + sizeof (uint32_t) + size; break; + + case DEBUG_S_LINES: + { + uint16_t sect; + + sect = bfd_getl16 (data + off + sizeof (uint32_t)); + + /* Skip if GC'd. */ + if (sect != 0) + { + bfd_putl32 (type, bufptr); + bufptr += sizeof (uint32_t); + + bfd_putl32 (size, bufptr); + bufptr += sizeof (uint32_t); + + memcpy (bufptr, data + off, size); + bufptr += size; + } + + break; + } } off += size; @@ -770,7 +872,8 @@ static bool populate_module_stream (bfd *stream, bfd *mod, uint32_t *sym_byte_size, struct string_table *strings, uint32_t *c13_info_size, - struct mod_source_files *mod_source) + struct mod_source_files *mod_source, + bfd *abfd) { uint8_t int_buf[sizeof (uint32_t)]; uint8_t *c13_info = NULL; @@ -785,7 +888,7 @@ populate_module_stream (bfd *stream, bfd *mod, uint32_t *sym_byte_size, if (!strcmp (s->name, ".debug$S") && s->size >= sizeof (uint32_t)) { if (!handle_debugs_section (s, mod, strings, &c13_info, - c13_info_size, mod_source)) + c13_info_size, mod_source, abfd)) { free (c13_info); free (mod_source->files); @@ -917,7 +1020,7 @@ create_module_info_substream (bfd *abfd, bfd *pdb, void **data, if (!populate_module_stream (stream, in, &sym_byte_size, strings, &c13_info_size, - &source->mods[mod_num])) + &source->mods[mod_num], abfd)) { for (unsigned int i = 0; i < source->mod_count; i++) { @@ -155,6 +155,7 @@ struct optional_dbg_header #define CV_SIGNATURE_C13 4 +#define DEBUG_S_LINES 0xf2 #define DEBUG_S_STRINGTABLE 0xf3 #define DEBUG_S_FILECHKSMS 0xf4 diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp index 9dab411..2e5f834 100644 --- a/ld/testsuite/ld-pe/pdb.exp +++ b/ld/testsuite/ld-pe/pdb.exp @@ -870,7 +870,7 @@ proc test4 { } { return } - if ![ld_link $ld "tmpdir/pdb3.exe" "--pdb=tmpdir/pdb3.pdb tmpdir/pdb3a.o tmpdir/pdb3b.o"] { + if ![ld_link $ld "tmpdir/pdb3.exe" "--pdb=tmpdir/pdb3.pdb --gc-sections -e main tmpdir/pdb3a.o tmpdir/pdb3b.o"] { unsupported "Create PE image with PDB file" return } diff --git a/ld/testsuite/ld-pe/pdb3-c13-info1.d b/ld/testsuite/ld-pe/pdb3-c13-info1.d index f92062b..5a4f948 100644 --- a/ld/testsuite/ld-pe/pdb3-c13-info1.d +++ b/ld/testsuite/ld-pe/pdb3-c13-info1.d @@ -5,4 +5,10 @@ Contents of section .data: 0000 f4000000 30000000 02000000 10016745 ....0.........gE 0010 2301efcd ab8998ba dcfe1023 45670000 #..........#Eg.. 0020 06000000 100198ba dcfe1023 45676745 ...........#EggE - 0030 2301efcd ab890000 #.......
\ No newline at end of file + 0030 2301efcd ab890000 f2000000 58000000 #...........X... + 0040 00000000 01000000 14000000 00000000 ................ + 0050 02000000 1c000000 00000000 01000080 ................ + 0060 04000000 02000080 18000000 02000000 ................ + 0070 1c000000 08000000 03000080 0c000000 ................ + 0080 04000080 00000000 01000000 14000000 ................ + 0090 10000000 05000080 ........
\ No newline at end of file diff --git a/ld/testsuite/ld-pe/pdb3a.s b/ld/testsuite/ld-pe/pdb3a.s index 71795b5..1df84a3 100644 --- a/ld/testsuite/ld-pe/pdb3a.s +++ b/ld/testsuite/ld-pe/pdb3a.s @@ -1,4 +1,5 @@ .equ CV_SIGNATURE_C13, 4 +.equ DEBUG_S_LINES, 0xf2 .equ DEBUG_S_STRINGTABLE, 0xf3 .equ DEBUG_S_FILECHKSMS, 0xf4 .equ CHKSUM_TYPE_MD5, 1 @@ -50,3 +51,90 @@ .chksms_end: .balign 4 + +.long DEBUG_S_LINES +.long .lines_end - .lines_start + +.lines_start: + +.secrel32 main +.secidx main +.short 0 # flags +.long .main_end - main # length of region + +.lines_block1: + +.long 0 # file ID 0 (foo) +.long 2 # no. lines +.long .lines_block2 - .lines_block1 # length + +.long .line1 - main +.long 0x80000001 # line 1 +.long .line2 - main +.long 0x80000002 # line 2 + +.lines_block2: + +.long 0x18 # file ID 18 (bar) +.long 2 # no. lines +.long .lines_block3 - .lines_block2 # length + +.long .line3 - main +.long 0x80000003 # line 3 +.long .line4 - main +.long 0x80000004 # line 4 + +.lines_block3: + +.long 0 # file ID 0 (foo) +.long 1 # no. lines +.long .lines_end - .lines_block3 # length + +.long .line5 - main +.long 0x80000005 # line 5 + +.lines_end: + +.long DEBUG_S_LINES +.long .lines_end2 - .lines_start2 + +.lines_start2: + +.secrel32 gcfunc +.secidx gcfunc +.short 0 # flags +.long .gcfunc_end - gcfunc # length of region + +.lines_block4: + +.long 0 # file ID 0 (foo) +.long 1 # no. lines +.long .lines_end2 - .lines_block4 # length + +.long .line6 - gcfunc +.long 0x80000006 # line 6 + +.lines_end2: + +.text + +.global main +main: +.line1: + .long 0x12345678 +.line2: + .long 0x12345678 +.line3: + .long 0x12345678 +.line4: + .long 0x12345678 +.line5: + .long 0x12345678 +.main_end: + +.section "gcsect" + +gcfunc: +.line6: + .long 0x12345678 +.gcfunc_end: |