ld: Copy other symbols into PDB file
This commit is contained in:
parent
81814b6f5b
commit
5d9c033689
5 changed files with 1076 additions and 0 deletions
362
ld/pdb.c
362
ld/pdb.c
|
@ -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 (®->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
179
ld/pdb.h
|
@ -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
|
||||
|
|
38
ld/testsuite/ld-pe/pdb-syms2-symbols1.d
Normal file
38
ld/testsuite/ld-pe/pdb-syms2-symbols1.d
Normal 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 ................
|
430
ld/testsuite/ld-pe/pdb-syms2.s
Normal file
430
ld/testsuite/ld-pe/pdb-syms2.s
Normal 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:
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue