diff options
Diffstat (limited to 'libctf/ctf-open.c')
-rw-r--r-- | libctf/ctf-open.c | 206 |
1 files changed, 115 insertions, 91 deletions
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c index 9dcd274..c4fca24 100644 --- a/libctf/ctf-open.c +++ b/libctf/ctf-open.c @@ -655,7 +655,6 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) unsigned long pop[CTF_K_MAX + 1] = { 0 }; const ctf_type_t *tp; - ctf_hash_t *hp; uint32_t id, dst; uint32_t *xp; @@ -666,6 +665,8 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) int nlstructs = 0, nlunions = 0; int err; + assert (!(fp->ctf_flags & LCTF_RDWR)); + if (_libctf_unlikely_ (fp->ctf_version == CTF_VERSION_1)) { int err; @@ -717,32 +718,37 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) /* Now that we've counted up the number of each type, we can allocate the hash tables, type translation table, and pointer table. */ - if ((fp->ctf_structs = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string, - ctf_hash_eq_string)) == NULL) + if ((fp->ctf_structs.ctn_readonly + = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string, + ctf_hash_eq_string)) == NULL) return ENOMEM; - if ((fp->ctf_unions = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string, - ctf_hash_eq_string)) == NULL) + if ((fp->ctf_unions.ctn_readonly + = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string, + ctf_hash_eq_string)) == NULL) return ENOMEM; - if ((fp->ctf_enums = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string, - ctf_hash_eq_string)) == NULL) + if ((fp->ctf_enums.ctn_readonly + = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string, + ctf_hash_eq_string)) == NULL) return ENOMEM; - if ((fp->ctf_names = ctf_hash_create (pop[CTF_K_INTEGER] + - pop[CTF_K_FLOAT] + - pop[CTF_K_FUNCTION] + - pop[CTF_K_TYPEDEF] + - pop[CTF_K_POINTER] + - pop[CTF_K_VOLATILE] + - pop[CTF_K_CONST] + - pop[CTF_K_RESTRICT], - ctf_hash_string, - ctf_hash_eq_string)) == NULL) + if ((fp->ctf_names.ctn_readonly + = ctf_hash_create (pop[CTF_K_INTEGER] + + pop[CTF_K_FLOAT] + + pop[CTF_K_FUNCTION] + + pop[CTF_K_TYPEDEF] + + pop[CTF_K_POINTER] + + pop[CTF_K_VOLATILE] + + pop[CTF_K_CONST] + + pop[CTF_K_RESTRICT], + ctf_hash_string, + ctf_hash_eq_string)) == NULL) return ENOMEM; fp->ctf_txlate = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1)); - fp->ctf_ptrtab = ctf_alloc (sizeof (uint32_t) * (fp->ctf_typemax + 1)); + fp->ctf_ptrtab_len = fp->ctf_typemax + 1; + fp->ctf_ptrtab = ctf_alloc (sizeof (uint32_t) * fp->ctf_ptrtab_len); if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL) return ENOMEM; /* Memory allocation failed. */ @@ -779,10 +785,11 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) root-visible version so that we can be sure to find it when checking for conflicting definitions in ctf_add_type(). */ - if (((ctf_hash_lookup_type (fp->ctf_names, fp, name)) == 0) + if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly, + fp, name)) == 0) || (flag & CTF_ADD_ROOT)) { - err = ctf_hash_define_type (fp->ctf_names, fp, + err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); if (err != 0) @@ -797,7 +804,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_FUNCTION: - err = ctf_hash_insert_type (fp->ctf_names, fp, + err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); if (err != 0) @@ -805,7 +812,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_STRUCT: - err = ctf_hash_define_type (fp->ctf_structs, fp, + err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); @@ -817,7 +824,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_UNION: - err = ctf_hash_define_type (fp->ctf_unions, fp, + err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); @@ -829,7 +836,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_ENUM: - err = ctf_hash_define_type (fp->ctf_enums, fp, + err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); @@ -838,7 +845,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_TYPEDEF: - err = ctf_hash_insert_type (fp->ctf_names, fp, + err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); if (err != 0) @@ -846,32 +853,20 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) break; case CTF_K_FORWARD: - /* Only insert forward tags into the given hash if the type or tag - name is not already present. */ - switch (tp->ctt_type) - { - case CTF_K_STRUCT: - hp = fp->ctf_structs; - break; - case CTF_K_UNION: - hp = fp->ctf_unions; - break; - case CTF_K_ENUM: - hp = fp->ctf_enums; - break; - default: - hp = fp->ctf_structs; - } - - if (ctf_hash_lookup_type (hp, fp, name) == 0) - { - err = ctf_hash_insert_type (hp, fp, - LCTF_INDEX_TO_TYPE (fp, id, child), - tp->ctt_name); - if (err != 0) - return err; - } - break; + { + ctf_names_t *np = ctf_name_table (fp, tp->ctt_type); + /* Only insert forward tags into the given hash if the type or tag + name is not already present. */ + if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0) + { + err = ctf_hash_insert_type (np->ctn_readonly, fp, + LCTF_INDEX_TO_TYPE (fp, id, child), + tp->ctt_name); + if (err != 0) + return err; + } + break; + } case CTF_K_POINTER: /* If the type referenced by the pointer is in this CTF container, @@ -886,7 +881,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) case CTF_K_VOLATILE: case CTF_K_CONST: case CTF_K_RESTRICT: - err = ctf_hash_insert_type (fp->ctf_names, fp, + err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, LCTF_INDEX_TO_TYPE (fp, id, child), tp->ctt_name); if (err != 0) @@ -903,12 +898,14 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) } ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax); - ctf_dprintf ("%u enum names hashed\n", ctf_hash_size (fp->ctf_enums)); + ctf_dprintf ("%u enum names hashed\n", + ctf_hash_size (fp->ctf_enums.ctn_readonly)); ctf_dprintf ("%u struct names hashed (%d long)\n", - ctf_hash_size (fp->ctf_structs), nlstructs); + ctf_hash_size (fp->ctf_structs.ctn_readonly), nlstructs); ctf_dprintf ("%u union names hashed (%d long)\n", - ctf_hash_size (fp->ctf_unions), nlunions); - ctf_dprintf ("%u base type names hashed\n", ctf_hash_size (fp->ctf_names)); + ctf_hash_size (fp->ctf_unions.ctn_readonly), nlunions); + ctf_dprintf ("%u base type names hashed\n", + ctf_hash_size (fp->ctf_names.ctn_readonly)); /* Make an additional pass through the pointer table to find pointers that point to anonymous typedef nodes. If we find one, modify the pointer table @@ -921,11 +918,11 @@ init_types (ctf_file_t *fp, ctf_header_t *cth) { tp = LCTF_INDEX_TO_TYPEPTR (fp, id); - if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF && - strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0 && - LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child && - LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax) - fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst; + if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF + && strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0 + && LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child + && LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax) + fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst; } } @@ -1197,6 +1194,29 @@ flip_ctf (ctf_header_t *cth, unsigned char *buf) return flip_types (buf + cth->cth_typeoff, cth->cth_stroff - cth->cth_typeoff); } +/* Set up the ctl hashes in a ctf_file_t. Called by both writable and + non-writable dictionary initialization. */ +void ctf_set_ctl_hashes (ctf_file_t *fp) +{ + /* Initialize the ctf_lookup_by_name top-level dictionary. We keep an + array of type name prefixes and the corresponding ctf_hash to use. */ + fp->ctf_lookups[0].ctl_prefix = "struct"; + fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix); + fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs; + fp->ctf_lookups[1].ctl_prefix = "union"; + fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix); + fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions; + fp->ctf_lookups[2].ctl_prefix = "enum"; + fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix); + fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums; + fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; + fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix); + fp->ctf_lookups[3].ctl_hash = &fp->ctf_names; + fp->ctf_lookups[4].ctl_prefix = NULL; + fp->ctf_lookups[4].ctl_len = 0; + fp->ctf_lookups[4].ctl_hash = NULL; +} + /* Open a CTF file, mocking up a suitable ctf_sect. */ ctf_file_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size, @@ -1207,7 +1227,7 @@ ctf_file_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size, { return ctf_simple_open_internal (ctfsect, ctfsect_size, symsect, symsect_size, symsect_entsize, strsect, strsect_size, NULL, - errp); + 0, errp); } /* Open a CTF file, mocking up a suitable ctf_sect and overriding the external @@ -1217,7 +1237,8 @@ ctf_file_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size, const char *symsect, size_t symsect_size, size_t symsect_entsize, const char *strsect, size_t strsect_size, - ctf_dynhash_t *syn_strtab, int *errp) + ctf_dynhash_t *syn_strtab, int writable, + int *errp) { ctf_sect_t skeleton; @@ -1254,7 +1275,8 @@ ctf_file_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size, strsectp = &str_sect; } - return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab, errp); + return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab, + writable, errp); } /* Decode the specified CTF buffer and optional symbol table, and create a new @@ -1266,7 +1288,7 @@ ctf_file_t * ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, const ctf_sect_t *strsect, int *errp) { - return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, errp); + return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, 0, errp); } /* Like ctf_bufopen, but overriding the external strtab with a synthetic one. */ @@ -1274,7 +1296,7 @@ ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, ctf_file_t * ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, const ctf_sect_t *strsect, ctf_dynhash_t *syn_strtab, - int *errp) + int writable, int *errp) { const ctf_preamble_t *pp; size_t hdrsz = sizeof (ctf_header_t); @@ -1353,6 +1375,9 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, memset (fp, 0, sizeof (ctf_file_t)); + if (writable) + fp->ctf_flags |= LCTF_RDWR; + if ((fp->ctf_header = ctf_alloc (sizeof (struct ctf_header))) == NULL) { ctf_free (fp); @@ -1514,6 +1539,14 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, ctf_set_base (fp, hp, fp->ctf_base); + /* No need to do anything else for dynamic containers: they do not support + symbol lookups, and the type table is maintained in the dthashes. */ + if (fp->ctf_flags & LCTF_RDWR) + { + fp->ctf_refcnt = 1; + return fp; + } + if ((err = init_types (fp, hp)) != 0) goto bad; @@ -1537,24 +1570,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect, goto bad; } - /* Initialize the ctf_lookup_by_name top-level dictionary. We keep an - array of type name prefixes and the corresponding ctf_hash to use. - NOTE: This code must be kept in sync with the code in ctf_update(). */ - fp->ctf_lookups[0].ctl_prefix = "struct"; - fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix); - fp->ctf_lookups[0].ctl_hash = fp->ctf_structs; - fp->ctf_lookups[1].ctl_prefix = "union"; - fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix); - fp->ctf_lookups[1].ctl_hash = fp->ctf_unions; - fp->ctf_lookups[2].ctl_prefix = "enum"; - fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix); - fp->ctf_lookups[2].ctl_hash = fp->ctf_enums; - fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR; - fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix); - fp->ctf_lookups[3].ctl_hash = fp->ctf_names; - fp->ctf_lookups[4].ctl_prefix = NULL; - fp->ctf_lookups[4].ctl_len = 0; - fp->ctf_lookups[4].ctl_hash = NULL; + ctf_set_ctl_hashes (fp); if (symsect != NULL) { @@ -1607,7 +1623,20 @@ ctf_file_close (ctf_file_t *fp) ctf_dtd_delete (fp, dtd); } ctf_dynhash_destroy (fp->ctf_dthash); - ctf_dynhash_destroy (fp->ctf_dtbyname); + if (fp->ctf_flags & LCTF_RDWR) + { + ctf_dynhash_destroy (fp->ctf_structs.ctn_writable); + ctf_dynhash_destroy (fp->ctf_unions.ctn_writable); + ctf_dynhash_destroy (fp->ctf_enums.ctn_writable); + ctf_dynhash_destroy (fp->ctf_names.ctn_writable); + } + else + { + ctf_hash_destroy (fp->ctf_structs.ctn_readonly); + ctf_hash_destroy (fp->ctf_unions.ctn_readonly); + ctf_hash_destroy (fp->ctf_enums.ctn_readonly); + ctf_hash_destroy (fp->ctf_names.ctn_readonly); + } for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd) { @@ -1641,11 +1670,6 @@ ctf_file_close (ctf_file_t *fp) ctf_free (fp->ctf_txlate); ctf_free (fp->ctf_ptrtab); - ctf_hash_destroy (fp->ctf_structs); - ctf_hash_destroy (fp->ctf_unions); - ctf_hash_destroy (fp->ctf_enums); - ctf_hash_destroy (fp->ctf_names); - ctf_free (fp->ctf_header); ctf_free (fp); } @@ -1670,7 +1694,7 @@ ctf_get_arc (const ctf_file_t *fp) structure, not a pointer to it, since that is likely to become a pointer to freed data before the return value is used under the expected use case of ctf_getsect()/ ctf_file_close()/free(). */ -extern ctf_sect_t +ctf_sect_t ctf_getdatasect (const ctf_file_t *fp) { return fp->ctf_data; |