diff options
author | Mark Harmstone <mark@harmstone.com> | 2022-11-11 03:30:40 +0000 |
---|---|---|
committer | Mark Harmstone <mark@harmstone.com> | 2022-11-23 01:13:35 +0000 |
commit | e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4 (patch) | |
tree | 36840a4f7b24b27762344fe244a341b2c49b8453 | |
parent | c392c0e0ae1b654c3fafc42e2a9ed7cbfcee0769 (diff) | |
download | gdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.zip gdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.tar.gz gdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.tar.bz2 |
ld: Add section contributions substream to PDB files
-rw-r--r-- | ld/pdb.c | 112 | ||||
-rw-r--r-- | ld/pdb.h | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb.exp | 29 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb2-section-contrib.d | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb2a.s | 9 | ||||
-rw-r--r-- | ld/testsuite/ld-pe/pdb2b.s | 3 |
6 files changed, 162 insertions, 5 deletions
@@ -592,6 +592,96 @@ find_section_number (bfd *abfd, asection *sect) return 0; } +/* Create the substream which maps addresses in the image file to locations + in the original object files. */ +static bool +create_section_contrib_substream (bfd *abfd, void **data, uint32_t *size) +{ + unsigned int num_sc = 0; + struct section_contribution *sc; + uint16_t mod_index; + char *sect_flags; + file_ptr offset; + + for (bfd *in = coff_data (abfd)->link_info->input_bfds; in; + in = in->link.next) + { + for (asection *s = in->sections; s; s = s->next) + { + if (s->size == 0 || discarded_section (s)) + continue; + + num_sc++; + } + } + + *size = sizeof (uint32_t) + (num_sc * sizeof (struct section_contribution)); + *data = xmalloc (*size); + + bfd_putl32 (SECTION_CONTRIB_VERSION_60, *data); + + /* Read characteristics of outputted sections. */ + + sect_flags = xmalloc (sizeof (uint32_t) * abfd->section_count); + + offset = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); + offset += offsetof (struct external_scnhdr, s_flags); + + for (unsigned int i = 0; i < abfd->section_count; i++) + { + bfd_seek (abfd, offset, SEEK_SET); + + if (bfd_bread (sect_flags + (i * sizeof (uint32_t)), sizeof (uint32_t), + abfd) != sizeof (uint32_t)) + { + free (*data); + free (sect_flags); + return false; + } + + offset += sizeof (struct external_scnhdr); + } + + sc = + (struct section_contribution *) ((uint8_t *) *data + sizeof (uint32_t)); + + mod_index = 0; + for (bfd *in = coff_data (abfd)->link_info->input_bfds; in; + in = in->link.next) + { + for (asection *s = in->sections; s; s = s->next) + { + uint16_t sect_num; + + if (s->size == 0 || discarded_section (s)) + continue; + + sect_num = find_section_number (abfd, s->output_section); + + memcpy (&sc->characteristics, + sect_flags + ((sect_num - 1) * sizeof (uint32_t)), + sizeof (uint32_t)); + + bfd_putl16 (sect_num, &sc->section); + bfd_putl16 (0, &sc->padding1); + bfd_putl32 (s->output_offset, &sc->offset); + bfd_putl32 (s->size, &sc->size); + bfd_putl16 (mod_index, &sc->module_index); + bfd_putl16 (0, &sc->padding2); + bfd_putl32 (0, &sc->data_crc); + bfd_putl32 (0, &sc->reloc_crc); + + sc++; + } + + mod_index++; + } + + free (sect_flags); + + return true; +} + /* Stream 4 is the debug information (DBI) stream. */ static bool populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb, @@ -601,12 +691,18 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb, { struct pdb_dbi_stream_header h; struct optional_dbg_header opt; - void *mod_info; - uint32_t mod_info_size; + void *mod_info, *sc; + uint32_t mod_info_size, sc_size; if (!create_module_info_substream (abfd, pdb, &mod_info, &mod_info_size)) return false; + if (!create_section_contrib_substream (abfd, &sc, &sc_size)) + { + free (mod_info); + return false; + } + bfd_putl32 (0xffffffff, &h.version_signature); bfd_putl32 (DBI_STREAM_VERSION_70, &h.version_header); bfd_putl32 (1, &h.age); @@ -617,7 +713,7 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb, bfd_putl16 (sym_rec_stream_num, &h.sym_record_stream); bfd_putl16 (0, &h.pdb_dll_rbld); bfd_putl32 (mod_info_size, &h.mod_info_size); - bfd_putl32 (0, &h.section_contribution_size); + bfd_putl32 (sc_size, &h.section_contribution_size); bfd_putl32 (0, &h.section_map_size); bfd_putl32 (0, &h.source_info_size); bfd_putl32 (0, &h.type_server_map_size); @@ -630,18 +726,28 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb, if (bfd_bwrite (&h, sizeof (h), stream) != sizeof (h)) { + free (sc); free (mod_info); return false; } if (bfd_bwrite (mod_info, mod_info_size, stream) != mod_info_size) { + free (sc); free (mod_info); return false; } free (mod_info); + if (bfd_bwrite (sc, sc_size, stream) != sc_size) + { + free (sc); + return false; + } + + free (sc); + bfd_putl16 (0xffff, &opt.fpo_stream); bfd_putl16 (0xffff, &opt.exception_stream); bfd_putl16 (0xffff, &opt.fixup_stream); @@ -155,6 +155,8 @@ struct optional_dbg_header #define CV_SIGNATURE_C13 4 +#define SECTION_CONTRIB_VERSION_60 0xf12eba2d + /* SC in dbicommon.h */ struct section_contribution { diff --git a/ld/testsuite/ld-pe/pdb.exp b/ld/testsuite/ld-pe/pdb.exp index ab22506..0be65e2 100644 --- a/ld/testsuite/ld-pe/pdb.exp +++ b/ld/testsuite/ld-pe/pdb.exp @@ -626,6 +626,26 @@ proc test_mod_info { mod_info } { } } +proc test_section_contrib { section_contrib } { + global objdump + global srcdir + global subdir + + set fi [open tmpdir/pdb2-sc w] + fconfigure $fi -translation binary + puts -nonewline $fi $section_contrib + close $fi + + set exp [file_contents "$srcdir/$subdir/pdb2-section-contrib.d"] + set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb2-sc"] + + if [string equal $exp $got] { + pass "Correct section contribution substream" + } else { + fail "Incorrect section contribution substream" + } +} + proc test2 { } { global as global ar @@ -650,7 +670,7 @@ proc test2 { } { return } - if ![ld_link $ld "tmpdir/pdb2.exe" "--pdb=tmpdir/pdb2.pdb -e foo tmpdir/pdb2a.o tmpdir/pdb2b.a"] { + if ![ld_link $ld "tmpdir/pdb2.exe" "--pdb=tmpdir/pdb2.pdb --gc-sections -e foo tmpdir/pdb2a.o tmpdir/pdb2b.a"] { unsupported "Create PE image with PDB file" return } @@ -669,13 +689,18 @@ proc test2 { } { set data [read $fi 4] binary scan $data i mod_info_size - seek $fi 36 current + set data [read $fi 4] + binary scan $data i section_contrib_size + + seek $fi 32 current set mod_info [read $fi $mod_info_size] + set section_contrib [read $fi $section_contrib_size] close $fi test_mod_info $mod_info + test_section_contrib $section_contrib } test1 diff --git a/ld/testsuite/ld-pe/pdb2-section-contrib.d b/ld/testsuite/ld-pe/pdb2-section-contrib.d new file mode 100644 index 0000000..3afeb14 --- /dev/null +++ b/ld/testsuite/ld-pe/pdb2-section-contrib.d @@ -0,0 +1,12 @@ + +tmpdir/pdb2-sc: file format binary + +Contents of section .data: + 0000 2dba2ef1 01000000 00000000 10000000 -............... + 0010 20000060 00000000 00000000 00000000 ..`............ + 0020 02000000 00000000 44000000 40000040 ........D...@..@ + 0030 00000000 00000000 00000000 01000000 ................ + 0040 10000000 10000000 20000060 01000000 ........ ..`.... + 0050 00000000 00000000 04000000 00000000 ................ + 0060 0c000000 40000042 02000000 00000000 ....@..B........ + 0070 00000000 ....
\ No newline at end of file diff --git a/ld/testsuite/ld-pe/pdb2a.s b/ld/testsuite/ld-pe/pdb2a.s index 414edeb..beeea8b 100644 --- a/ld/testsuite/ld-pe/pdb2a.s +++ b/ld/testsuite/ld-pe/pdb2a.s @@ -3,3 +3,12 @@ .global foo foo: .secrel32 bar + .long 0 + .long 0 + .long 0 + +.section "gcsect" + +.global baz +baz: + .long 0x12345678 diff --git a/ld/testsuite/ld-pe/pdb2b.s b/ld/testsuite/ld-pe/pdb2b.s index 6401023..3a63386 100644 --- a/ld/testsuite/ld-pe/pdb2b.s +++ b/ld/testsuite/ld-pe/pdb2b.s @@ -3,3 +3,6 @@ .global bar bar: .long 0x12345678 + .long 0 + .long 0 + .long 0 |