summaryrefslogtreecommitdiff
path: root/ld/pdb.c
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2022-12-09 01:52:36 +0000
committerAlan Modra <amodra@gmail.com>2022-12-23 20:13:31 +1030
commitfca9096a94ff6b3dbf0bf71fc402b3b37184a235 (patch)
tree2cd44173d9b5e8334ce5ab76f261837ea4a9cfc6 /ld/pdb.c
parentd5b4c0ddb9afaac5d5f741da4a863a4a71992969 (diff)
ld: Write types into IPI stream of PDB
Diffstat (limited to 'ld/pdb.c')
-rw-r--r--ld/pdb.c204
1 files changed, 187 insertions, 17 deletions
diff --git a/ld/pdb.c b/ld/pdb.c
index 535ea1d46ab..d5819723a2b 100644
--- a/ld/pdb.c
+++ b/ld/pdb.c
@@ -1124,13 +1124,16 @@ is_name_anonymous (char *name, size_t len)
already seen add it to types (for TPI types) or ids (for IPI types). */
static bool
handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
- uint32_t num_types, struct types *types)
+ uint32_t num_types, struct types *types,
+ struct types *ids)
{
uint16_t size, type;
void **slot;
hashval_t hash;
bool other_hash = false;
uint32_t cv_hash;
+ struct types *t;
+ bool ipi = false;
size = bfd_getl16 (data) + sizeof (uint16_t);
type = bfd_getl16 (data + sizeof (uint16_t));
@@ -1911,6 +1914,168 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
/* Does not reference any types, nothing to be done. */
break;
+ case LF_STRING_ID:
+ {
+ struct lf_string_id *str = (struct lf_string_id *) data;
+ size_t string_len;
+
+ if (size < offsetof (struct lf_string_id, string))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_STRING_ID\n"));
+ return false;
+ }
+
+ if (!remap_type (&str->substring, map, type_num, num_types))
+ return false;
+
+ string_len = strnlen (str->string,
+ size - offsetof (struct lf_string_id, string));
+
+ if (string_len == size - offsetof (struct lf_string_id, string))
+ {
+ einfo (_("%P: warning: string for LF_STRING_ID has no"
+ " terminating zero\n"));
+ return false;
+ }
+
+ ipi = true;
+
+ break;
+ }
+
+ case LF_SUBSTR_LIST:
+ {
+ uint32_t num_entries;
+ struct lf_arglist *ssl = (struct lf_arglist *) data;
+
+ if (size < offsetof (struct lf_arglist, args))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_SUBSTR_LIST\n"));
+ return false;
+ }
+
+ num_entries = bfd_getl32 (&ssl->num_entries);
+
+ if (size < offsetof (struct lf_arglist, args)
+ + (num_entries * sizeof (uint32_t)))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_SUBSTR_LIST\n"));
+ return false;
+ }
+
+ for (uint32_t i = 0; i < num_entries; i++)
+ {
+ if (!remap_type (&ssl->args[i], map, type_num, num_types))
+ return false;
+ }
+
+ ipi = true;
+
+ break;
+ }
+
+ case LF_BUILDINFO:
+ {
+ uint16_t num_entries;
+ struct lf_build_info *bi = (struct lf_build_info *) data;
+
+ if (size < offsetof (struct lf_build_info, strings))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_BUILDINFO\n"));
+ return false;
+ }
+
+ num_entries = bfd_getl16 (&bi->count);
+
+ if (size < offsetof (struct lf_build_info, strings)
+ + (num_entries * sizeof (uint32_t)))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_BUILDINFO\n"));
+ return false;
+ }
+
+ for (uint32_t i = 0; i < num_entries; i++)
+ {
+ if (!remap_type (&bi->strings[i], map, type_num, num_types))
+ return false;
+ }
+
+ ipi = true;
+
+ break;
+ }
+
+ case LF_FUNC_ID:
+ {
+ struct lf_func_id *func = (struct lf_func_id *) data;
+ size_t name_len;
+
+ if (size < offsetof (struct lf_func_id, name))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_FUNC_ID\n"));
+ return false;
+ }
+
+ if (!remap_type (&func->parent_scope, map, type_num, num_types))
+ return false;
+
+ if (!remap_type (&func->function_type, map, type_num, num_types))
+ return false;
+
+ name_len = strnlen (func->name,
+ size - offsetof (struct lf_func_id, name));
+
+ if (name_len == size - offsetof (struct lf_func_id, name))
+ {
+ einfo (_("%P: warning: string for LF_FUNC_ID has no"
+ " terminating zero\n"));
+ return false;
+ }
+
+ ipi = true;
+
+ break;
+ }
+
+ case LF_MFUNC_ID:
+ {
+ struct lf_mfunc_id *mfunc = (struct lf_mfunc_id *) data;
+ size_t name_len;
+
+ if (size < offsetof (struct lf_mfunc_id, name))
+ {
+ einfo (_("%P: warning: truncated CodeView type record"
+ " LF_MFUNC_ID\n"));
+ return false;
+ }
+
+ if (!remap_type (&mfunc->parent_type, map, type_num, num_types))
+ return false;
+
+ if (!remap_type (&mfunc->function_type, map, type_num, num_types))
+ return false;
+
+ name_len = strnlen (mfunc->name,
+ size - offsetof (struct lf_mfunc_id, name));
+
+ if (name_len == size - offsetof (struct lf_mfunc_id, name))
+ {
+ einfo (_("%P: warning: string for LF_MFUNC_ID has no"
+ " terminating zero\n"));
+ return false;
+ }
+
+ ipi = true;
+
+ break;
+ }
+
default:
einfo (_("%P: warning: unrecognized CodeView type %v\n"), type);
return false;
@@ -1918,7 +2083,9 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
hash = iterative_hash (data, size, 0);
- slot = htab_find_slot_with_hash (types->hashmap, data, hash, INSERT);
+ t = ipi ? ids : types;
+
+ slot = htab_find_slot_with_hash (t->hashmap, data, hash, INSERT);
if (!slot)
return false;
@@ -1931,7 +2098,7 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
e = (struct type_entry *) *slot;
e->next = NULL;
- e->index = types->num_types;
+ e->index = t->num_types;
if (other_hash)
e->cv_hash = cv_hash;
@@ -1940,16 +2107,16 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
memcpy (e->data, data, size);
- if (types->last)
- types->last->next = e;
+ if (t->last)
+ t->last->next = e;
else
- types->first = e;
+ t->first = e;
- types->last = e;
+ t->last = e;
map[type_num] = e;
- types->num_types++;
+ t->num_types++;
}
else /* duplicate */
{
@@ -1962,7 +2129,8 @@ handle_type (uint8_t *data, struct type_entry **map, uint32_t type_num,
/* Parse the .debug$T section of a module, and pass any type definitions
found to handle_type. */
static bool
-handle_debugt_section (asection *s, bfd *mod, struct types *types)
+handle_debugt_section (asection *s, bfd *mod, struct types *types,
+ struct types *ids)
{
bfd_byte *data = NULL;
size_t off;
@@ -2019,7 +2187,7 @@ handle_debugt_section (asection *s, bfd *mod, struct types *types)
size = bfd_getl16 (data + off);
- if (!handle_type (data + off, map, type_num, num_types, types))
+ if (!handle_type (data + off, map, type_num, num_types, types, ids))
{
free (data);
free (map);
@@ -2044,7 +2212,8 @@ 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,
- bfd *abfd, struct types *types)
+ bfd *abfd, struct types *types,
+ struct types *ids)
{
uint8_t int_buf[sizeof (uint32_t)];
uint8_t *c13_info = NULL;
@@ -2068,7 +2237,7 @@ populate_module_stream (bfd *stream, bfd *mod, uint32_t *sym_byte_size,
}
else if (!strcmp (s->name, ".debug$T") && s->size >= sizeof (uint32_t))
{
- if (!handle_debugt_section (s, mod, types))
+ if (!handle_debugt_section (s, mod, types, ids))
{
free (c13_info);
free (mod_source->files);
@@ -2113,7 +2282,7 @@ static bool
create_module_info_substream (bfd *abfd, bfd *pdb, void **data,
uint32_t *size, struct string_table *strings,
struct source_files_info *source,
- struct types *types)
+ struct types *types, struct types *ids)
{
uint8_t *ptr;
unsigned int mod_num;
@@ -2202,7 +2371,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], abfd,
- types))
+ types, ids))
{
for (unsigned int i = 0; i < source->mod_count; i++)
{
@@ -2525,7 +2694,8 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb,
uint16_t sym_rec_stream_num,
uint16_t publics_stream_num,
struct string_table *strings,
- struct types *types)
+ struct types *types,
+ struct types *ids)
{
struct pdb_dbi_stream_header h;
struct optional_dbg_header opt;
@@ -2537,7 +2707,7 @@ populate_dbi_stream (bfd *stream, bfd *abfd, bfd *pdb,
source.mods = NULL;
if (!create_module_info_substream (abfd, pdb, &mod_info, &mod_info_size,
- strings, &source, types))
+ strings, &source, types, ids))
return false;
if (!create_section_contrib_substream (abfd, &sc, &sc_size))
@@ -3210,7 +3380,7 @@ create_pdb_file (bfd *abfd, const char *pdb_name, const unsigned char *guid)
if (!populate_dbi_stream (dbi_stream, abfd, pdb, section_header_stream_num,
sym_rec_stream_num, publics_stream_num,
- &strings, &types))
+ &strings, &types, &ids))
{
einfo (_("%P: warning: cannot populate DBI stream "
"in PDB file: %E\n"));