diff options
Diffstat (limited to 'libctf/ctf-open.c')
-rw-r--r-- | libctf/ctf-open.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 2945228..87b0f74 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -685,6 +685,7 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) const ctf_type_t *tp; uint32_t id; uint32_t *xp; + unsigned long typemax = 0; /* We determine whether the dict is a child or a parent based on the value of cth_parname. */ @@ -708,7 +709,7 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) /* We make two passes through the entire type section. In this first pass, we count the number of each type and the total number of types. */ - for (tp = tbuf; tp < tend; fp->ctf_typemax++) + for (tp = tbuf; tp < tend; typemax++) { unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info); unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info); @@ -769,8 +770,8 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) ctf_hash_eq_string, NULL, NULL)) == NULL) return ENOMEM; - fp->ctf_txlate = malloc (sizeof (uint32_t) * (fp->ctf_typemax + 1)); - fp->ctf_ptrtab_len = fp->ctf_typemax + 1; + fp->ctf_txlate = malloc (sizeof (uint32_t) * (typemax + 1)); + fp->ctf_ptrtab_len = typemax + 1; fp->ctf_ptrtab = malloc (sizeof (uint32_t) * fp->ctf_ptrtab_len); if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) @@ -779,13 +780,17 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) xp = fp->ctf_txlate; *xp++ = 0; /* Type id 0 is used as a sentinel value. */ - memset (fp->ctf_txlate, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1)); - memset (fp->ctf_ptrtab, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1)); + memset (fp->ctf_txlate, 0, sizeof (uint32_t) * (typemax + 1)); + memset (fp->ctf_ptrtab, 0, sizeof (uint32_t) * (typemax + 1)); /* In the second pass through the types, we fill in each entry of the - type and pointer tables and add names to the appropriate hashes. */ + type and pointer tables and add names to the appropriate hashes. - for (id = 1, tp = tbuf; tp < tend; xp++, id++) + Bump ctf_typemax as we go, but keep it one higher than normal, so that + the type being read in is considered a valid type and it is at least + barely possible to run simple lookups on it. */ + + for (id = 1, fp->ctf_typemax = 1, tp = tbuf; tp < tend; xp++, id++, fp->ctf_typemax++) { unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info); unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info); @@ -799,27 +804,47 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) /* Cannot fail: shielded by call in loop above. */ vbytes = LCTF_VBYTES (fp, kind, size, vlen); + *xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf); + switch (kind) { case CTF_K_UNKNOWN: case CTF_K_INTEGER: case CTF_K_FLOAT: - /* Names are reused by bit-fields, which are differentiated by their - encodings, and so typically we'd record only the first instance of - a given intrinsic. However, we replace an existing type with a - root-visible version so that we can be sure to find it when - checking for conflicting definitions in ctf_add_type(). */ - - if (((ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0) - || isroot) - { - err = ctf_dynhash_insert_type (fp, fp->ctf_names, - LCTF_INDEX_TO_TYPE (fp, id, child), - tp->ctt_name); - if (err != 0) - return err; - } - break; + { + ctf_id_t existing; + ctf_encoding_t existing_en; + ctf_encoding_t this_en; + + if (!isroot) + break; + + /* Names are reused by bitfields, which are differentiated by + their encodings. So check for the type already existing, and + iff the new type is a root-visible non-bitfield, replace the + old one. It's a little hard to figure out whether a type is + a non-bitfield without already knowing that type's native + width, but we can converge on it by replacing an existing + type as long as the new type is zero-offset and has a + bit-width wider than the existing one, since the native type + must necessarily have a bit-width at least as wide as any + bitfield based on it. */ + + if (((existing = ctf_dynhash_lookup_type (fp->ctf_names, name)) == 0) + || ctf_type_encoding (fp, existing, &existing_en) != 0 + || (ctf_type_encoding (fp, LCTF_INDEX_TO_TYPE (fp, id, child), &this_en) == 0 + && this_en.cte_offset == 0 + && (existing_en.cte_offset != 0 + || existing_en.cte_bits < this_en.cte_bits))) + { + err = ctf_dynhash_insert_type (fp, fp->ctf_names, + LCTF_INDEX_TO_TYPE (fp, id, child), + tp->ctt_name); + if (err != 0) + return err; + } + break; + } /* These kinds have no name, so do not need interning into any hashtables. */ @@ -938,10 +963,10 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth) _("init_static_types(): unhandled CTF kind: %x"), kind); return ECTF_CORRUPT; } - - *xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf); tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes); } + fp->ctf_typemax--; + assert (fp->ctf_typemax == typemax); ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax); ctf_dprintf ("%zu enum names hashed\n", |