ld: Write DEBUG_S_LINES entries in PDB file

This commit is contained in:
Mark Harmstone 2022-12-09 01:52:34 +00:00 committed by Alan Modra
parent 8b182dc3c6
commit 598c1ae610
5 changed files with 204 additions and 6 deletions

111
ld/pdb.c
View file

@ -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++)
{

View file

@ -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

View file

@ -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
}

View file

@ -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 #.......
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 ........

View file

@ -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: