diff options
Diffstat (limited to 'libctf/ctf-open.c')
-rw-r--r-- | libctf/ctf-open.c | 140 |
1 files changed, 94 insertions, 46 deletions
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 313500c..558b13d 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -591,9 +591,13 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf) fp->ctf_provtypemax = (uint32_t) -1; /* We determine whether the dict is a child or a parent based on the value of - cth_parent_name. */ + cth_parent_name: for BTF this is not enough, because there is no + cth_parent_name: instead, we can check the first byte of the strtab, which + is always 0 for parents and never 0 for children. */ - int child = cth->cth_parent_name != 0; + int child = (cth->cth_parent_name != 0 + || (fp->ctf_str[CTF_STRTAB_0].cts_len > 0 + && fp->ctf_str[CTF_STRTAB_0].cts_strs[0] != 0)); if (fp->ctf_version < CTF_VERSION_4) { @@ -656,9 +660,6 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf) kind = LCTF_INFO_UNPREFIXED_KIND (fp, suffix->ctt_info); } - if (nonroot) - continue; - if (is_btf && kind > CTF_BTF_K_MAX) return ECTF_CORRUPT; @@ -667,24 +668,28 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf) if (vbytes < 0) return ECTF_CORRUPT; - /* For forward declarations, the kflag indicates what type to use, so bump - that population count too. For enums, vlen 0 indicates a forward, so - bump the forward population count. */ - if (kind == CTF_K_FORWARD) + if (!nonroot) { - if (CTF_INFO_KFLAG (suffix->ctt_info)) - pop[CTF_K_UNION]++; - else - pop[CTF_K_STRUCT]++; - } - else if (kind == CTF_K_ENUM && vlen == 0) - pop[CTF_K_FORWARD]++; + /* For forward declarations, the kflag indicates what type to use, so bump + that population count too. For enums, vlen 0 indicates a forward, so + bump the forward population count. */ + if (kind == CTF_K_FORWARD) + { + if (CTF_INFO_KFLAG (suffix->ctt_info)) + pop[CTF_K_UNION]++; + else + pop[CTF_K_STRUCT]++; + } + else if (kind == CTF_K_ENUM && vlen == 0) + pop[CTF_K_FORWARD]++; + + if (kind == CTF_K_ENUM || kind == CTF_K_ENUM64) + pop_enumerators += vlen; - if (kind == CTF_K_ENUM || kind == CTF_K_ENUM64) - pop_enumerators += vlen; + pop[kind]++; + } tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes); - pop[kind]++; } if (child) @@ -766,7 +771,7 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf) if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) return ENOMEM; /* Memory allocation failed. */ - if (child && cth->cth_parent_strlen != 0) + if (child || cth->cth_parent_strlen != 0) { fp->ctf_flags |= LCTF_NO_STR; return 0; @@ -819,13 +824,14 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf, uint32_t id; ctf_id_t type; - unsigned long typemax = fp->ctf_typemax; - ctf_next_t *i = NULL; void *k; int err; - int child = cth->cth_parent_name != 0; + /* See init_static_types. */ + int child = (cth->cth_parent_name != 0 + || (fp->ctf_str[CTF_STRTAB_0].cts_len > 0 + && fp->ctf_str[CTF_STRTAB_0].cts_strs[0] != 0)); tbuf = (ctf_type_t *) (fp->ctf_buf + cth->btf.bth_type_off); tend = (ctf_type_t *) ((uintptr_t) tbuf + cth->btf.bth_type_len); @@ -837,16 +843,9 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf, /* In this second pass through the types, we fill in each entry of the type and pointer tables and add names to the appropriate hashes. - (Not all names are added in this pass, only type names. See below.) - - Reset ctf_typemax and bump it 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: but higher types are - not, since their names are not yet known. (It is kept at its standard - value before this function is called so that at least some type-related - operations work. */ + (Not all names are added in this pass, only type names. See below.) */ - for (id = 1, fp->ctf_typemax = 1, tp = tbuf; tp < tend; xp++, id++, fp->ctf_typemax++) + for (id = 1, tp = tbuf; tp < tend; xp++, id++) { unsigned short kind = LCTF_KIND (fp, tp); unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info); @@ -1104,10 +1103,9 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf, } tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes); } - fp->ctf_typemax--; - assert (fp->ctf_typemax == typemax); + assert (fp->ctf_typemax == id - 1); - ctf_dprintf ("%u total types processed\n", fp->ctf_typemax); + ctf_dprintf ("%u total types processed\n", id - 1); if ((err = init_void (fp) < 0)) return err; @@ -2513,6 +2511,50 @@ ctf_symsect_endianness (ctf_dict_t *fp, int little_endian) assert (init_symtab (fp, fp->ctf_header, &fp->ctf_ext_symtab) == 0); } +/* Return the size in bytes of a given CTF section, or 0 if none. */ + +size_t +ctf_sect_size (ctf_dict_t *fp, ctf_sect_names_t sect) +{ + switch (sect) + { + case CTF_SECT_HEADER: + switch (CTH_VERSION (fp->ctf_header)) + { + case CTF_VERSION_1: + case CTF_VERSION_1_UPGRADED_3: + case CTF_VERSION_2: + return sizeof (ctf_header_v2_t); + + case CTF_VERSION_3: + return sizeof (ctf_header_v3_t); + + case CTF_VERSION_4: + default: + if (fp->ctf_opened_btf) + return sizeof (ctf_btf_header_t); + else + return sizeof (ctf_header_t); + } + case CTF_SECT_OBJT: + return fp->ctf_header->cth_objtidx_len + fp->ctf_header->cth_objt_len; + case CTF_SECT_FUNC: + return fp->ctf_header->cth_funcidx_len + fp->ctf_header->cth_func_len; + case CTF_SECT_VAR: + if (fp->ctf_v3_header) + return fp->ctf_v3_header->cth_typeoff - fp->ctf_v3_header->cth_varoff; + else + return 0; + case CTF_SECT_TYPE: + return fp->ctf_header->btf.bth_type_len; + case CTF_SECT_STR: + return fp->ctf_header->btf.bth_str_len; + default: + ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN); + return 0; + } +} + /* Return the CTF handle for the parent CTF dict, if one exists. Otherwise return NULL to indicate this dict has no imported parent. */ ctf_dict_t * @@ -2579,8 +2621,6 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed) ctf_dict_t *old_parent = fp->ctf_parent; const char *old_parent_name = fp->ctf_parent_name; int old_unreffed = fp->ctf_parent_unreffed; - int is_btf = 0; - size_t expected_prov_strings = 0; if (pfp == NULL || pfp == fp->ctf_parent) return 0; @@ -2627,7 +2667,10 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed) { /* If we are importing into a parent dict, the child dict had better be empty. Set its starting type ID, which need not be zero: the - parent can already have types. */ + parent can already have types. We assign typemax rather than + idmax because when this is a new dict we want the types to count + up from the number of types currently in the parent, not the number + in the parent when it was opened. */ if (fp->ctf_typemax != 0) { @@ -2637,19 +2680,19 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed) return (ctf_set_errno (fp, EINVAL)); } fp->ctf_header->cth_parent_ntypes = pfp->ctf_typemax; - - /* We expect one provisional string in this new dict, for the name of - the (non-reffed, non-written-out) void type. */ - expected_prov_strings++; } } /* No importing dicts with provisional strings in (except for the void one added to all new dicts). We might in time be able to lift this restriction, but it is unlikely to be something anyone would want to do, so - let's not bother for now. */ + let's not bother for now. If we have a system-created void type, it might + have instantiated a new string. */ - if (ctf_dynhash_elements (fp->ctf_prov_strtab) != expected_prov_strings) + if ((fp->ctf_void_type == NULL + && ctf_dynhash_elements (fp->ctf_prov_strtab) != 0) + || (fp->ctf_void_type != NULL + && ctf_dynhash_elements (fp->ctf_prov_strtab) > 1)) { ctf_err_warn (fp, 0, EINVAL, _("ctf_import: child dict already has %zi strings, cannot import"), @@ -2673,6 +2716,12 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed) fp->ctf_parent_unreffed = unreffed; fp->ctf_parent = pfp; + /* BTF dicts don't have any parent strlen in the header, but we need to know + it to dereference strings. */ + + if (fp->ctf_opened_btf) + fp->ctf_header->cth_parent_strlen = pfp->ctf_str[CTF_STRTAB_0].cts_len; + /* If this is a dict that hasn't previously allowed string lookups, we can allow them now, and finish initialization. (This requires us to figure out whether the buffer contains pure BTF or not: we can do that by @@ -2681,9 +2730,8 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed) fp->ctf_flags |= LCTF_CHILD; fp->ctf_flags &= ~LCTF_NO_STR; - is_btf = CTH_MAGIC (fp->ctf_header) != CTFv4_MAGIC; if (no_strings && (err = init_static_types_names (fp, fp->ctf_header, - is_btf) < 0)) + fp->ctf_opened_btf) < 0)) { /* Undo everything other than cache flushing. */ |