ld: Copy other symbols into PDB file

This commit is contained in:
Mark Harmstone 2022-12-09 01:52:39 +00:00 committed by Alan Modra
parent 81814b6f5b
commit 5d9c033689
5 changed files with 1076 additions and 0 deletions

362
ld/pdb.c
View file

@ -908,11 +908,15 @@ find_end_of_scope (uint8_t *data, uint32_t size)
{
case S_GPROC32:
case S_LPROC32:
case S_BLOCK32:
case S_INLINESITE:
case S_THUNK32:
scope_level++;
break;
case S_END:
case S_PROC_ID_END:
case S_INLINESITE_END:
scope_level--;
if (scope_level == 0)
@ -961,6 +965,7 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
{
uint8_t *orig_buf = *buf;
unsigned int scope_level = 0;
uint8_t *scope = NULL;
while (size >= sizeof (uint16_t))
{
@ -1206,6 +1211,8 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
free (ref);
scope = *buf;
memcpy (*buf, proc, len);
*buf += len;
@ -1321,16 +1328,343 @@ parse_symbols (uint8_t *data, uint32_t size, uint8_t **buf,
}
case S_END:
case S_INLINESITE_END:
case S_PROC_ID_END:
memcpy (*buf, data, len);
if (type == S_PROC_ID_END) /* transform to S_END */
bfd_putl16 (S_END, *buf + sizeof (uint16_t));
/* Reset scope variable back to the address of the previous
scope start. */
if (scope)
{
uint32_t parent;
uint16_t scope_start_type =
bfd_getl16 (scope + sizeof (uint16_t));
switch (scope_start_type)
{
case S_GPROC32:
case S_LPROC32:
parent = bfd_getl32 (scope + offsetof (struct procsym,
parent));
break;
case S_BLOCK32:
parent = bfd_getl32 (scope + offsetof (struct blocksym,
parent));
break;
case S_INLINESITE:
parent = bfd_getl32 (scope + offsetof (struct inline_site,
parent));
break;
case S_THUNK32:
parent = bfd_getl32 (scope + offsetof (struct thunk,
parent));
break;
default:
einfo (_("%P: warning: unexpected CodeView scope start"
" record %v\n"), scope_start_type);
bfd_set_error (bfd_error_bad_value);
return false;
}
if (parent == 0)
scope = NULL;
else
scope = orig_buf + parent - sizeof (uint32_t);
}
*buf += len;
scope_level--;
break;
case S_BUILDINFO:
{
struct buildinfosym *bi = (struct buildinfosym *) data;
if (len < sizeof (struct buildinfosym))
{
einfo (_("%P: warning: truncated CodeView record"
" S_BUILDINFO\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&bi->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_BLOCK32:
{
struct blocksym *bl = (struct blocksym *) data;
uint8_t *endptr;
uint32_t end;
if (len < offsetof (struct blocksym, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_BLOCK32\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &bl->parent);
endptr = find_end_of_scope (data, size);
if (!endptr)
{
einfo (_("%P: warning: could not find end of"
" S_BLOCK32 record\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
bfd_putl32 (end, &bl->end);
scope = *buf;
memcpy (*buf, data, len);
*buf += len;
scope_level++;
break;
}
case S_BPREL32:
{
struct bprelsym *bp = (struct bprelsym *) data;
if (len < offsetof (struct bprelsym, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_BPREL32\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&bp->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_REGISTER:
{
struct regsym *reg = (struct regsym *) data;
if (len < offsetof (struct regsym, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_REGISTER\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&reg->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_REGREL32:
{
struct regrel *rr = (struct regrel *) data;
if (len < offsetof (struct regrel, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_REGREL32\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&rr->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_LOCAL:
{
struct localsym *l = (struct localsym *) data;
if (len < offsetof (struct localsym, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_LOCAL\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&l->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_INLINESITE:
{
struct inline_site *is = (struct inline_site *) data;
uint8_t *endptr;
uint32_t end;
if (len < offsetof (struct inline_site, binary_annotations))
{
einfo (_("%P: warning: truncated CodeView record"
" S_INLINESITE\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &is->parent);
endptr = find_end_of_scope (data, size);
if (!endptr)
{
einfo (_("%P: warning: could not find end of"
" S_INLINESITE record\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
bfd_putl32 (end, &is->end);
if (!remap_symbol_type (&is->inlinee, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
scope = *buf;
memcpy (*buf, data, len);
*buf += len;
scope_level++;
break;
}
case S_THUNK32:
{
struct thunk *th = (struct thunk *) data;
uint8_t *endptr;
uint32_t end;
if (len < offsetof (struct thunk, name))
{
einfo (_("%P: warning: truncated CodeView record"
" S_THUNK32\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
bfd_putl32 (scope - orig_buf + sizeof (uint32_t), &th->parent);
endptr = find_end_of_scope (data, size);
if (!endptr)
{
einfo (_("%P: warning: could not find end of"
" S_THUNK32 record\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
end = *buf - orig_buf + sizeof (uint32_t) + endptr - data;
bfd_putl32 (end, &th->end);
scope = *buf;
memcpy (*buf, data, len);
*buf += len;
scope_level++;
break;
}
case S_HEAPALLOCSITE:
{
struct heap_alloc_site *has = (struct heap_alloc_site *) data;
if (len < sizeof (struct heap_alloc_site))
{
einfo (_("%P: warning: truncated CodeView record"
" S_HEAPALLOCSITE\n"));
bfd_set_error (bfd_error_bad_value);
return false;
}
if (!remap_symbol_type (&has->type, map, num_types))
{
bfd_set_error (bfd_error_bad_value);
return false;
}
memcpy (*buf, data, len);
*buf += len;
break;
}
case S_OBJNAME: /* just copy */
case S_COMPILE3:
case S_UNAMESPACE:
case S_FRAMEPROC:
case S_FRAMECOOKIE:
case S_LABEL32:
case S_DEFRANGE_REGISTER_REL:
case S_DEFRANGE_FRAMEPOINTER_REL:
case S_DEFRANGE_SUBFIELD_REGISTER:
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
case S_DEFRANGE_REGISTER:
memcpy (*buf, data, len);
*buf += len;
break;
default:
einfo (_("%P: warning: unrecognized CodeView record %v\n"), type);
bfd_set_error (bfd_error_bad_value);
@ -1441,12 +1775,40 @@ calculate_symbols_size (uint8_t *data, uint32_t size, uint32_t *sym_size)
*sym_size += len;
break;
case S_BLOCK32: /* always copied */
case S_INLINESITE:
case S_THUNK32:
*sym_size += len;
scope_level++;
break;
case S_END: /* always copied */
case S_PROC_ID_END:
case S_INLINESITE_END:
*sym_size += len;
scope_level--;
break;
case S_OBJNAME: /* always copied */
case S_COMPILE3:
case S_UNAMESPACE:
case S_FRAMEPROC:
case S_FRAMECOOKIE:
case S_LABEL32:
case S_BUILDINFO:
case S_BPREL32:
case S_REGISTER:
case S_REGREL32:
case S_LOCAL:
case S_DEFRANGE_REGISTER_REL:
case S_DEFRANGE_FRAMEPOINTER_REL:
case S_DEFRANGE_SUBFIELD_REGISTER:
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
case S_DEFRANGE_REGISTER:
case S_HEAPALLOCSITE:
*sym_size += len;
break;
default:
einfo (_("%P: warning: unrecognized CodeView record %v\n"), type);
return false;

179
ld/pdb.h
View file

@ -71,20 +71,41 @@
#define LF_UQUADWORD 0x800a
#define S_END 0x0006
#define S_FRAMEPROC 0x1012
#define S_OBJNAME 0x1101
#define S_THUNK32 0x1102
#define S_BLOCK32 0x1103
#define S_LABEL32 0x1105
#define S_REGISTER 0x1106
#define S_CONSTANT 0x1107
#define S_UDT 0x1108
#define S_BPREL32 0x110b
#define S_LDATA32 0x110c
#define S_GDATA32 0x110d
#define S_PUB32 0x110e
#define S_LPROC32 0x110f
#define S_GPROC32 0x1110
#define S_REGREL32 0x1111
#define S_LTHREAD32 0x1112
#define S_GTHREAD32 0x1113
#define S_UNAMESPACE 0x1124
#define S_PROCREF 0x1125
#define S_LPROCREF 0x1127
#define S_FRAMECOOKIE 0x113a
#define S_COMPILE3 0x113c
#define S_LOCAL 0x113e
#define S_DEFRANGE_REGISTER 0x1141
#define S_DEFRANGE_FRAMEPOINTER_REL 0x1142
#define S_DEFRANGE_SUBFIELD_REGISTER 0x1143
#define S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 0x1144
#define S_DEFRANGE_REGISTER_REL 0x1145
#define S_LPROC32_ID 0x1146
#define S_GPROC32_ID 0x1147
#define S_BUILDINFO 0x114c
#define S_INLINESITE 0x114d
#define S_INLINESITE_END 0x114e
#define S_PROC_ID_END 0x114f
#define S_HEAPALLOCSITE 0x115e
/* PDBStream70 in pdb1.h */
struct pdb_stream_70
@ -617,6 +638,164 @@ struct constsym
char name[];
} ATTRIBUTE_PACKED;
/* BUILDINFOSYM in cvinfo.h */
struct buildinfosym
{
uint16_t size;
uint16_t kind;
uint32_t type;
} ATTRIBUTE_PACKED;
/* BLOCKSYM32 in cvinfo.h */
struct blocksym
{
uint16_t size;
uint16_t kind;
uint32_t parent;
uint32_t end;
uint32_t len;
uint32_t offset;
uint16_t section;
char name[];
} ATTRIBUTE_PACKED;
/* BPRELSYM32 in cvinfo.h */
struct bprelsym
{
uint16_t size;
uint16_t kind;
uint32_t bp_offset;
uint32_t type;
char name[];
} ATTRIBUTE_PACKED;
/* REGSYM in cvinfo.h */
struct regsym
{
uint16_t size;
uint16_t kind;
uint32_t type;
uint16_t reg;
char name[];
} ATTRIBUTE_PACKED;
/* REGREL32 in cvinfo.h */
struct regrel
{
uint16_t size;
uint16_t kind;
uint32_t offset;
uint32_t type;
uint16_t reg;
char name[];
} ATTRIBUTE_PACKED;
/* LOCALSYM in cvinfo.h */
struct localsym
{
uint16_t size;
uint16_t kind;
uint32_t type;
uint16_t flags;
char name[];
} ATTRIBUTE_PACKED;
/* CV_LVAR_ADDR_RANGE in cvinfo.h */
struct lvar_addr_range
{
uint32_t offset;
uint16_t section;
uint16_t length;
} ATTRIBUTE_PACKED;
/* CV_LVAR_ADDR_GAP in cvinfo.h */
struct lvar_addr_gap {
uint16_t offset;
uint16_t length;
} ATTRIBUTE_PACKED;
/* DEFRANGESYMREGISTERREL in cvinfo.h */
struct defrange_register_rel
{
uint16_t size;
uint16_t kind;
uint16_t reg;
uint16_t offset_parent;
uint32_t offset_register;
struct lvar_addr_range range;
struct lvar_addr_gap gaps[];
} ATTRIBUTE_PACKED;
/* DEFRANGESYMFRAMEPOINTERREL in cvinfo.h */
struct defrange_framepointer_rel
{
uint16_t size;
uint16_t kind;
uint32_t offset;
struct lvar_addr_range range;
struct lvar_addr_gap gaps[];
} ATTRIBUTE_PACKED;
/* DEFRANGESYMSUBFIELDREGISTER in cvinfo.h */
struct defrange_subfield_register
{
uint16_t size;
uint16_t kind;
uint16_t reg;
uint16_t attributes;
uint32_t offset_parent;
struct lvar_addr_range range;
struct lvar_addr_gap gaps[];
} ATTRIBUTE_PACKED;
/* DEFRANGESYMREGISTER in cvinfo.h */
struct defrange_register
{
uint16_t size;
uint16_t kind;
uint16_t reg;
uint16_t attributes;
struct lvar_addr_range range;
struct lvar_addr_gap gaps[];
} ATTRIBUTE_PACKED;
/* INLINESITESYM in cvinfo.h */
struct inline_site
{
uint16_t size;
uint16_t kind;
uint32_t parent;
uint32_t end;
uint32_t inlinee;
uint8_t binary_annotations[];
} ATTRIBUTE_PACKED;
/* THUNKSYM32 in cvinfo.h */
struct thunk
{
uint16_t size;
uint16_t kind;
uint32_t parent;
uint32_t end;
uint32_t next;
uint32_t offset;
uint16_t section;
uint16_t length;
uint8_t thunk_type;
char name[];
} ATTRIBUTE_PACKED;
/* HEAPALLOCSITE in cvinfo.h */
struct heap_alloc_site
{
uint16_t size;
uint16_t kind;
uint32_t offset;
uint16_t section;
uint16_t length;
uint32_t type;
} ATTRIBUTE_PACKED;
extern bool create_pdb_file (bfd *, const char *, const unsigned char *);
#endif

View file

@ -0,0 +1,38 @@
*: file format binary
Contents of section .data:
0000 04000000 0e000111 00000000 73796d73 ............syms
0010 332e6f00 22003c11 00000000 d0000000 3.o.".<.........
0020 00000000 00000000 00000000 0000474e ..............GN
0030 55204153 00f3f2f1 06002411 73746400 U AS......$.std.
0040 06004c11 05100000 2e001011 00000000 ..L.............
0050 18020000 00000000 06000000 00000000 ................
0060 00000000 01100000 00000000 01000070 ...............p
0070 726f6331 00f3f2f1 1e001210 00000000 roc1............
0080 00000000 00000000 00000000 00000000 ................
0090 00000000 0000f2f1 0e003a11 08000000 ..........:.....
00a0 48010000 000000f1 0e000b11 04000000 H...............
00b0 02100000 666f6f00 0e000611 02100000 ....foo.........
00c0 48016261 7200f2f1 12001111 04000000 H.bar...........
00d0 02100000 48016261 7a00f2f1 12003e11 ....H.baz.....>.
00e0 02100000 00006c6f 63616c31 00f3f2f1 ......local1....
00f0 16004511 48010000 00000000 01000000 ..E.H...........
0100 01000400 02000100 12003e11 02100000 ..........>.....
0110 00006c6f 63616c32 00f3f2f1 12004211 ..local2......B.
0120 04000000 01000000 01000400 02000100 ................
0130 12003e11 02100000 00006c6f 63616c33 ..>.......local3
0140 00f3f2f1 16004311 48010000 04000000 ......C.H.......
0150 01000000 01000400 02000100 12003e11 ..............>.
0160 02100000 00006c6f 63616c34 00f3f2f1 ......local4....
0170 06004411 04000000 12003e11 02100000 ..D.......>.....
0180 00006c6f 63616c35 00f3f2f1 12004111 ..local5......A.
0190 48010000 01000000 01000400 02000100 H...............
01a0 0e004d11 48000000 b0010000 06100000 ..M.H...........
01b0 02004e11 16000311 48000000 e0010000 ..N.....H.......
01c0 04000000 01000000 010000f1 12000511 ................
01d0 02000000 0100006c 6162656c 00f3f2f1 .......label....
01e0 02000600 1e000211 48000000 04020000 ........H.......
01f0 00000000 06000000 01000100 00746875 .............thu
0200 6e6b00f1 02000600 0e005e11 04000000 nk........^.....
0210 01000100 02100000 02000600 00000000 ................

View file

@ -0,0 +1,430 @@
.equ CV_SIGNATURE_C13, 4
.equ DEBUG_S_SYMBOLS, 0xf1
.equ T_VOID, 0x0003
.equ T_UINT4, 0x0075
.equ LF_MODIFIER, 0x1001
.equ LF_PROCEDURE, 0x1008
.equ LF_ARGLIST, 0x1201
.equ LF_FUNC_ID, 0x1601
.equ LF_BUILDINFO, 0x1603
.equ LF_STRING_ID, 0x1605
.equ S_END, 0x0006
.equ S_FRAMEPROC, 0x1012
.equ S_OBJNAME, 0x1101
.equ S_THUNK32, 0x1102
.equ S_BLOCK32, 0x1103
.equ S_LABEL32, 0x1105
.equ S_REGISTER, 0x1106
.equ S_BPREL32, 0x110b
.equ S_GPROC32, 0x1110
.equ S_REGREL32, 0x1111
.equ S_UNAMESPACE, 0x1124
.equ S_FRAMECOOKIE, 0x113a
.equ S_COMPILE3, 0x113c
.equ S_LOCAL, 0x113e
.equ S_DEFRANGE_REGISTER, 0x1141
.equ S_DEFRANGE_FRAMEPOINTER_REL, 0x1142
.equ S_DEFRANGE_SUBFIELD_REGISTER, 0x1143
.equ S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE, 0x1144
.equ S_DEFRANGE_REGISTER_REL, 0x1145
.equ S_BUILDINFO, 0x114c
.equ S_INLINESITE, 0x114d
.equ S_INLINESITE_END, 0x114e
.equ S_HEAPALLOCSITE, 0x115e
.equ CV_AMD64_RAX, 328
.equ CV_CFL_AMD64, 0xd0
.section ".debug$S", "rn"
.long CV_SIGNATURE_C13
.long DEBUG_S_SYMBOLS
.long .syms_end - .syms_start
.syms_start:
.objname1:
.short .compile1 - .objname1 - 2
.short S_OBJNAME
.long 0 # signature
.asciz "syms3.o"
.compile1:
.short .unamespace1 - .compile1 - 2
.short S_COMPILE3
.long 0 # flags
.short CV_CFL_AMD64 # target processor
.short 0 # frontend major
.short 0 # frontend minor
.short 0 # frontend build
.short 0 # frontend qfe
.short 0 # backend major
.short 0 # backend minor
.short 0 # backend build
.short 0 # backend qfe
.asciz "GNU AS"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.unamespace1:
.short .sbuildinfo1 - .unamespace1 - 2
.short S_UNAMESPACE
.asciz "std"
.sbuildinfo1:
.short .gproc1 - .sbuildinfo1 - 2
.short S_BUILDINFO
.long 0x1007 # type
.gproc1:
.short .frameproc1 - .gproc1 - 2
.short S_GPROC32
.long 0 # parent
.long 0 # end
.long 0 # next symbol
.long .proc1_end - proc1 # length
.long 0 # debug start offset
.long 0 # debug end offset
.long 0x1001 # type
.secrel32 proc1
.secidx proc1
.byte 0 # flags
.asciz "proc1"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.frameproc1:
.short .framecookie1 - .frameproc1 - 2
.short S_FRAMEPROC
.long 0 # frame size
.long 0 # frame padding
.long 0 # padding offset
.long 0 # size of callee-save registers
.long 0 # offset of exception handler
.short 0 # section of exception handler
.long 0 # flags
.byte 0xf2 # padding
.byte 0xf1 # padding
.framecookie1:
.short .bprel1 - .framecookie1 - 2
.short S_FRAMECOOKIE
.long 8 # frame-relative offset
.short CV_AMD64_RAX # register
.long 0 # cookie type (CV_COOKIETYPE_COPY)
.byte 0 # flags
.byte 0xf1 # padding
.bprel1:
.short .reg1 - .bprel1 - 2
.short S_BPREL32
.long 4 # BP-relative offset
.long 0x1008 # type
.asciz "foo"
.reg1:
.short .regrel1 - .reg1 - 2
.short S_REGISTER
.long 0x1008 # type
.short CV_AMD64_RAX
.asciz "bar"
.byte 0xf2 # padding
.byte 0xf1 # padding
.regrel1:
.short .local1 - .regrel1 - 2
.short S_REGREL32
.long 4 # offset
.long 0x1008 # type
.short CV_AMD64_RAX
.asciz "baz"
.byte 0xf2 # padding
.byte 0xf1 # padding
.local1:
.short .defrange1 - .local1 - 2
.short S_LOCAL
.long 0x1008 # type
.short 0 # flags
.asciz "local1"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.defrange1:
.short .local2 - .defrange1 - 2
.short S_DEFRANGE_REGISTER_REL
.short CV_AMD64_RAX
.short 0 # offset parent
.long 0 # offset register
.secrel32 .block1 # offset
.secidx .block1 # section
.short .block1_end - .block1 # length
.short .gap1 - .block1 # gap 1 offset
.short .gap1_end - .gap1 # gap 1 length
.local2:
.short .defrange2 - .local2 - 2
.short S_LOCAL
.long 0x1008 # type
.short 0 # flags
.asciz "local2"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.defrange2:
.short .local3 - .defrange2 - 2
.short S_DEFRANGE_FRAMEPOINTER_REL
.long 4 # frame pointer offset
.secrel32 .block1 # offset
.secidx .block1 # section
.short .block1_end - .block1 # length
.short .gap1 - .block1 # gap 1 offset
.short .gap1_end - .gap1 # gap 1 length
.local3:
.short .defrange3 - .local3 - 2
.short S_LOCAL
.long 0x1008 # type
.short 0 # flags
.asciz "local3"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.defrange3:
.short .local4 - .defrange3 - 2
.short S_DEFRANGE_SUBFIELD_REGISTER
.short CV_AMD64_RAX
.short 0 # attributes
.long 4 # offset in parent variable
.secrel32 .block1 # offset
.secidx .block1 # section
.short .block1_end - .block1 # length
.short .gap1 - .block1 # gap 1 offset
.short .gap1_end - .gap1 # gap 1 length
.local4:
.short .defrange4 - .local4 - 2
.short S_LOCAL
.long 0x1008 # type
.short 0 # flags
.asciz "local4"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.defrange4:
.short .local5 - .defrange4 - 2
.short S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
.long 4 # frame pointer offset
.local5:
.short .defrange5 - .local5 - 2
.short S_LOCAL
.long 0x1008 # type
.short 0 # flags
.asciz "local5"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.defrange5:
.short .inlinesite1 - .defrange5 - 2
.short S_DEFRANGE_REGISTER
.short CV_AMD64_RAX
.short 0 # attributes
.secrel32 .block1 # offset
.secidx .block1 # section
.short .block1_end - .block1 # length
.short .gap1 - .block1 # gap 1 offset
.short .gap1_end - .gap1 # gap 1 length
.inlinesite1:
.short .inlinesite1end - .inlinesite1 - 2
.short S_INLINESITE
.long 0 # parent
.long 0 # end
.long 0x1009 # inlinee (inline_func)
.inlinesite1end:
.short .sblock1 - .inlinesite1end - 2
.short S_INLINESITE_END
.sblock1:
.short .label1 - .sblock1 - 2
.short S_BLOCK32
.long 0 # parent (filled in by linker)
.long 0 # end (filled in by linker)
.long .block1_end - .block1 # length
.secrel32 .block1
.secidx .block1
.byte 0 # name
.byte 0xf1 # padding
.label1:
.short .sblock1_end - .label1 - 2
.short S_LABEL32
.secrel32 label
.secidx label
.byte 0 # flags
.asciz "label"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
.sblock1_end:
.short .thunk1 - .sblock1_end - 2
.short S_END
.thunk1:
.short .thunk1_end - .thunk1 - 2
.short S_THUNK32
.long 0 # parent
.long 0 # end
.long 0 # next
.secrel32 thunk
.secidx thunk
.short .thunk_end - thunk
.byte 0 # THUNK_ORDINAL value
.asciz "thunk"
.byte 0xf1 # padding
.thunk1_end:
.short .heapallocsite1 - .thunk1_end - 2
.short S_END
.heapallocsite1:
.short .gproc1_end - .heapallocsite1 - 2
.short S_HEAPALLOCSITE
.secrel32 .gap1_end
.secidx .gap1_end
.short .block1_end - .gap1_end
.long 0x1008 # type
.gproc1_end:
.short .syms_end - .gproc1_end - 2
.short S_END
.syms_end:
.section ".debug$T", "rn"
.long CV_SIGNATURE_C13
# Type 1000, arglist (uint32_t)
.arglist1:
.short .proctype1 - .arglist1 - 2
.short LF_ARGLIST
.long 1 # no. entries
.long T_UINT4
# Type 1001, procedure (return type T_VOID, arglist 1000)
.proctype1:
.short .string1 - .proctype1 - 2
.short LF_PROCEDURE
.long T_VOID
.byte 0 # calling convention
.byte 0 # attributes
.short 1 # no. parameters
.long 0x1000
# Type 1002, string "/tmp" (build directory)
.string1:
.short .string2 - .string1 - 2
.short LF_STRING_ID
.long 0 # sub-string
.asciz "/tmp"
.byte 0xf3 # padding
.byte 0xf2 # padding
.byte 0xf1 # padding
# Type 1003, string "gcc" (compiler)
.string2:
.short .string3 - .string2 - 2
.short LF_STRING_ID
.long 0 # sub-string
.asciz "gcc"
# Type 1004, string "tmp.c" (source file)
.string3:
.short .string4 - .string3 - 2
.short LF_STRING_ID
.long 0 # sub-string
.asciz "tmp.c"
.byte 0xf2 # padding
.byte 0xf1 # padding
# Type 1005, string "tmp.pdb" (PDB file)
.string4:
.short .string5 - .string4 - 2
.short LF_STRING_ID
.long 0 # sub-string
.asciz "tmp.pdb"
# Type 1006, string "-gcodeview" (command arguments)
.string5:
.short .buildinfo1 - .string5 - 2
.short LF_STRING_ID
.long 0 # sub-string
.asciz "-gcodeview"
.byte 0xf1 # padding
# Type 1007, build info
.buildinfo1:
.short .mod1 - .buildinfo1 - 2
.short LF_BUILDINFO
.short 5 # count
.long 0x1002 # build directory
.long 0x1003 # compiler
.long 0x1004 # source file
.long 0x1005 # PDB file
.long 0x1006 # command arguments
.byte 0xf2 # padding
.byte 0xf1 # padding
# Type 1008, const uint32_t
.mod1:
.short .funcid1 - .mod1 - 2
.short LF_MODIFIER
.long T_UINT4
.short 1 # const
.p2align 2
# Type 1009, func ID for inline_func
.funcid1:
.short .types_end - .funcid1 - 2
.short LF_FUNC_ID
.long 0 # parent scope
.long 0x1001 # type
.asciz "inline_func"
.types_end:
.text
.global proc1
proc1:
nop
.block1:
nop
label:
nop
.gap1:
nop
.gap1_end:
nop
.block1_end:
nop
.proc1_end:
thunk:
nop
.thunk_end:

View file

@ -1614,6 +1614,72 @@ proc test8 { } {
}
}
proc test9 { } {
global as
global ar
global ld
global objdump
global srcdir
global subdir
if ![ld_assemble $as $srcdir/$subdir/pdb-syms2.s tmpdir/pdb-syms2.o] {
unsupported "Build pdb-syms2.o"
return
}
if ![ld_link $ld "tmpdir/pdb-syms2.exe" "--pdb=tmpdir/pdb-syms2.pdb tmpdir/pdb-syms2.o"] {
unsupported "Create PE image with PDB file"
return
}
# get index of module stream
set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb 0003"]
if ![string match "" $exec_output] {
fail "Could not extract DBI stream"
return
} else {
pass "Extracted DBI stream"
}
set fi [open tmpdir/0003]
fconfigure $fi -translation binary
seek $fi 24
set data [read $fi 4]
binary scan $data i mod_info_size
seek $fi 36 current
set mod_info [read $fi $mod_info_size]
close $fi
binary scan [string range $mod_info 34 35] s module_index
# check module records
set index_str [format "%04x" $module_index]
set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb $index_str"]
if ![string match "" $exec_output] {
fail "Could not extract module symbols"
return
} else {
pass "Extracted module symbols"
}
set exp [file_contents "$srcdir/$subdir/pdb-syms2-symbols1.d"]
set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
if [string match $exp $got] {
pass "Correct symbols in module stream"
} else {
fail "Incorrect symbols in module stream"
}
}
test1
test2
test3
@ -1622,3 +1688,4 @@ test5
test6
test7
test8
test9