aboutsummaryrefslogtreecommitdiff
path: root/ld/pdb.c
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2022-11-11 03:30:40 +0000
committerMark Harmstone <mark@harmstone.com>2022-11-23 01:13:35 +0000
commite2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4 (patch)
tree36840a4f7b24b27762344fe244a341b2c49b8453 /ld/pdb.c
parentc392c0e0ae1b654c3fafc42e2a9ed7cbfcee0769 (diff)
downloadgdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.zip
gdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.tar.gz
gdb-e2a1b0a0d1bf0e9282e4902b2a2b2e75400104b4.tar.bz2
ld: Add section contributions substream to PDB files
Diffstat (limited to 'ld/pdb.c')
-rw-r--r--ld/pdb.c112
1 files changed, 109 insertions, 3 deletions
diff --git a/ld/pdb.c b/ld/pdb.c
index 910589b..6f69574 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -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);