ld: Add section contributions substream to PDB files
This commit is contained in:
parent
c392c0e0ae
commit
e2a1b0a0d1
112
ld/pdb.c
112
ld/pdb.c
@ -592,6 +592,96 @@ find_section_number (bfd *abfd, asection *sect)
|
|||||||
return 0;
|
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. */
|
/* Stream 4 is the debug information (DBI) stream. */
|
||||||
static bool
|
static bool
|
||||||
populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb,
|
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 pdb_dbi_stream_header h;
|
||||||
struct optional_dbg_header opt;
|
struct optional_dbg_header opt;
|
||||||
void *mod_info;
|
void *mod_info, *sc;
|
||||||
uint32_t mod_info_size;
|
uint32_t mod_info_size, sc_size;
|
||||||
|
|
||||||
if (!create_module_info_substream (abfd, pdb, &mod_info, &mod_info_size))
|
if (!create_module_info_substream (abfd, pdb, &mod_info, &mod_info_size))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!create_section_contrib_substream (abfd, &sc, &sc_size))
|
||||||
|
{
|
||||||
|
free (mod_info);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bfd_putl32 (0xffffffff, &h.version_signature);
|
bfd_putl32 (0xffffffff, &h.version_signature);
|
||||||
bfd_putl32 (DBI_STREAM_VERSION_70, &h.version_header);
|
bfd_putl32 (DBI_STREAM_VERSION_70, &h.version_header);
|
||||||
bfd_putl32 (1, &h.age);
|
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 (sym_rec_stream_num, &h.sym_record_stream);
|
||||||
bfd_putl16 (0, &h.pdb_dll_rbld);
|
bfd_putl16 (0, &h.pdb_dll_rbld);
|
||||||
bfd_putl32 (mod_info_size, &h.mod_info_size);
|
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.section_map_size);
|
||||||
bfd_putl32 (0, &h.source_info_size);
|
bfd_putl32 (0, &h.source_info_size);
|
||||||
bfd_putl32 (0, &h.type_server_map_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))
|
if (bfd_bwrite (&h, sizeof (h), stream) != sizeof (h))
|
||||||
{
|
{
|
||||||
|
free (sc);
|
||||||
free (mod_info);
|
free (mod_info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfd_bwrite (mod_info, mod_info_size, stream) != mod_info_size)
|
if (bfd_bwrite (mod_info, mod_info_size, stream) != mod_info_size)
|
||||||
{
|
{
|
||||||
|
free (sc);
|
||||||
free (mod_info);
|
free (mod_info);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (mod_info);
|
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.fpo_stream);
|
||||||
bfd_putl16 (0xffff, &opt.exception_stream);
|
bfd_putl16 (0xffff, &opt.exception_stream);
|
||||||
bfd_putl16 (0xffff, &opt.fixup_stream);
|
bfd_putl16 (0xffff, &opt.fixup_stream);
|
||||||
|
2
ld/pdb.h
2
ld/pdb.h
@ -155,6 +155,8 @@ struct optional_dbg_header
|
|||||||
|
|
||||||
#define CV_SIGNATURE_C13 4
|
#define CV_SIGNATURE_C13 4
|
||||||
|
|
||||||
|
#define SECTION_CONTRIB_VERSION_60 0xf12eba2d
|
||||||
|
|
||||||
/* SC in dbicommon.h */
|
/* SC in dbicommon.h */
|
||||||
struct section_contribution
|
struct section_contribution
|
||||||
{
|
{
|
||||||
|
@ -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 { } {
|
proc test2 { } {
|
||||||
global as
|
global as
|
||||||
global ar
|
global ar
|
||||||
@ -650,7 +670,7 @@ proc test2 { } {
|
|||||||
return
|
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"
|
unsupported "Create PE image with PDB file"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -669,13 +689,18 @@ proc test2 { } {
|
|||||||
set data [read $fi 4]
|
set data [read $fi 4]
|
||||||
binary scan $data i mod_info_size
|
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 mod_info [read $fi $mod_info_size]
|
||||||
|
set section_contrib [read $fi $section_contrib_size]
|
||||||
|
|
||||||
close $fi
|
close $fi
|
||||||
|
|
||||||
test_mod_info $mod_info
|
test_mod_info $mod_info
|
||||||
|
test_section_contrib $section_contrib
|
||||||
}
|
}
|
||||||
|
|
||||||
test1
|
test1
|
||||||
|
12
ld/testsuite/ld-pe/pdb2-section-contrib.d
Normal file
12
ld/testsuite/ld-pe/pdb2-section-contrib.d
Normal file
@ -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 ....
|
@ -3,3 +3,12 @@
|
|||||||
.global foo
|
.global foo
|
||||||
foo:
|
foo:
|
||||||
.secrel32 bar
|
.secrel32 bar
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
.section "gcsect"
|
||||||
|
|
||||||
|
.global baz
|
||||||
|
baz:
|
||||||
|
.long 0x12345678
|
||||||
|
@ -3,3 +3,6 @@
|
|||||||
.global bar
|
.global bar
|
||||||
bar:
|
bar:
|
||||||
.long 0x12345678
|
.long 0x12345678
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
.long 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user