binutils-gdb/libctf/ctf-create.c

3138 lines
91 KiB
C
Raw Normal View History

libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* CTF file creation.
Copyright (C) 2019-2021 Free Software Foundation, Inc.
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
This file is part of libctf.
libctf is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not see
<http://www.gnu.org/licenses/>. */
#include <ctf-impl.h>
#include <sys/param.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
#include <zlib.h>
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
#include <elf.h>
#include "elf-bfd.h"
#ifndef EOVERFLOW
#define EOVERFLOW ERANGE
#endif
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
#ifndef roundup
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#endif
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
/* Make sure the ptrtab has enough space for at least one more type.
We start with 4KiB of ptrtab, enough for a thousand types, then grow it 25%
at a time. */
static int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_grow_ptrtab (ctf_dict_t *fp)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
{
size_t new_ptrtab_len = fp->ctf_ptrtab_len;
/* We allocate one more ptrtab entry than we need, for the initial zero,
plus one because the caller will probably allocate a new type. */
if (fp->ctf_ptrtab == NULL)
new_ptrtab_len = 1024;
else if ((fp->ctf_typemax + 2) > fp->ctf_ptrtab_len)
new_ptrtab_len = fp->ctf_ptrtab_len * 1.25;
if (new_ptrtab_len != fp->ctf_ptrtab_len)
{
uint32_t *new_ptrtab;
if ((new_ptrtab = realloc (fp->ctf_ptrtab,
new_ptrtab_len * sizeof (uint32_t))) == NULL)
return (ctf_set_errno (fp, ENOMEM));
fp->ctf_ptrtab = new_ptrtab;
memset (fp->ctf_ptrtab + fp->ctf_ptrtab_len, 0,
(new_ptrtab_len - fp->ctf_ptrtab_len) * sizeof (uint32_t));
fp->ctf_ptrtab_len = new_ptrtab_len;
}
return 0;
}
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* To create an empty CTF dict, we just declare a zeroed header and call
ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new dict r/w and
initialize the dynamic members. We start assigning type IDs at 1 because
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
type ID 0 is used as a sentinel and a not-found indicator. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_create (int *errp)
{
static const ctf_header_t hdr = { .cth_preamble = { CTF_MAGIC, CTF_VERSION, 0 } };
ctf_dynhash_t *dthash;
ctf_dynhash_t *dvhash;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
ctf_dynhash_t *structs = NULL, *unions = NULL, *enums = NULL, *names = NULL;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
ctf_dynhash_t *objthash = NULL, *funchash = NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_sect_t cts;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf_init_debug();
dthash = ctf_dynhash_create (ctf_hash_integer, ctf_hash_eq_integer,
NULL, NULL);
if (dthash == NULL)
{
ctf_set_open_errno (errp, EAGAIN);
goto err;
}
dvhash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
if (dvhash == NULL)
{
ctf_set_open_errno (errp, EAGAIN);
goto err_dt;
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
structs = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
unions = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
enums = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
names = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL);
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
objthash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
funchash = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
free, NULL);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (!structs || !unions || !enums || !names)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_set_open_errno (errp, EAGAIN);
goto err_dv;
}
cts.cts_name = _CTF_SECTION;
cts.cts_data = &hdr;
cts.cts_size = sizeof (hdr);
cts.cts_entsize = 1;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((fp = ctf_bufopen_internal (&cts, NULL, NULL, NULL, 1, errp)) == NULL)
goto err_dv;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
fp->ctf_structs.ctn_writable = structs;
fp->ctf_unions.ctn_writable = unions;
fp->ctf_enums.ctn_writable = enums;
fp->ctf_names.ctn_writable = names;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
fp->ctf_objthash = objthash;
fp->ctf_funchash = funchash;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_dthash = dthash;
fp->ctf_dvhash = dvhash;
fp->ctf_dtoldid = 0;
fp->ctf_snapshots = 1;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_snapshot_lu = 0;
fp->ctf_flags |= LCTF_DIRTY;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
ctf_set_ctl_hashes (fp);
ctf_setmodel (fp, CTF_MODEL_NATIVE);
if (ctf_grow_ptrtab (fp) < 0)
{
ctf_set_open_errno (errp, ctf_errno (fp));
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_close (fp);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return NULL;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return fp;
err_dv:
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
ctf_dynhash_destroy (structs);
ctf_dynhash_destroy (unions);
ctf_dynhash_destroy (enums);
ctf_dynhash_destroy (names);
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
ctf_dynhash_destroy (objthash);
ctf_dynhash_destroy (funchash);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_dynhash_destroy (dvhash);
err_dt:
ctf_dynhash_destroy (dthash);
err:
return NULL;
}
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
/* Delete data symbols that have been assigned names from the variable section.
Must be called from within ctf_serialize, because that is the only place
you can safely delete variables without messing up ctf_rollback. */
static int
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
symtypetab_delete_nonstatic_vars (ctf_dict_t *fp, ctf_dict_t *symfp)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
{
ctf_dvdef_t *dvd, *nvd;
ctf_id_t type;
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
nvd = ctf_list_next (dvd);
if (((type = (ctf_id_t) (uintptr_t)
ctf_dynhash_lookup (fp->ctf_objthash, dvd->dvd_name)) > 0)
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
&& ctf_dynhash_lookup (symfp->ctf_dynsyms, dvd->dvd_name) != NULL
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
&& type == dvd->dvd_type)
ctf_dvd_delete (fp, dvd);
}
return 0;
}
/* Determine if a symbol is "skippable" and should never appear in the
symtypetab sections. */
int
ctf_symtab_skippable (ctf_link_sym_t *sym)
{
/* Never skip symbols whose name is not yet known. */
if (sym->st_nameidx_set)
return 0;
return (sym->st_name == NULL || sym->st_name[0] == 0
|| sym->st_shndx == SHN_UNDEF
|| strcmp (sym->st_name, "_START_") == 0
|| strcmp (sym->st_name, "_END_") == 0
|| (sym->st_type == STT_OBJECT && sym->st_shndx == SHN_EXTABS
&& sym->st_value == 0));
}
/* Symtypetab emission flags. */
#define CTF_SYMTYPETAB_EMIT_FUNCTION 0x1
#define CTF_SYMTYPETAB_EMIT_PAD 0x2
#define CTF_SYMTYPETAB_FORCE_INDEXED 0x4
/* Get the number of symbols in a symbol hash, the count of symbols, the maximum
seen, the eventual size, without any padding elements, of the func/data and
(if generated) index sections, and the size of accumulated padding elements.
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
The linker-reported set of symbols is found in SYMFP: it may be NULL if
symbol filtering is not desired, in which case CTF_SYMTYPETAB_FORCE_INDEXED
will always be set in the flags.
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
Also figure out if any symbols need to be moved to the variable section, and
add them (if not already present). */
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
_libctf_nonnull_ ((1,3,4,5,6,7,8))
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
static int
symtypetab_density (ctf_dict_t *fp, ctf_dict_t *symfp, ctf_dynhash_t *symhash,
size_t *count, size_t *max, size_t *unpadsize,
size_t *padsize, size_t *idxsize, int flags)
{
ctf_next_t *i = NULL;
const void *name;
const void *ctf_sym;
ctf_dynhash_t *linker_known = NULL;
int err;
int beyond_max = 0;
*count = 0;
*max = 0;
*unpadsize = 0;
*idxsize = 0;
*padsize = 0;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
/* Make a dynhash citing only symbols reported by the linker of the
appropriate type, then traverse all potential-symbols we know the types
of, removing them from linker_known as we go. Once this is done, the
only symbols remaining in linker_known are symbols we don't know the
types of: we must emit pads for those symbols that are below the
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
maximum symbol we will emit (any beyond that are simply skipped).
If there are none, this symtypetab will be empty: just report that. */
if (!symfp->ctf_dynsyms)
return 0;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
if ((linker_known = ctf_dynhash_create (ctf_hash_string, ctf_hash_eq_string,
NULL, NULL)) == NULL)
return (ctf_set_errno (fp, ENOMEM));
while ((err = ctf_dynhash_cnext (symfp->ctf_dynsyms, &i,
&name, &ctf_sym)) == 0)
{
ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym;
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_OBJECT))
continue;
if (ctf_symtab_skippable (sym))
continue;
/* This should only be true briefly before all the names are
finalized, long before we get this far. */
if (!ctf_assert (fp, !sym->st_nameidx_set))
return -1; /* errno is set for us. */
if (ctf_dynhash_cinsert (linker_known, name, ctf_sym) < 0)
{
ctf_dynhash_destroy (linker_known);
return (ctf_set_errno (fp, ENOMEM));
}
}
if (err != ECTF_NEXT_END)
{
ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols during "
"serialization"));
ctf_dynhash_destroy (linker_known);
return (ctf_set_errno (fp, err));
}
}
while ((err = ctf_dynhash_cnext (symhash, &i, &name, NULL)) == 0)
{
ctf_link_sym_t *sym;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
/* Linker did not report symbol in symtab. Remove it from the
set of known data symbols and continue. */
if ((sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, name)) == NULL)
{
ctf_dynhash_remove (symhash, name);
continue;
}
/* We don't remove skippable symbols from the symhash because we don't
want them to be migrated into variables. */
if (ctf_symtab_skippable (sym))
continue;
if ((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_FUNC)
{
ctf_err_warn (fp, 1, 0, _("Symbol %x added to CTF as a function "
"but is of type %x\n"),
sym->st_symidx, sym->st_type);
ctf_dynhash_remove (symhash, name);
continue;
}
else if (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& sym->st_type != STT_OBJECT)
{
ctf_err_warn (fp, 1, 0, _("Symbol %x added to CTF as a data "
"object but is of type %x\n"),
sym->st_symidx, sym->st_type);
ctf_dynhash_remove (symhash, name);
continue;
}
ctf_dynhash_remove (linker_known, name);
}
*unpadsize += sizeof (uint32_t);
(*count)++;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
if (*max < sym->st_symidx)
*max = sym->st_symidx;
}
else
(*max)++;
}
if (err != ECTF_NEXT_END)
{
ctf_err_warn (fp, 0, err, _("iterating over CTF symtypetab during "
"serialization"));
ctf_dynhash_destroy (linker_known);
return (ctf_set_errno (fp, err));
}
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
while ((err = ctf_dynhash_cnext (linker_known, &i, NULL, &ctf_sym)) == 0)
{
ctf_link_sym_t *sym = (ctf_link_sym_t *) ctf_sym;
if (sym->st_symidx > *max)
beyond_max++;
}
if (err != ECTF_NEXT_END)
{
ctf_err_warn (fp, 0, err, _("iterating over linker-known symbols "
"during CTF serialization"));
ctf_dynhash_destroy (linker_known);
return (ctf_set_errno (fp, err));
}
}
*idxsize = *count * sizeof (uint32_t);
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
*padsize = (ctf_dynhash_elements (linker_known) - beyond_max) * sizeof (uint32_t);
ctf_dynhash_destroy (linker_known);
return 0;
}
/* Emit an objt or func symtypetab into DP in a particular order defined by an
array of ctf_link_sym_t or symbol names passed in. The index has NIDX
elements in it: unindexed output would terminate at symbol OUTMAX and is in
any case no larger than SIZE bytes. Some index elements are expected to be
skipped: see symtypetab_density. The linker-reported set of symbols (if any)
is found in SYMFP. */
static int
emit_symtypetab (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
ctf_link_sym_t **idx, const char **nameidx, uint32_t nidx,
uint32_t outmax, int size, int flags)
{
uint32_t i;
uint32_t *dpp = dp;
ctf_dynhash_t *symhash;
ctf_dprintf ("Emitting table of size %i, outmax %u, %u symtypetab entries, "
"flags %i\n", size, outmax, nidx, flags);
/* Empty table? Nothing to do. */
if (size == 0)
return 0;
if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
symhash = fp->ctf_funchash;
else
symhash = fp->ctf_objthash;
for (i = 0; i < nidx; i++)
{
const char *sym_name;
void *type;
/* If we have a linker-reported set of symbols, we may be given that set
to work from, or a set of symbol names. In both cases we want to look
at the corresponding linker-reported symbol (if any). */
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
ctf_link_sym_t *this_link_sym;
if (idx)
this_link_sym = idx[i];
else
this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, nameidx[i]);
/* Unreported symbol number. No pad, no nothing. */
if (!this_link_sym)
continue;
/* Symbol of the wrong type, or skippable? This symbol is not in this
table. */
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_OBJECT))
continue;
if (ctf_symtab_skippable (this_link_sym))
continue;
sym_name = this_link_sym->st_name;
/* Linker reports symbol of a different type to the symbol we actually
added? Skip the symbol. No pad, since the symbol doesn't actually
belong in this table at all. (Warned about in
symtypetab_density.) */
if ((this_link_sym->st_type == STT_FUNC)
&& (ctf_dynhash_lookup (fp->ctf_objthash, sym_name)))
continue;
if ((this_link_sym->st_type == STT_OBJECT)
&& (ctf_dynhash_lookup (fp->ctf_funchash, sym_name)))
continue;
}
else
sym_name = nameidx[i];
/* Symbol in index but no type set? Silently skip and (optionally)
pad. (In force-indexed mode, this is also where we track symbols of
the wrong type for this round of insertion.) */
if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL)
{
if (flags & CTF_SYMTYPETAB_EMIT_PAD)
*dpp++ = 0;
continue;
}
if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) < size))
return -1; /* errno is set for us. */
*dpp++ = (ctf_id_t) (uintptr_t) type;
/* When emitting unindexed output, all later symbols are pads: stop
early. */
if ((flags & CTF_SYMTYPETAB_EMIT_PAD) && idx[i]->st_symidx == outmax)
break;
}
return 0;
}
/* Emit an objt or func symtypetab index into DP in a paticular order defined by
an array of symbol names passed in. Stop at NIDX. The linker-reported set
of symbols (if any) is found in SYMFP. */
static int
emit_symtypetab_index (ctf_dict_t *fp, ctf_dict_t *symfp, uint32_t *dp,
const char **idx, uint32_t nidx, int size, int flags)
{
uint32_t i;
uint32_t *dpp = dp;
ctf_dynhash_t *symhash;
ctf_dprintf ("Emitting index of size %i, %u entries reported by linker, "
"flags %i\n", size, nidx, flags);
/* Empty table? Nothing to do. */
if (size == 0)
return 0;
if (flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
symhash = fp->ctf_funchash;
else
symhash = fp->ctf_objthash;
/* Indexes should always be unpadded. */
if (!ctf_assert (fp, !(flags & CTF_SYMTYPETAB_EMIT_PAD)))
return -1; /* errno is set for us. */
for (i = 0; i < nidx; i++)
{
const char *sym_name;
void *type;
if (!(flags & CTF_SYMTYPETAB_FORCE_INDEXED))
{
ctf_link_sym_t *this_link_sym;
this_link_sym = ctf_dynhash_lookup (symfp->ctf_dynsyms, idx[i]);
/* This is an index: unreported symbols should never appear in it. */
if (!ctf_assert (fp, this_link_sym != NULL))
return -1; /* errno is set for us. */
/* Symbol of the wrong type, or skippable? This symbol is not in this
table. */
if (((flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_FUNC)
|| (!(flags & CTF_SYMTYPETAB_EMIT_FUNCTION)
&& this_link_sym->st_type != STT_OBJECT))
continue;
if (ctf_symtab_skippable (this_link_sym))
continue;
sym_name = this_link_sym->st_name;
/* Linker reports symbol of a different type to the symbol we actually
added? Skip the symbol. */
if ((this_link_sym->st_type == STT_FUNC)
&& (ctf_dynhash_lookup (fp->ctf_objthash, sym_name)))
continue;
if ((this_link_sym->st_type == STT_OBJECT)
&& (ctf_dynhash_lookup (fp->ctf_funchash, sym_name)))
continue;
}
else
sym_name = idx[i];
/* Symbol in index and reported by linker, but no type set? Silently skip
and (optionally) pad. (In force-indexed mode, this is also where we
track symbols of the wrong type for this round of insertion.) */
if ((type = ctf_dynhash_lookup (symhash, sym_name)) == NULL)
continue;
ctf_str_add_ref (fp, sym_name, dpp++);
if (!ctf_assert (fp, (((char *) dpp) - (char *) dp) <= size))
return -1; /* errno is set for us. */
}
return 0;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
static unsigned char *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_copy_smembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
ctf_member_t ctm;
for (; dmd != NULL; dmd = ctf_list_next (dmd))
{
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_member_t *copied;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctm.ctm_name = 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctm.ctm_type = (uint32_t) dmd->dmd_type;
ctm.ctm_offset = (uint32_t) dmd->dmd_offset;
memcpy (t, &ctm, sizeof (ctm));
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
copied = (ctf_member_t *) t;
if (dmd->dmd_name)
ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctm_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
t += sizeof (ctm);
}
return t;
}
static unsigned char *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_copy_lmembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
ctf_lmember_t ctlm;
for (; dmd != NULL; dmd = ctf_list_next (dmd))
{
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_lmember_t *copied;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctlm.ctlm_name = 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctlm.ctlm_type = (uint32_t) dmd->dmd_type;
ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset);
ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset);
memcpy (t, &ctlm, sizeof (ctlm));
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
copied = (ctf_lmember_t *) t;
if (dmd->dmd_name)
ctf_str_add_ref (fp, dmd->dmd_name, &copied->ctlm_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
t += sizeof (ctlm);
}
return t;
}
static unsigned char *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_copy_emembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
ctf_enum_t cte;
for (; dmd != NULL; dmd = ctf_list_next (dmd))
{
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_enum_t *copied;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
cte.cte_value = dmd->dmd_value;
memcpy (t, &cte, sizeof (cte));
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
copied = (ctf_enum_t *) t;
ctf_str_add_ref (fp, dmd->dmd_name, &copied->cte_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
t += sizeof (cte);
}
return t;
}
/* Sort a newly-constructed static variable array. */
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
typedef struct ctf_sort_var_arg_cb
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *fp;
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
ctf_strs_t *strtab;
} ctf_sort_var_arg_cb_t;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
static int
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
ctf_sort_var (const void *one_, const void *two_, void *arg_)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
const ctf_varent_t *one = one_;
const ctf_varent_t *two = two_;
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
ctf_sort_var_arg_cb_t *arg = arg_;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
return (strcmp (ctf_strraw_explicit (arg->fp, one->ctv_name, arg->strtab),
ctf_strraw_explicit (arg->fp, two->ctv_name, arg->strtab)));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
/* Compatibility: just update the threshold for ctf_discard. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_update (ctf_dict_t *fp)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
{
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
fp->ctf_dtoldid = fp->ctf_typemax;
return 0;
}
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* If the specified CTF dict is writable and has been modified, reload this dict
with the updated type definitions, ready for serialization. In order to make
this code and the rest of libctf as simple as possible, we perform updates by
taking the dynamic type definitions and creating an in-memory CTF dict
containing the definitions, and then call ctf_simple_open_internal() on it.
We perform one extra trick here for the benefit of callers and to keep our
code simple: ctf_simple_open_internal() will return a new ctf_dict_t, but we
want to keep the fp constant for the caller, so after
ctf_simple_open_internal() returns, we use memcpy to swap the interior of the
old and new ctf_dict_t's, and then free the old. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_serialize (ctf_dict_t *fp)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t ofp, *nfp;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_header_t hdr, *hdrp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_dtdef_t *dtd;
ctf_dvdef_t *dvd;
ctf_varent_t *dvarents;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_strs_writable_t strtab;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
unsigned char *t;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
unsigned long i;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
size_t buf_size, type_size, objt_size, func_size;
size_t objt_unpadsize, func_unpadsize, objt_padsize, func_padsize;
size_t funcidx_size, objtidx_size;
size_t nvars, nfuncs, nobjts, maxobjt, maxfunc;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
size_t nsymtypes = 0;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
const char **sym_name_order = NULL;
unsigned char *buf = NULL, *newbuf;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int err;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* Symtab filtering. If filter_syms is true, symfp is set: otherwise,
CTF_SYMTYPETAB_FORCE_INDEXED is set in symflags. */
int filter_syms = 0;
int sort_syms = 1;
int symflags = 0;
ctf_dict_t *symfp = NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
/* Update required? */
if (!(fp->ctf_flags & LCTF_DIRTY))
return 0;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* If doing a writeout as part of linking, and the link flags request it,
filter out reported symbols from the variable section, and filter out all
other symbols from the symtypetab sections. (If we are not linking, the
symbols are sorted; if we are linking, don't bother sorting if we are not
filtering out reported symbols: this is almost certaily an ld -r and only
the linker is likely to consume these symtypetabs again. The linker
doesn't care what order the symtypetab entries is in, since it only
iterates over symbols and does not use the ctf_lookup_by_symbol* API.) */
if (fp->ctf_flags & LCTF_LINKING)
{
filter_syms = !(fp->ctf_link_flags & CTF_LINK_NO_FILTER_REPORTED_SYMS);
if (!filter_syms)
sort_syms = 0;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* Fill in an initial CTF header. We will leave the label, object,
and function sections empty and only output a header, type section,
and string table. The type section begins at a 4-byte aligned
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
boundary past the CTF header itself (at relative offset zero). The flag
indicating a new-style function info section (an array of CTF_K_FUNCTION
type IDs in the types section) is flipped on. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
memset (&hdr, 0, sizeof (hdr));
hdr.cth_magic = CTF_MAGIC;
hdr.cth_version = CTF_VERSION;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
/* This is a new-format func info section, and the symtab and strtab come out
of the dynsym and dynstr these days. */
hdr.cth_flags = (CTF_F_NEWFUNCINFO | CTF_F_DYNSTR);
bfd, include, ld, binutils, libctf: CTF should use the dynstr/sym This is embarrassing. The whole point of CTF is that it remains intact even after a binary is stripped, providing a compact mapping from symbols to types for everything in the externally-visible interface of an ELF object: it has connections to the symbol table for that purpose, and to the string table to avoid duplicating symbol names. So it's a shame that the hooks I implemented last year served to hook it up to the .symtab and .strtab, which obviously disappear on strip, leaving any accompanying the CTF dict containing references to strings (and, soon, symbols) which don't exist any more because their containing strtab has been vaporized. The original Solaris design used .dynsym and .dynstr (well, actually, .ldynsym, which has more symbols) which do not disappear. So should we. Thankfully the work we did before serves as guide rails, and adjusting things to use the .dynstr and .dynsym was fast and easy. The only annoyance is that the dynsym is assembled inside elflink.c in a fairly piecemeal fashion, so that the easiest way to get the symbols out was to hook in before every call to swap_symbol_out (we also leave in a hook in front of symbol additions to the .symtab because it seems plausible that we might want to hook them in future too: for now that hook is unused). We adjust things so that rather than being offered a whole hash table of symbols at once, libctf is now given symbols one at a time, with st_name indexes already resolved and pointing at their final .dynstr offsets: it's now up to libctf to resolve these to names as needed using the strtab info we pass it separately. Some bits might be contentious. The ctf_new_dynstr callback takes an elf_internal_sym, and this remains an elf_internal_sym right down through the generic emulation layers into ldelfgen. This is no worse than the elf_sym_strtab we used to pass down, but in the future when we gain non-ELF CTF symtab support we might want to lower the elf_internal_sym to some other representation (perhaps a ctf_link_symbol) in bfd or in ldlang_ctf_new_dynsym. We rename the 'apply_strsym' hooks to 'acquire_strings' instead, becuse they no longer have anything to do with symbols. There are some API changes to pieces of API which are technically public but actually totally unused by anything and/or unused by anything but ld so they can change freely: the ctf_link_symbol gains new fields to allow symbol names to be given as strtab offsets as well as strings, and a symidx so that the symbol index can be passed in. ctf_link_shuffle_syms loses its callback parameter: the idea now is that linkers call the new ctf_link_add_linker_symbol for every symbol in .dynsym, feed in all the strtab entries with ctf_link_add_strtab, and then a call to ctf_link_shuffle_syms will apply both and arrange to use them to reorder the CTF symtab at CTF serialization time (which is coming in the next commit). Inside libctf we have a new preamble flag CTF_F_DYNSTR which is always set in v3-format CTF dicts from this commit forwards: CTF dicts without this flag are associated with .strtab like they used to be, so that old dicts' external strings don't turn to garbage when loaded by new libctf. Dicts with this flag are associated with .dynstr and .dynsym instead. (The flag is not the next in sequence because this commit was written quite late: the missing flags will be filled in by the next commit.) Tests forthcoming in a later commit in this series. bfd/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * elflink.c (elf_finalize_dynstr): Call examine_strtab after dynstr finalization. (elf_link_swap_symbols_out): Don't call it here. Call ctf_new_symbol before swap_symbol_out. (elf_link_output_extsym): Call ctf_new_dynsym before swap_symbol_out. (bfd_elf_final_link): Likewise. * elf.c (swap_out_syms): Pass in bfd_link_info. Call ctf_new_symbol before swap_symbol_out. (_bfd_elf_compute_section_file_positions): Adjust. binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * readelf.c (dump_section_as_ctf): Use .dynsym and .dynstr, not .symtab and .strtab. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * bfdlink.h (struct elf_sym_strtab): Replace with... (struct elf_internal_sym): ... this. (struct bfd_link_callbacks) <examine_strtab>: Take only a symstrtab argument. <ctf_new_symbol>: New. <ctf_new_dynsym>: Likewise. * ctf-api.h (struct ctf_link_sym) <st_symidx>: New. <st_nameidx>: Likewise. <st_nameidx_set>: Likewise. (ctf_link_iter_symbol_f): Removed. (ctf_link_shuffle_syms): Remove most parameters, just takes a ctf_dict_t now. (ctf_link_add_linker_symbol): New, split from ctf_link_shuffle_syms. * ctf.h (CTF_F_DYNSTR): New. (CTF_F_MAX): Adjust. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldelfgen.c (struct ctf_strsym_iter_cb_arg): Rename to... (struct ctf_strtab_iter_cb_arg): ... this, changing fields: <syms>: Remove. <symcount>: Remove. <symstrtab>: Rename to... <strtab>: ... this. (ldelf_ctf_strtab_iter_cb): Adjust. (ldelf_ctf_symbols_iter_cb): Remove. (ldelf_new_dynsym_for_ctf): New, tell libctf about a single symbol. (ldelf_examine_strtab_for_ctf): Rename to... (ldelf_acquire_strings_for_ctf): ... this, only doing the strtab portion and not symbols. * ldelfgen.h: Adjust declarations accordingly. * ldemul.c (ldemul_examine_strtab_for_ctf): Rename to... (ldemul_acquire_strings_for_ctf): ... this. (ldemul_new_dynsym_for_ctf): New. * ldemul.h: Adjust declarations accordingly. * ldlang.c (ldlang_ctf_apply_strsym): Rename to... (ldlang_ctf_acquire_strings): ... this. (ldlang_ctf_new_dynsym): New. (lang_write_ctf): Call ldemul_new_dynsym_for_ctf with NULL to do the actual symbol shuffle. * ldlang.h (struct elf_strtab_hash): Adjust accordingly. * ldmain.c (bfd_link_callbacks): Wire up new/renamed callbacks. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-link.c (ctf_link_shuffle_syms): Adjust. (ctf_link_add_linker_symbol): New, unimplemented stub. * libctf.ver: Add it. * ctf-create.c (ctf_serialize): Set CTF_F_DYNSTR on newly-serialized dicts. * ctf-open-bfd.c (ctf_bfdopen_ctfsect): Check for the flag: open the symtab/strtab if not present, dynsym/dynstr otherwise. * ctf-archive.c (ctf_arc_bufpreamble): New, get the preamble from some arbitrary member of a CTF archive. * ctf-impl.h (ctf_arc_bufpreamble): Declare it.
2020-11-20 21:34:04 +08:00
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* Iterate through the dynamic type definition list and compute the
size of the CTF type section we will need to generate. */
for (type_size = 0, dtd = ctf_list_next (&fp->ctf_dtdefs);
dtd != NULL; dtd = ctf_list_next (dtd))
{
uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
type_size += sizeof (ctf_stype_t);
else
type_size += sizeof (ctf_type_t);
switch (kind)
{
case CTF_K_INTEGER:
case CTF_K_FLOAT:
type_size += sizeof (uint32_t);
break;
case CTF_K_ARRAY:
type_size += sizeof (ctf_array_t);
break;
case CTF_K_SLICE:
type_size += sizeof (ctf_slice_t);
break;
case CTF_K_FUNCTION:
type_size += sizeof (uint32_t) * (vlen + (vlen & 1));
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
type_size += sizeof (ctf_member_t) * vlen;
else
type_size += sizeof (ctf_lmember_t) * vlen;
break;
case CTF_K_ENUM:
type_size += sizeof (ctf_enum_t) * vlen;
break;
}
}
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* Find the dict to which the linker has reported symbols, if any. */
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (filter_syms)
{
if (!fp->ctf_dynsyms && fp->ctf_parent && fp->ctf_parent->ctf_dynsyms)
symfp = fp->ctf_parent;
else
symfp = fp;
}
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* If not filtering, keep all potential symbols in an unsorted, indexed
dict. */
if (!filter_syms)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
symflags = CTF_SYMTYPETAB_FORCE_INDEXED;
else
hdr.cth_flags |= CTF_F_IDXSORTED;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (!ctf_assert (fp, (filter_syms && symfp)
|| (!filter_syms && !symfp
&& ((symflags & CTF_SYMTYPETAB_FORCE_INDEXED) != 0))))
return -1;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
/* Work out the sizes of the object and function sections, and work out the
number of pad (unassigned) symbols in each, and the overall size of the
sections. */
if (symtypetab_density (fp, symfp, fp->ctf_objthash, &nobjts, &maxobjt,
&objt_unpadsize, &objt_padsize, &objtidx_size,
symflags) < 0)
return -1; /* errno is set for us. */
ctf_dprintf ("Object symtypetab: %i objects, max %i, unpadded size %i, "
"%i bytes of pads, index size %i\n", (int) nobjts, (int) maxobjt,
(int) objt_unpadsize, (int) objt_padsize, (int) objtidx_size);
if (symtypetab_density (fp, symfp, fp->ctf_funchash, &nfuncs, &maxfunc,
&func_unpadsize, &func_padsize, &funcidx_size,
symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
return -1; /* errno is set for us. */
ctf_dprintf ("Function symtypetab: %i functions, max %i, unpadded size %i, "
"%i bytes of pads, index size %i\n", (int) nfuncs, (int) maxfunc,
(int) func_unpadsize, (int) func_padsize, (int) funcidx_size);
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* If we are filtering symbols out, those symbols that the linker has not
reported have now been removed from the ctf_objthash and ctf_funchash.
Delete entries from the variable section that duplicate newly-added data
symbols. There's no need to migrate new ones in, because the compiler
always emits both a variable and a data symbol simultaneously, and
filtering only happens at final link time. */
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (filter_syms && symfp->ctf_dynsyms &&
symtypetab_delete_nonstatic_vars (fp, symfp) < 0)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
return -1;
/* It is worth indexing each section if it would save space to do so, due to
reducing the number of pads sufficiently. A pad is the same size as a
single index entry: but index sections compress relatively poorly compared
to constant pads, so it takes a lot of contiguous padding to equal one
index section entry. It would be nice to be able to *verify* whether we
would save space after compression rather than guessing, but this seems
difficult, since it would require complete reserialization. Regardless, if
the linker has not reported any symbols (e.g. if this is not a final link
but just an ld -r), we must emit things in indexed fashion just as the
compiler does. */
objt_size = objt_unpadsize;
if (!(symflags & CTF_SYMTYPETAB_FORCE_INDEXED)
&& ((objt_padsize + objt_unpadsize) * CTF_INDEX_PAD_THRESHOLD
> objt_padsize))
{
objt_size += objt_padsize;
objtidx_size = 0;
}
func_size = func_unpadsize;
if (!(symflags & CTF_SYMTYPETAB_FORCE_INDEXED)
&& ((func_padsize + func_unpadsize) * CTF_INDEX_PAD_THRESHOLD
> func_padsize))
{
func_size += func_padsize;
funcidx_size = 0;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* Computing the number of entries in the CTF variable section is much
simpler. */
for (nvars = 0, dvd = ctf_list_next (&fp->ctf_dvdefs);
dvd != NULL; dvd = ctf_list_next (dvd), nvars++);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
/* Compute the size of the CTF buffer we need, sans only the string table,
then allocate a new buffer and memcpy the finished header to the start of
the buffer. (We will adjust this later with strtab length info.) */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
hdr.cth_lbloff = hdr.cth_objtoff = 0;
hdr.cth_funcoff = hdr.cth_objtoff + objt_size;
hdr.cth_objtidxoff = hdr.cth_funcoff + func_size;
hdr.cth_funcidxoff = hdr.cth_objtidxoff + objtidx_size;
hdr.cth_varoff = hdr.cth_funcidxoff + funcidx_size;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
hdr.cth_typeoff = hdr.cth_varoff + (nvars * sizeof (ctf_varent_t));
hdr.cth_stroff = hdr.cth_typeoff + type_size;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
hdr.cth_strlen = 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
buf_size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
libctf: drop mmap()-based CTF data allocator This allocator has the ostensible benefit that it lets us mprotect() the memory used for CTF storage: but in exchange for this it adds considerable complexity, since we have to track allocation sizes ourselves for use at freeing time, note whether the data we are storing was ctf_data_alloc()ed or not so we know if we can safely mprotect() it... and while the mprotect()ing has found few bugs, it *has* been the cause of more than one due to errors in all this tracking leading to us mprotect()ing bits of the heap and stuff like that. We are about to start composing CTF buffers from pieces so that we can do usage-based optimizations on the strtab. This means we need realloc(), which needs nonportable mremap() and *more* tracking of the *original* allocation size, and the complexity and bureaucracy of all of this is just too high for its negligible benefits. Drop the whole thing and just use malloc() like everyone else. It knows better than we do when it is safe to use mmap() under the covers, anyway. While we're at it, don't leak the entire buffer if ctf_compress_write() fails to compress it. libctf/ * ctf-subr.c (_PAGESIZE): Remove. (ctf_data_alloc): Likewise. (ctf_data_free): Likewise. (ctf_data_protect): Likewise. * ctf-impl.h: Remove declarations. * ctf-create.c (ctf_update): No longer call ctf_data_protect: use ctf_free, not ctf_data_free. (ctf_compress_write): Use ctf_data_alloc, not ctf_alloc. Free the buffer again on compression error. * ctf-open.c (ctf_set_base): No longer track the size: call ctf_free, not ctf_data_free. (upgrade_types): Likewise. Call ctf_alloc, not ctf_data_alloc. (ctf_bufopen): Likewise. No longer call ctf_data_protect.
2019-06-19 19:20:47 +08:00
if ((buf = malloc (buf_size)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
memcpy (buf, &hdr, sizeof (ctf_header_t));
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
t = (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_objtoff;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
hdrp = (ctf_header_t *) buf;
if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parname != NULL))
ctf_str_add_ref (fp, fp->ctf_parname, &hdrp->cth_parname);
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
if (fp->ctf_cuname != NULL)
ctf_str_add_ref (fp, fp->ctf_cuname, &hdrp->cth_cuname);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
/* Sort the linker's symbols into name order if need be. */
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
if ((objtidx_size != 0) || (funcidx_size != 0))
{
ctf_next_t *i = NULL;
void *symname;
const char **walk;
int err;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (filter_syms)
{
if (symfp->ctf_dynsyms)
nsymtypes = ctf_dynhash_elements (symfp->ctf_dynsyms);
else
nsymtypes = 0;
}
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
else
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
nsymtypes = ctf_dynhash_elements (fp->ctf_objthash)
+ ctf_dynhash_elements (fp->ctf_funchash);
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if ((sym_name_order = calloc (nsymtypes, sizeof (const char *))) == NULL)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
goto oom;
walk = sym_name_order;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (filter_syms)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
{
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if (symfp->ctf_dynsyms)
{
while ((err = ctf_dynhash_next_sorted (symfp->ctf_dynsyms, &i,
&symname, NULL,
ctf_dynhash_sort_by_name,
NULL)) == 0)
*walk++ = (const char *) symname;
if (err != ECTF_NEXT_END)
goto symerr;
}
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
}
else
{
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
ctf_hash_sort_f sort_fun = NULL;
/* Since we partition the set of symbols back into objt and func,
we can sort the two independently without harm. */
if (sort_syms)
sort_fun = ctf_dynhash_sort_by_name;
while ((err = ctf_dynhash_next_sorted (fp->ctf_objthash, &i, &symname,
NULL, sort_fun, NULL)) == 0)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
*walk++ = (const char *) symname;
if (err != ECTF_NEXT_END)
goto symerr;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
while ((err = ctf_dynhash_next_sorted (fp->ctf_funchash, &i, &symname,
NULL, sort_fun, NULL)) == 0)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
*walk++ = (const char *) symname;
if (err != ECTF_NEXT_END)
goto symerr;
}
}
/* Emit the object and function sections, and if necessary their indexes.
Emission is done in symtab order if there is no index, and in index
(name) order otherwise. */
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if ((objtidx_size == 0) && symfp && symfp->ctf_dynsymidx)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
{
ctf_dprintf ("Emitting unindexed objt symtypetab\n");
if (emit_symtypetab (fp, symfp, (uint32_t *) t, symfp->ctf_dynsymidx,
NULL, symfp->ctf_dynsymmax + 1, maxobjt, objt_size,
symflags | CTF_SYMTYPETAB_EMIT_PAD) < 0)
goto err; /* errno is set for us. */
}
else
{
ctf_dprintf ("Emitting indexed objt symtypetab\n");
if (emit_symtypetab (fp, symfp, (uint32_t *) t, NULL, sym_name_order,
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
nsymtypes, maxobjt, objt_size, symflags) < 0)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
goto err; /* errno is set for us. */
}
t += objt_size;
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
if ((funcidx_size == 0) && symfp && symfp->ctf_dynsymidx)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
{
ctf_dprintf ("Emitting unindexed func symtypetab\n");
if (emit_symtypetab (fp, symfp, (uint32_t *) t, symfp->ctf_dynsymidx,
NULL, symfp->ctf_dynsymmax + 1, maxfunc,
func_size, symflags | CTF_SYMTYPETAB_EMIT_FUNCTION
| CTF_SYMTYPETAB_EMIT_PAD) < 0)
goto err; /* errno is set for us. */
}
else
{
ctf_dprintf ("Emitting indexed func symtypetab\n");
if (emit_symtypetab (fp, symfp, (uint32_t *) t, NULL, sym_name_order,
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
nsymtypes, maxfunc, func_size,
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
goto err; /* errno is set for us. */
}
t += func_size;
if (objtidx_size > 0)
if (emit_symtypetab_index (fp, symfp, (uint32_t *) t, sym_name_order,
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
nsymtypes, objtidx_size, symflags) < 0)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
goto err;
t += objtidx_size;
if (funcidx_size > 0)
if (emit_symtypetab_index (fp, symfp, (uint32_t *) t, sym_name_order,
libctf, ld: fix symtypetab and var section population under ld -r The variable section in a CTF dict is meant to contain the types of variables that do not appear in the symbol table (mostly file-scope static declarations). We implement this by having the compiler emit all potential data symbols into both sections, then delete those symbols from the variable section that correspond to data symbols the linker has reported. Unfortunately, the check for this in ctf_serialize is wrong: rather than checking the set of linker-reported symbols, we check the set of names in the data object symtypetab section: if the linker has reported no symbols at all (usually if ld -r has been run, or if a non-linker program that does not use symbol tables is calling ctf_link) this will include every single symbol, emptying the variable section completely. Worse, when ld -r is in use, we want to force writeout of every symtypetab entry on the inputs, in an indexed section, whether or not the linker has reported them, since this isn't a final link yet and the symbol table is not finalized (and may grow more symbols than the linker has yet reported). But the check for this is flawed too: we were relying on ctf_link_shuffle_syms not having been called if no symbols exist, but that function is *always* called by ld even when ld -r is in use: ctf_link_add_linker_symbol is the one that's not called when there are no symbols. We clearly need to rethink this. Using the emptiness of the set of reported symbols as a test for ld -r is just ugly: the linker already knows if ld -r is underway and can just tell us. So add a new linker flag CTF_LINK_NO_FILTER_REPORTED_SYMS that is set to stop the linker filtering the symbols in the symtypetab sections using the set that the linker has reported: use the presence or absence of this flag to determine whether to emit unindexed symtabs: we only remove entries from the variable section when filtering symbols, and we only remove them if they are in the reported symbol set, fixing the case where no symbols are reported by the linker at all. (The negative sense of the new CTF_LINK flag is intentional: the common case, both for ld and for simple tools that want to do a ctf_link with no ELF symbol table in sight, is probably to filter out symbols that no linker has reported: i.e., for the simple tools, all of them.) There's another wrinkle, though. It is quite possible for a non-linker to add symbols to a dict via ctf_add_*_sym and then write it out via the ctf_write APIs: perhaps it's preparing a dict for a later linker invocation. Right now this would not lead to anything terribly meaningful happening: ctf_serialize just assumes it was called via ctf_link if symbols are present. So add an (internal-to-libctf) flag that indicates that a writeout is happening via ctf_link_write, and set it there (propagating it to child dicts as needed). ctf_serialize can then spot when it is not being called by a linker, and arrange to always write out an indexed, sorted symtypetab for fastest possible future symbol lookup by name in that case. (The writeouts done by ld -r are unsorted, because the only thing likely to use those symtabs is the linker, which doesn't benefit from symtypetab sorting.) Tests added for all three linking cases (ld -r, ld -shared, ld), with a bit of testsuite framework enhancement to stop it unconditionally linking the CTF to be checked by the lookup program with -shared, so tests can now examine CTF linked with -r or indeed with no flags at all, though the output filename is still foo.so even in this case. Another test added for the non-linker case that endeavours to determine whether the symtypetab is sorted by examining the order of entries returned from ctf_symbol_next: nobody outside libctf should rely on this ordering, but this test is not outside libctf :) include/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (CTF_LINK_NO_FILTER_REPORTED_SYMS): New. ld/ChangeLog 2021-01-26 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_merge_ctf): Set CTF_LINK_NO_FILTER_REPORTED_SYMS when appropriate. libctf/ChangeLog 2021-01-27 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.c (_libctf_nonnull_): Add parameters. (LCTF_LINKING): New flag. (ctf_dict_t) <ctf_link_flags>: Mention it. * ctf-link.c (ctf_link): Keep LCTF_LINKING set across call. (ctf_write): Likewise, including in child dictionaries. (ctf_link_shuffle_syms): Make sure ctf_dynsyms is NULL if there are no reported symbols. * ctf-create.c (symtypetab_delete_nonstatic_vars): Make sure the variable has been reported as a symbol by the linker. (symtypetab_skippable): Mention relationship between SYMFP and the flags. (symtypetab_density): Adjust nonnullity. Exit early if no symbols were reported and force-indexing is off (i.e., we are doing a final link). (ctf_serialize): Handle the !LCTF_LINKING case by writing out an indexed, sorted symtypetab (and allow SYMFP to be NULL in this case). Turn sorting off if this is a non-final link. Only delete nonstatic vars if we are filtering symbols and the linker has reported some. * testsuite/libctf-regression/nonstatic-var-section-ld-r*: New test of variable and symtypetab section population when ld -r is used. * testsuite/libctf-regression/nonstatic-var-section-ld-executable.lk: Likewise, when ld of an executable is used. * testsuite/libctf-regression/nonstatic-var-section-ld.lk: Likewise, when ld -shared alone is used. * testsuite/libctf-regression/nonstatic-var-section-ld*.c: Lookup programs for the above. * testsuite/libctf-writable/symtypetab-nonlinker-writeout.*: New test, testing survival of symbols across ctf_write paths. * testsuite/lib/ctf-lib.exp (run_lookup_test): New option, nonshared, suppressing linking of the SOURCE with -shared.
2021-01-17 00:49:29 +08:00
nsymtypes, funcidx_size,
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
symflags | CTF_SYMTYPETAB_EMIT_FUNCTION) < 0)
goto err;
t += funcidx_size;
free (sym_name_order);
sym_name_order = NULL;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
/* Work over the variable list, translating everything into ctf_varent_t's and
prepping the string table. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
dvarents = (ctf_varent_t *) t;
for (i = 0, dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL;
dvd = ctf_list_next (dvd), i++)
{
ctf_varent_t *var = &dvarents[i];
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_str_add_ref (fp, dvd->dvd_name, &var->ctv_name);
var->ctv_type = (uint32_t) dvd->dvd_type;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
assert (i == nvars);
t += sizeof (ctf_varent_t) * nvars;
assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_typeoff);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
/* We now take a final lap through the dynamic type definition list and copy
the appropriate type records to the output buffer, noting down the
strings as we go. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
for (dtd = ctf_list_next (&fp->ctf_dtdefs);
dtd != NULL; dtd = ctf_list_next (dtd))
{
uint32_t kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
uint32_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
ctf_array_t cta;
uint32_t encoding;
size_t len;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_stype_t *copied;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
const char *name;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
len = sizeof (ctf_stype_t);
else
len = sizeof (ctf_type_t);
memcpy (t, &dtd->dtd_data, len);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
copied = (ctf_stype_t *) t; /* name is at the start: constant offset. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (copied->ctt_name
&& (name = ctf_strraw (fp, copied->ctt_name)) != NULL)
ctf_str_add_ref (fp, name, &copied->ctt_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
t += len;
switch (kind)
{
case CTF_K_INTEGER:
case CTF_K_FLOAT:
if (kind == CTF_K_INTEGER)
{
encoding = CTF_INT_DATA (dtd->dtd_u.dtu_enc.cte_format,
dtd->dtd_u.dtu_enc.cte_offset,
dtd->dtd_u.dtu_enc.cte_bits);
}
else
{
encoding = CTF_FP_DATA (dtd->dtd_u.dtu_enc.cte_format,
dtd->dtd_u.dtu_enc.cte_offset,
dtd->dtd_u.dtu_enc.cte_bits);
}
memcpy (t, &encoding, sizeof (encoding));
t += sizeof (encoding);
break;
case CTF_K_SLICE:
memcpy (t, &dtd->dtd_u.dtu_slice, sizeof (struct ctf_slice));
t += sizeof (struct ctf_slice);
break;
case CTF_K_ARRAY:
cta.cta_contents = (uint32_t) dtd->dtd_u.dtu_arr.ctr_contents;
cta.cta_index = (uint32_t) dtd->dtd_u.dtu_arr.ctr_index;
cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
memcpy (t, &cta, sizeof (cta));
t += sizeof (cta);
break;
case CTF_K_FUNCTION:
{
uint32_t *argv = (uint32_t *) (uintptr_t) t;
uint32_t argc;
for (argc = 0; argc < vlen; argc++)
*argv++ = dtd->dtd_u.dtu_argv[argc];
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (vlen & 1)
*argv++ = 0; /* Pad to 4-byte boundary. */
t = (unsigned char *) argv;
break;
}
case CTF_K_STRUCT:
case CTF_K_UNION:
if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
t = ctf_copy_smembers (fp, dtd, t);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
else
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
t = ctf_copy_lmembers (fp, dtd, t);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
break;
case CTF_K_ENUM:
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
t = ctf_copy_emembers (fp, dtd, t);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
break;
}
}
assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
/* Construct the final string table and fill out all the string refs with the
final offsets. Then purge the refs list, because we're about to move this
strtab onto the end of the buf, invalidating all the offsets. */
strtab = ctf_str_write_strtab (fp);
ctf_str_purge_refs (fp);
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
if (strtab.cts_strs == NULL)
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
goto oom;
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
/* Now the string table is constructed, we can sort the buffer of
ctf_varent_t's. */
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
ctf_sort_var_arg_cb_t sort_var_arg = { fp, (ctf_strs_t *) &strtab };
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_qsort_r (dvarents, nvars, sizeof (ctf_varent_t), ctf_sort_var,
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
&sort_var_arg);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
if ((newbuf = ctf_realloc (fp, buf, buf_size + strtab.cts_len)) == NULL)
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (strtab.cts_strs);
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
goto oom;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
}
buf = newbuf;
memcpy (buf + buf_size, strtab.cts_strs, strtab.cts_len);
hdrp = (ctf_header_t *) buf;
hdrp->cth_strlen = strtab.cts_len;
buf_size += hdrp->cth_strlen;
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (strtab.cts_strs);
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* Finally, we are ready to ctf_simple_open() the new dict. If this is
successful, we then switch nfp and fp and free the old dict. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
if ((nfp = ctf_simple_open_internal ((char *) buf, buf_size, NULL, 0,
0, NULL, 0, fp->ctf_syn_ext_strtab,
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
1, &err)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (buf);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, err));
}
(void) ctf_setmodel (nfp, ctf_getmodel (fp));
libctf: sort out potential refcount loops When you link TUs that contain conflicting types together, the resulting CTF section is an archive containing many CTF dicts. These dicts appear in ctf_link_outputs of the shared dict, with each ctf_import'ing that shared dict. ctf_importing a dict bumps its refcount to stop it going away while it's in use -- but if the shared dict (whose refcount is bumped) has the child dict (doing the bumping) in its ctf_link_outputs, we have a refcount loop, since the child dict only un-ctf_imports and drops the parent's refcount when it is freed, but the child is only freed when the parent's refcount falls to zero. (In the future, this will be able to go wrong on the inputs too, when an ld -r'ed deduplicated output with conflicts is relinked. Right now this cannot happen because we don't ctf_import such dicts at all. This will be fixed in a later commit in this series.) Fix this by introducing an internal-use-only ctf_import_unref function that imports a parent dict *witthout* bumping the parent's refcount, and using it when we create per-CU outputs. This function is only safe to use if you know the parent cannot go away while the child exists: but if the parent *owns* the child, as here, this is necessarily true. Record in the ctf_file_t whether a parent was imported via ctf_import or ctf_import_unref, so that if you do another ctf_import later on (or a ctf_import_unref) it can decide whether to drop the refcount of the existing parent being replaced depending on which function you used to import that one. Adjust ctf_serialize so that rather than doing a ctf_import (which is wrong if the original import was ctf_import_unref'fed), we just copy the parent field and refcount over and forcibly flip the unref flag on on the old copy we are going to discard. ctf_file_close also needs a bit of tweaking to only close the parent if it was not imported with ctf_import_unref: while we're at it, guard against repeated closes with a refcount of zero and stop them causing double-frees, even if destruction of things freed *inside* ctf_file_close cause such recursion. Verified no leaks or accesses to freed memory after all of this with valgrind. (It was leak-happy before.) libctf/ * ctf-impl.c (ctf_file_t) <ctf_parent_unreffed>: New. (ctf_import_unref): New. * ctf-open.c (ctf_file_close) Drop the refcount all the way to zero. Don't recurse back in if the refcount is already zero. (ctf_import): Check ctf_parent_unreffed before deciding whether to close a pre-existing parent. Set it to zero. (ctf_import_unreffed): New, as above, setting ctf_parent_unreffed to 1. * ctf-create.c (ctf_serialize): Do not ctf_import into the new child: use direct assignment, and set unreffed on the new and old children. * ctf-link.c (ctf_create_per_cu): Import the parent using ctf_import_unreffed.
2020-06-05 00:30:01 +08:00
nfp->ctf_parent = fp->ctf_parent;
nfp->ctf_parent_unreffed = fp->ctf_parent_unreffed;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
nfp->ctf_refcnt = fp->ctf_refcnt;
nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
if (nfp->ctf_dynbase == NULL)
nfp->ctf_dynbase = buf; /* Make sure buf is freed on close. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
nfp->ctf_dthash = fp->ctf_dthash;
nfp->ctf_dtdefs = fp->ctf_dtdefs;
nfp->ctf_dvhash = fp->ctf_dvhash;
nfp->ctf_dvdefs = fp->ctf_dvdefs;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
nfp->ctf_dtoldid = fp->ctf_dtoldid;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
nfp->ctf_add_processing = fp->ctf_add_processing;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
nfp->ctf_snapshots = fp->ctf_snapshots + 1;
nfp->ctf_specific = fp->ctf_specific;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
nfp->ctf_nfuncidx = fp->ctf_nfuncidx;
nfp->ctf_nobjtidx = fp->ctf_nobjtidx;
nfp->ctf_objthash = fp->ctf_objthash;
nfp->ctf_funchash = fp->ctf_funchash;
nfp->ctf_dynsyms = fp->ctf_dynsyms;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
nfp->ctf_ptrtab = fp->ctf_ptrtab;
libctf: fix lookups of pointers by name in parent dicts When you look up a type by name using ctf_lookup_by_name, in most cases libctf can just strip off any qualifiers and look for the name, but for pointer types this doesn't work, since the caller will want the pointer type itself. But pointer types are nameless, and while they cite the types they point to, looking up a type by name requires a link going the *other way*, from the type pointed to to the pointer type that points to it. libctf has always built this up at open time: ctf_ptrtab is an array of type indexes pointing from the index of every type to the index of the type that points to it. But because it is built up at open time (and because it uses type indexes and not type IDs) it is restricted to working within a single dict and ignoring parent/child relationships. This is normally invisible, unless you manage to get a dict with a type in the parent but the only pointer to it in a child. The ctf_ptrtab will not track this relationship, so lookups of this pointer type by name will fail. Since which type is in the parent and which in the child is largely opaque to the user (which goes where is up to the deduplicator, and it can and does reshuffle things to save space), this leads to a very bad user experience, with an obviously-visible pointer type which ctf_lookup_by_name claims doesn't exist. The fix is to have another array, ctf_pptrtab, which is populated in child dicts: like the parent's ctf_ptrtab, it has one element per type in the parent, but is all zeroes except for those types which are pointed to by types in the child: so it maps parent dict indices to child dict indices. The array is grown, and new child types scanned, whenever a lookup happens and new types have been added to the child since the last time a lookup happened that might need the pptrtab. (So for non-writable dicts, this only happens once, since new types cannot be added to non-writable dicts at all.) Since this introduces new complexity (involving updating only part of the ctf_pptrtab) which is only seen when a writable dict is in use, we introduce a new libctf-writable testsuite that contains lookup tests with no corresponding CTF-containing .c files (which can thus be run even on platforms with no .ctf-section support in the linker yet), and add a test to check that creation of pointers in children to types in parents and a following lookup by name works as expected. The non- writable case is tested in a new libctf-regression testsuite which is used to track now-fixed outright bugs in libctf. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_pptrtab>: New. <ctf_pptrtab_len>: New. <ctf_pptrtab_typemax>: New. * ctf-create.c (ctf_serialize): Update accordingly. (ctf_add_reftype): Note that we don't need to update pptrtab here, despite updating ptrtab. * ctf-open.c (ctf_dict_close): Destroy the pptrtab. (ctf_import): Likewise. (ctf_import_unref): Likewise. * ctf-lookup.c (grow_pptrtab): New. (refresh_pptrtab): New, update a pptrtab. (ctf_lookup_by_name): Turn into a wrapper around (and rename to)... (ctf_lookup_by_name_internal): ... this: construct the pptrtab, and use it in addition to the parent's ptrtab when parent dicts are searched. * testsuite/libctf-regression/regression.exp: New testsuite for regression tests. * testsuite/libctf-regression/pptrtab*: New test. * testsuite/libctf-writable/writable.exp: New testsuite for tests of writable CTF dicts. * testsuite/libctf-writable/pptrtab*: New test.
2021-01-05 21:25:56 +08:00
nfp->ctf_pptrtab = fp->ctf_pptrtab;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
nfp->ctf_dynsymidx = fp->ctf_dynsymidx;
nfp->ctf_dynsymmax = fp->ctf_dynsymmax;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len;
libctf: fix lookups of pointers by name in parent dicts When you look up a type by name using ctf_lookup_by_name, in most cases libctf can just strip off any qualifiers and look for the name, but for pointer types this doesn't work, since the caller will want the pointer type itself. But pointer types are nameless, and while they cite the types they point to, looking up a type by name requires a link going the *other way*, from the type pointed to to the pointer type that points to it. libctf has always built this up at open time: ctf_ptrtab is an array of type indexes pointing from the index of every type to the index of the type that points to it. But because it is built up at open time (and because it uses type indexes and not type IDs) it is restricted to working within a single dict and ignoring parent/child relationships. This is normally invisible, unless you manage to get a dict with a type in the parent but the only pointer to it in a child. The ctf_ptrtab will not track this relationship, so lookups of this pointer type by name will fail. Since which type is in the parent and which in the child is largely opaque to the user (which goes where is up to the deduplicator, and it can and does reshuffle things to save space), this leads to a very bad user experience, with an obviously-visible pointer type which ctf_lookup_by_name claims doesn't exist. The fix is to have another array, ctf_pptrtab, which is populated in child dicts: like the parent's ctf_ptrtab, it has one element per type in the parent, but is all zeroes except for those types which are pointed to by types in the child: so it maps parent dict indices to child dict indices. The array is grown, and new child types scanned, whenever a lookup happens and new types have been added to the child since the last time a lookup happened that might need the pptrtab. (So for non-writable dicts, this only happens once, since new types cannot be added to non-writable dicts at all.) Since this introduces new complexity (involving updating only part of the ctf_pptrtab) which is only seen when a writable dict is in use, we introduce a new libctf-writable testsuite that contains lookup tests with no corresponding CTF-containing .c files (which can thus be run even on platforms with no .ctf-section support in the linker yet), and add a test to check that creation of pointers in children to types in parents and a following lookup by name works as expected. The non- writable case is tested in a new libctf-regression testsuite which is used to track now-fixed outright bugs in libctf. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_pptrtab>: New. <ctf_pptrtab_len>: New. <ctf_pptrtab_typemax>: New. * ctf-create.c (ctf_serialize): Update accordingly. (ctf_add_reftype): Note that we don't need to update pptrtab here, despite updating ptrtab. * ctf-open.c (ctf_dict_close): Destroy the pptrtab. (ctf_import): Likewise. (ctf_import_unref): Likewise. * ctf-lookup.c (grow_pptrtab): New. (refresh_pptrtab): New, update a pptrtab. (ctf_lookup_by_name): Turn into a wrapper around (and rename to)... (ctf_lookup_by_name_internal): ... this: construct the pptrtab, and use it in addition to the parent's ptrtab when parent dicts are searched. * testsuite/libctf-regression/regression.exp: New testsuite for regression tests. * testsuite/libctf-regression/pptrtab*: New test. * testsuite/libctf-writable/writable.exp: New testsuite for tests of writable CTF dicts. * testsuite/libctf-writable/pptrtab*: New test.
2021-01-05 21:25:56 +08:00
nfp->ctf_pptrtab_len = fp->ctf_pptrtab_len;
libctf: add the ctf_link machinery This is the start of work on the core of the linking mechanism for CTF sections. This commit handles the type and string sections. The linker calls these functions in sequence: ctf_link_add_ctf: to add each CTF section in the input in turn to a newly-created ctf_file_t (which will appear in the output, and which itself will become the shared parent that contains types that all TUs have in common (in all link modes) and all types that do not have conflicting definitions between types (by default). Input files that are themselves products of ld -r are supported, though this is not heavily tested yet. ctf_link: called once all input files are added to merge the types in all the input containers into the output container, eliminating duplicates. ctf_link_add_strtab: called once the ELF string table is finalized and all its offsets are known, this calls a callback provided by the linker which returns the string content and offset of every string in the ELF strtab in turn: all these strings which appear in the input CTF strtab are eliminated from it in favour of the ELF strtab: equally, any strings that only appear in the input strtab will reappear in the internal CTF strtab of the output. ctf_link_shuffle_syms (not yet implemented): called once the ELF symtab is finalized, this calls a callback provided by the linker which returns information on every symbol in turn as a ctf_link_sym_t. This is then used to shuffle the function info and data object sections in the CTF section into symbol table order, eliminating the index sections which map those sections to symbol names before that point. Currently just returns ECTF_NOTYET. ctf_link_write: Returns a buffer containing either a serialized ctf_file_t (if there are no types with conflicting definitions in the object files in the link) or a ctf_archive_t containing a large ctf_file_t (the common types) and a bunch of small ones named after individual CUs in which conflicting types are found (containing the conflicting types, and all types that reference them). A threshold size above which compression takes place is passed as one parameter. (Currently, only gzip compression is supported, but I hope to add lzma as well.) Lifetime rules for this are simple: don't close the input CTF files until you've called ctf_link for the last time. We do not assume that symbols or strings passed in by the callback outlast the call to ctf_link_add_strtab or ctf_link_shuffle_syms. Right now, the duplicate elimination mechanism is the one already present as part of the ctf_add_type function, and is not particularly good: it misses numerous actual duplicates, and the conflicting-types detection hardly ever reports that types conflict, even when they do (one of them just tends to get silently dropped): it is also very slow. This will all be fixed in the next few weeks, but the fix hardly touches any of this code, and the linker does work without it, just not as well as it otherwise might. (And when no CTF section is present, there is no effect on performance, of course. So only people using a trunk GCC with not-yet-committed patches will even notice. By the time it gets upstream, things should be better.) v3: Fix error handling. v4: check for strdup failure. v5: fix tabdamage. include/ * ctf-api.h (struct ctf_link_sym): New, a symbol in flight to the libctf linking machinery. (CTF_LINK_SHARE_UNCONFLICTED): New. (CTF_LINK_SHARE_DUPLICATED): New. (ECTF_LINKADDEDLATE): New, replacing ECTF_UNUSED. (ECTF_NOTYET): New, a 'not yet implemented' message. (ctf_link_add_ctf): New, add an input file's CTF to the link. (ctf_link): New, merge the type and string sections. (ctf_link_strtab_string_f): New, callback for feeding strtab info. (ctf_link_iter_symbol_f): New, callback for feeding symtab info. (ctf_link_add_strtab): New, tell the CTF linker about the ELF strtab's strings. (ctf_link_shuffle_syms): New, ask the CTF linker to shuffle its symbols into symtab order. (ctf_link_write): New, ask the CTF linker to write the CTF out. libctf/ * ctf-link.c: New file, linking of the string and type sections. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate. * ctf-impl.h (ctf_file_t): New fields ctf_link_inputs, ctf_link_outputs. * ctf-create.c (ctf_update): Update accordingly. * ctf-open.c (ctf_file_close): Likewise. * ctf-error.c (_ctf_errlist): Updated with new errors.
2019-07-14 04:06:55 +08:00
nfp->ctf_link_inputs = fp->ctf_link_inputs;
nfp->ctf_link_outputs = fp->ctf_link_outputs;
libctf, ld, binutils: add textual error/warning reporting for libctf This commit adds a long-missing piece of infrastructure to libctf: the ability to report errors and warnings using all the power of printf, rather than being restricted to one errno value. Internally, libctf calls ctf_err_warn() to add errors and warnings to a list: a new iterator ctf_errwarning_next() then consumes this list one by one and hands it to the caller, which can free it. New errors and warnings are added until the list is consumed by the caller or the ctf_file_t is closed, so you can dump them at intervals. The caller can of course choose to print only those warnings it wants. (I am not sure whether we want objdump, readelf or ld to print warnings or not: right now I'm printing them, but maybe we only want to print errors? This entirely depends on whether warnings are voluminous things describing e.g. the inability to emit single types because of name clashes or something. There are no users of this infrastructure yet, so it's hard to say.) There is no internationalization here yet, but this at least adds a place where internationalization can be added, to one of ctf_errwarning_next or ctf_err_warn. We also provide a new ctf_assert() function which uses this infrastructure to provide non-fatal assertion failures while emitting an assert-like string to the caller: to save space and avoid needlessly duplicating unchanging strings, the assertion test is inlined but the print-things-out failure case is not. All assertions in libctf will be converted to use this machinery in future commits and propagate assertion-failure errors up, so that the linker in particular cannot be killed by libctf assertion failures when it could perfectly well just print warnings and drop the CTF section. include/ * ctf-api.h (ECTF_INTERNAL): Adjust error text. (ctf_errwarning_next): New. libctf/ * ctf-impl.h (ctf_assert): New. (ctf_err_warning_t): Likewise. (ctf_file_t) <ctf_errs_warnings>: Likewise. (ctf_err_warn): New prototype. (ctf_assert_fail_internal): Likewise. * ctf-inlines.h (ctf_assert_internal): Likewise. * ctf-open.c (ctf_file_close): Free ctf_errs_warnings. * ctf-create.c (ctf_serialize): Copy it on serialization. * ctf-subr.c (ctf_err_warn): New, add an error/warning. (ctf_errwarning_next): New iterator, free and pass back errors/warnings in succession. * libctf.ver (ctf_errwarning_next): Add. ld/ * ldlang.c (lang_ctf_errs_warnings): New, print CTF errors and warnings. Assert when libctf asserts. (lang_merge_ctf): Call it. (land_write_ctf): Likewise. binutils/ * objdump.c (ctf_archive_member): Print CTF errors and warnings. * readelf.c (dump_ctf_archive_member): Likewise.
2020-06-04 22:07:54 +08:00
nfp->ctf_errs_warnings = fp->ctf_errs_warnings;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
nfp->ctf_funcidx_names = fp->ctf_funcidx_names;
nfp->ctf_objtidx_names = fp->ctf_objtidx_names;
nfp->ctf_funcidx_sxlate = fp->ctf_funcidx_sxlate;
nfp->ctf_objtidx_sxlate = fp->ctf_objtidx_sxlate;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset;
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
libctf: fix lookups of pointers by name in parent dicts When you look up a type by name using ctf_lookup_by_name, in most cases libctf can just strip off any qualifiers and look for the name, but for pointer types this doesn't work, since the caller will want the pointer type itself. But pointer types are nameless, and while they cite the types they point to, looking up a type by name requires a link going the *other way*, from the type pointed to to the pointer type that points to it. libctf has always built this up at open time: ctf_ptrtab is an array of type indexes pointing from the index of every type to the index of the type that points to it. But because it is built up at open time (and because it uses type indexes and not type IDs) it is restricted to working within a single dict and ignoring parent/child relationships. This is normally invisible, unless you manage to get a dict with a type in the parent but the only pointer to it in a child. The ctf_ptrtab will not track this relationship, so lookups of this pointer type by name will fail. Since which type is in the parent and which in the child is largely opaque to the user (which goes where is up to the deduplicator, and it can and does reshuffle things to save space), this leads to a very bad user experience, with an obviously-visible pointer type which ctf_lookup_by_name claims doesn't exist. The fix is to have another array, ctf_pptrtab, which is populated in child dicts: like the parent's ctf_ptrtab, it has one element per type in the parent, but is all zeroes except for those types which are pointed to by types in the child: so it maps parent dict indices to child dict indices. The array is grown, and new child types scanned, whenever a lookup happens and new types have been added to the child since the last time a lookup happened that might need the pptrtab. (So for non-writable dicts, this only happens once, since new types cannot be added to non-writable dicts at all.) Since this introduces new complexity (involving updating only part of the ctf_pptrtab) which is only seen when a writable dict is in use, we introduce a new libctf-writable testsuite that contains lookup tests with no corresponding CTF-containing .c files (which can thus be run even on platforms with no .ctf-section support in the linker yet), and add a test to check that creation of pointers in children to types in parents and a following lookup by name works as expected. The non- writable case is tested in a new libctf-regression testsuite which is used to track now-fixed outright bugs in libctf. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_pptrtab>: New. <ctf_pptrtab_len>: New. <ctf_pptrtab_typemax>: New. * ctf-create.c (ctf_serialize): Update accordingly. (ctf_add_reftype): Note that we don't need to update pptrtab here, despite updating ptrtab. * ctf-open.c (ctf_dict_close): Destroy the pptrtab. (ctf_import): Likewise. (ctf_import_unref): Likewise. * ctf-lookup.c (grow_pptrtab): New. (refresh_pptrtab): New, update a pptrtab. (ctf_lookup_by_name): Turn into a wrapper around (and rename to)... (ctf_lookup_by_name_internal): ... this: construct the pptrtab, and use it in addition to the parent's ptrtab when parent dicts are searched. * testsuite/libctf-regression/regression.exp: New testsuite for regression tests. * testsuite/libctf-regression/pptrtab*: New test. * testsuite/libctf-writable/writable.exp: New testsuite for tests of writable CTF dicts. * testsuite/libctf-writable/pptrtab*: New test.
2021-01-05 21:25:56 +08:00
nfp->ctf_pptrtab_typemax = fp->ctf_pptrtab_typemax;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
nfp->ctf_in_flight_dynsyms = fp->ctf_in_flight_dynsyms;
libctf, link: redo cu-mapping handling Now a bunch of stuff that doesn't apply to ld or any normal use of libctf, piled into one commit so that it's easier to ignore. The cu-mapping machinery associates incoming compilation unit names with outgoing names of CTF dictionaries that should correspond to them, for non-gdb CTF consumers that would like to group multiple TUs into a single child dict if conflicting types are found in it (the existing use case is one kernel module, one child CTF dict, even if the kernel module is composed of multiple CUs). The upcoming deduplicator needs to track not only the mapping from incoming CU name to outgoing dict name, but the inverse mapping from outgoing dict name to incoming CU name, so it can work over every CTF dict we might see in the output and link into it. So rejig the ctf-link machinery to do that. Simultaneously (because they are closely associated and were written at the same time), we add a new CTF_LINK_EMPTY_CU_MAPPINGS flag to ctf_link, which tells the ctf_link machinery to create empty child dicts for each outgoing CU mapping even if no CUs that correspond to it exist in the link. This is a bit (OK, quite a lot) of a waste of space, but some existing consumers require it. (Nobody else should use it.) Its value is not consecutive with existing CTF_LINK flag values because we're about to add more flags that are conceptually closer to the existing ones than this one is. include/ * ctf-api.h (CTF_LINK_EMPTY_CU_MAPPINGS): New. libctf/ * ctf-impl.h (ctf_file_t): Improve comments. <ctf_link_cu_mapping>: Split into... <ctf_link_in_cu_mapping>: ... this... <ctf_link_out_cu_mapping>: ... and this. * ctf-create.c (ctf_serialize): Adjust. * ctf-open.c (ctf_file_close): Likewise. * ctf-link.c (ctf_create_per_cu): Look things up in the in_cu_mapping instead of the cu_mapping. (ctf_link_add_cu_mapping): The deduplicating link will define what happens if many FROMs share a TO. (ctf_link_add_cu_mapping): Create in_cu_mapping and out_cu_mapping. Do not create ctf_link_outputs here any more, or create per-CU dicts here: they are already created when needed. (ctf_link_one_variable): Log a debug message if we skip a variable due to its type being concealed in a CU-mapped link. (This is probably too common a case to make into a warning.) (ctf_link): Create empty per-CU dicts if requested.
2020-06-06 00:36:16 +08:00
nfp->ctf_link_in_cu_mapping = fp->ctf_link_in_cu_mapping;
nfp->ctf_link_out_cu_mapping = fp->ctf_link_out_cu_mapping;
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
nfp->ctf_link_type_mapping = fp->ctf_link_type_mapping;
libctf: add CU-mapping machinery Once the deduplicator is capable of actually detecting conflicting types with the same name (i.e., not yet) we will place such conflicting types, and types that depend on them, into CTF dictionaries that are the child of the main dictionary we usually emit: currently, this will lead to the .ctf section becoming a CTF archive rather than a single dictionary, with the default-named archive member (_CTF_SECTION, or NULL) being the main shared dictionary with most of the types in it. By default, the sections are named after the compilation unit they come from (complete path and all), with the cuname field in the CTF header providing further evidence of the name without requiring the caller to engage in tiresome parsing. But some callers may not wish the mapping from input CU to output sub-dictionary to be purely CU-based. The machinery here allows this to be freely changed, in two ways: - callers can call ctf_link_add_cu_mapping to specify that a single input compilation unit should have its types placed in some other CU if they conflict: the CU will always be created, even if empty, so the consuming program can depend on its existence. You can map multiple input CUs to one output CU to force all their types to be merged together: if some of *those* types conflict, the behaviour is currently unspecified (the new deduplicator will specify it). - callers can call ctf_link_set_memb_name_changer to provide a function which is passed every CTF sub-dictionary name in turn (including _CTF_SECTION) and can return a new name, or NULL if no change is desired. The mapping from input to output names should not map two input names to the same output name: if this happens, the two are not merged but will result in an archive with two members with the same name (technically valid, but it's hard to access the second same-named member: you have to do an iteration over archive members). This is used by the kernel's ctfarchive machinery (not yet upstream) to encode CTF under member names like {module name}.ctf rather than .ctf.CU, but it is anticipated that other large projects may wish to have their own storage for CTF outside of .ctf sections and may wish to have new naming schemes that suit their special-purpose consumers. New in v3. v4: check for strdup failure. v5: fix tabdamage. include/ * ctf-api.h (ctf_link_add_cu_mapping): New. (ctf_link_memb_name_changer_f): New. (ctf_link_set_memb_name_changer): New. libctf/ * ctf-impl.h (ctf_file_t) <ctf_link_cu_mappping>: New. <ctf_link_memb_name_changer>: Likewise. <ctf_link_memb_name_changer_arg>: Likewise. * ctf-create.c (ctf_update): Update accordingly. * ctf-open.c (ctf_file_close): Likewise. * ctf-link.c (ctf_create_per_cu): Apply the cu mapping. (ctf_link_add_cu_mapping): New. (ctf_link_set_memb_name_changer): Likewise. (ctf_change_parent_name): New. (ctf_name_list_accum_cb_arg_t) <dynames>: New, storage for names allocated by the caller's ctf_link_memb_name_changer. <ndynames>: Likewise. (ctf_accumulate_archive_names): Call the ctf_link_memb_name_changer. (ctf_link_write): Likewise (for _CTF_SECTION only): also call ctf_change_parent_name. Free any resulting names.
2019-07-20 21:44:44 +08:00
nfp->ctf_link_memb_name_changer = fp->ctf_link_memb_name_changer;
nfp->ctf_link_memb_name_changer_arg = fp->ctf_link_memb_name_changer_arg;
nfp->ctf_link_variable_filter = fp->ctf_link_variable_filter;
nfp->ctf_link_variable_filter_arg = fp->ctf_link_variable_filter_arg;
libctf, include: support foreign-endianness symtabs with CTF The CTF symbol lookup machinery added recently has one deficit: it assumes the symtab is in the machine's native endianness. This is always true when the linker is writing out symtabs (because cross linkers byteswap symbols only after libctf has been called on them), but may be untrue in the cross case when the linker or another tool (objdump, etc) is reading them. Unfortunately the easy way to model this to the caller, as an endianness field in the ctf_sect_t, is precluded because doing so would change the size of the ctf_sect_t, which would be an ABI break. So, instead, allow the endianness of the symtab to be set after open time, by calling one of the two new API functions ctf_symsect_endianness (for ctf_dict_t's) or ctf_arc_symsect_endianness (for entire ctf_archive_t's). libctf calls these functions automatically for objects opened via any of the BFD-aware mechanisms (ctf_bfdopen, ctf_bfdopen_ctfsect, ctf_fdopen, ctf_open, or ctf_arc_open), but the various mechanisms that just take raw ctf_sect_t's will assume the symtab is in native endianness and need a later call to ctf_*symsect_endianness to adjust it if needed. (This call is basically free if the endianness is actually native: it only costs anything if the symtab endianness was previously guessed wrong, and there is a symtab, and we are using it directly rather than using symtab indexing.) Obviously, calling ctf_lookup_by_symbol or ctf_symbol_next before the symtab endianness is correctly set will probably give wrong answers -- but you can set it at any time as long as it is before then. include/ChangeLog 2020-11-23 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h: Style nit: remove () on function names in comments. (ctf_sect_t): Mention endianness concerns. (ctf_symsect_endianness): New declaration. (ctf_arc_symsect_endianness): Likewise. libctf/ChangeLog 2020-11-23 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_symtab_little_endian>: New. (struct ctf_archive_internal) <ctfi_symsect_little_endian>: Likewise. * ctf-create.c (ctf_serialize): Adjust for new field. * ctf-open.c (init_symtab): Note the semantics of repeated calls. (ctf_symsect_endianness): New. (ctf_bufopen_internal): Set ctf_symtab_little_endian suitably for the native endianness. (_Static_assert): Moved... (swap_thing): ... with this... * swap.h: ... to here. * ctf-util.c (ctf_elf32_to_link_sym): Use it, byteswapping the Elf32_Sym if the ctf_symtab_little_endian demands it. (ctf_elf64_to_link_sym): Likewise swap the Elf64_Sym if needed. * ctf-archive.c (ctf_arc_symsect_endianness): New, set the endianness of the symtab used by the dicts in an archive. (ctf_archive_iter_internal): Initialize to unknown (assumed native, do not call ctf_symsect_endianness). (ctf_dict_open_by_offset): Call ctf_symsect_endianness if need be. (ctf_dict_open_internal): Propagate the endianness down. (ctf_dict_open_sections): Likewise. * ctf-open-bfd.c (ctf_bfdopen_ctfsect): Get the endianness from the struct bfd and pass it down to the archive. * libctf.ver: Add ctf_symsect_endianness and ctf_arc_symsect_endianness.
2020-11-24 05:17:44 +08:00
nfp->ctf_symsect_little_endian = fp->ctf_symsect_little_endian;
libctf, link: add lazy linking: clean up input members: err/warn cleanup This rather large and intertwined pile of changes does three things: First, it transitions from dprintf to ctf_err_warn for things the user might care about: this one file is the major impetus for the ctf_err_warn infrastructure, because things like file names are crucial in linker error messages, and errno values are utterly incapable of communicating them Second, it stabilizes the ctf_link APIs: you can now call ctf_link_add_ctf without a CTF argument (only a NAME), to lazily ctf_open the file with the given NAME when needed, and close it as soon as possible, to save memory. This is not an API change because a null CTF argument was prohibited before now. Since getting CTF directly from files uses ctf_open, passing in only a NAME requires use of libctf, not libctf-nobfd. The linker's behaviour is unchanged, as it still passes in a ctf_archive_t as before. This also let us fix a leak: we were opening ctf_archives and their containing ctf_files, then only closing the files and leaving the archives open. Third, this commit restructures the ctf_link_in_member argument used by the CTF linking machinery and adjusts its users accordingly. We drop two members: - arcname, which is difficult to construct and then only used in error messages (that were only dprintf()ed, so never seen!) - share_mode, since we store the flags passed to ctf_link (including the share mode) in a new ctf_file_t.ctf_link_flags to help dedup get hold of it We rename others whose existing names were fairly dreadful: - done_main_member -> done_parent, using consistent terminology for .ctf as the parent of all archive members - main_input_fp -> in_fp_parent, likewise - file_name -> in_file_name, likewise We add one new member, cu_mapped. Finally, we move the various frees of things like mapping table data to the top-level ctf_link, since deduplicating links will want to do that too. include/ * ctf-api.h (ECTF_NEEDSBFD): New. (ECTF_NERR): Adjust. (ctf_link): Rename share_mode arg to flags. libctf/ * Makefile.am: Set -DNOBFD=1 in libctf-nobfd, and =0 elsewhere. * Makefile.in: Regenerated. * ctf-impl.h (ctf_link_input_name): New. (ctf_file_t) <ctf_link_flags>: New. * ctf-create.c (ctf_serialize): Adjust accordingly. * ctf-link.c: Define ctf_open as weak when PIC. (ctf_arc_close_thunk): Remove unnecessary thunk. (ctf_file_close_thunk): Likewise. (ctf_link_input_name): New. (ctf_link_input_t): New value of the ctf_file_t.ctf_link_input. (ctf_link_input_close): Adjust accordingly. (ctf_link_add_ctf_internal): New, split from... (ctf_link_add_ctf): ... here. Return error if lazy loading of CTF is not possible. Change to just call... (ctf_link_add): ... this new function. (ctf_link_add_cu_mapping): Transition to ctf_err_warn. Drop the ctf_file_close_thunk. (ctf_link_in_member_cb_arg_t) <file_name> Rename to... <in_file_name>: ... this. <arcname>: Drop. <share_mode>: Likewise (migrated to ctf_link_flags). <done_main_member>: Rename to... <done_parent>: ... this. <main_input_fp>: Rename to... <in_fp_parent>: ... this. <cu_mapped>: New. (ctf_link_one_type): Adjuwt accordingly. Transition to ctf_err_warn, removing a TODO. (ctf_link_one_variable): Note a case too common to warn about. Report in the debug stream if a cu-mapped link prevents addition of a conflicting variable. (ctf_link_one_input_archive_member): Adjust. (ctf_link_lazy_open): New, open a CTF archive for linking when needed. (ctf_link_close_one_input_archive): New, close it again. (ctf_link_one_input_archive): Adjust for lazy opening, member renames, and ctf_err_warn transition. Move the empty_link_type_mapping call to... (ctf_link): ... here. Adjut for renamings and thunk removal. Don't spuriously fail if some input contains no CTF data. (ctf_link_write): ctf_err_warn transition. * libctf.ver: Remove not-yet-stable comment.
2020-06-05 02:28:52 +08:00
nfp->ctf_link_flags = fp->ctf_link_flags;
nfp->ctf_dedup_atoms = fp->ctf_dedup_atoms;
nfp->ctf_dedup_atoms_alloc = fp->ctf_dedup_atoms_alloc;
memcpy (&nfp->ctf_dedup, &fp->ctf_dedup, sizeof (fp->ctf_dedup));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
nfp->ctf_snapshot_lu = fp->ctf_snapshots;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
memcpy (&nfp->ctf_lookups, fp->ctf_lookups, sizeof (fp->ctf_lookups));
nfp->ctf_structs = fp->ctf_structs;
nfp->ctf_unions = fp->ctf_unions;
nfp->ctf_enums = fp->ctf_enums;
nfp->ctf_names = fp->ctf_names;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_dthash = NULL;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
ctf_str_free_atoms (nfp);
nfp->ctf_str_atoms = fp->ctf_str_atoms;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
nfp->ctf_prov_strtab = fp->ctf_prov_strtab;
libctf: deduplicate and sort the string table ctf.h states: > [...] the CTF string table does not contain any duplicated strings. Unfortunately this is entirely untrue: libctf has before now made no attempt whatsoever to deduplicate the string table. It computes the string table's length on the fly as it adds new strings to the dynamic CTF file, and ctf_update() just writes each string to the table and notes the current write position as it traverses the dynamic CTF file's data structures and builds the final CTF buffer. There is no global view of the strings and no deduplication. Fix this by erasing the ctf_dtvstrlen dead-reckoning length, and adding a new dynhash table ctf_str_atoms that maps unique strings to a list of references to those strings: a reference is a simple uint32_t * to some value somewhere in the under-construction CTF buffer that needs updating to note the string offset when the strtab is laid out. Adding a string is now a simple matter of calling ctf_str_add_ref(), which adds a new atom to the atoms table, if one doesn't already exist, and adding the location of the reference to this atom to the refs list attached to the atom: this works reliably as long as one takes care to only call ctf_str_add_ref() once the final location of the offset is known (so you can't call it on a temporary structure and then memcpy() that structure into place in the CTF buffer, because the ref will still point to the old location: ctf_update() changes accordingly). Generating the CTF string table is a matter of calling ctf_str_write_strtab(), which counts the length and number of elements in the atoms table using the ctf_dynhash_iter() function we just added, populating an array of pointers into the atoms table and sorting it into order (to help compressors), then traversing this table and emitting it, updating the refs to each atom as we go. The only complexity here is arranging to keep the null string at offset zero, since a lot of code in libctf depends on being able to leave strtab references at 0 to indicate 'no name'. Once the table is constructed and the refs updated, we know how long it is, so we can realloc() the partial CTF buffer we allocated earlier and can copy the table on to the end of it (and purge the refs because they're not needed any more and have been invalidated by the realloc() call in any case). The net effect of all this is a reduction in uncompressed strtab sizes of about 30% (perhaps a quarter to a half of all strings across the Linux kernel are eliminated as duplicates). Of course, duplicated strings are highly redundant, so the space saving after compression is only about 20%: when the other non-strtab sections are factored in, CTF sizes shrink by about 10%. No change in externally-visible API or file format (other than the reduction in pointless redundancy). libctf/ * ctf-impl.h: (struct ctf_strs_writable): New, non-const version of struct ctf_strs. (struct ctf_dtdef): Note that dtd_data.ctt_name is unpopulated. (struct ctf_str_atom): New, disambiguated single string. (struct ctf_str_atom_ref): New, points to some other location that references this string's offset. (struct ctf_file): New members ctf_str_atoms and ctf_str_num_refs. Remove member ctf_dtvstrlen: we no longer track the total strlen as we add strings. (ctf_str_create_atoms): Declare new function in ctf-string.c. (ctf_str_free_atoms): Likewise. (ctf_str_add): Likewise. (ctf_str_add_ref): Likewise. (ctf_str_purge_refs): Likewise. (ctf_str_write_strtab): Likewise. (ctf_realloc): Declare new function in ctf-util.c. * ctf-open.c (ctf_bufopen): Create the atoms table. (ctf_file_close): Destroy it. * ctf-create.c (ctf_update): Copy-and-free it on update. No longer special-case the position of the parname string. Construct the strtab by calling ctf_str_add_ref and ctf_str_write_strtab after the rest of each buffer element is constructed, not via open-coding: realloc the CTF buffer and append the strtab to it. No longer maintain ctf_dtvstrlen. Sort the variable entry table later, after strtab construction. (ctf_copy_membnames): Remove: integrated into ctf_copy_{s,l,e}members. (ctf_copy_smembers): Drop the string offset: call ctf_str_add_ref after buffer element construction instead. (ctf_copy_lmembers): Likewise. (ctf_copy_emembers): Likewise. (ctf_create): No longer maintain the ctf_dtvstrlen. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. * ctf-util.c (ctf_realloc): New, wrapper around realloc that aborts if there are active ctf_str_num_refs. (ctf_strraw): Move to ctf-string.c. (ctf_strptr): Likewise. * ctf-string.c: New file, strtab manipulation. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate.
2019-06-27 20:51:10 +08:00
fp->ctf_str_atoms = NULL;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
fp->ctf_prov_strtab = NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
libctf, ld, binutils: add textual error/warning reporting for libctf This commit adds a long-missing piece of infrastructure to libctf: the ability to report errors and warnings using all the power of printf, rather than being restricted to one errno value. Internally, libctf calls ctf_err_warn() to add errors and warnings to a list: a new iterator ctf_errwarning_next() then consumes this list one by one and hands it to the caller, which can free it. New errors and warnings are added until the list is consumed by the caller or the ctf_file_t is closed, so you can dump them at intervals. The caller can of course choose to print only those warnings it wants. (I am not sure whether we want objdump, readelf or ld to print warnings or not: right now I'm printing them, but maybe we only want to print errors? This entirely depends on whether warnings are voluminous things describing e.g. the inability to emit single types because of name clashes or something. There are no users of this infrastructure yet, so it's hard to say.) There is no internationalization here yet, but this at least adds a place where internationalization can be added, to one of ctf_errwarning_next or ctf_err_warn. We also provide a new ctf_assert() function which uses this infrastructure to provide non-fatal assertion failures while emitting an assert-like string to the caller: to save space and avoid needlessly duplicating unchanging strings, the assertion test is inlined but the print-things-out failure case is not. All assertions in libctf will be converted to use this machinery in future commits and propagate assertion-failure errors up, so that the linker in particular cannot be killed by libctf assertion failures when it could perfectly well just print warnings and drop the CTF section. include/ * ctf-api.h (ECTF_INTERNAL): Adjust error text. (ctf_errwarning_next): New. libctf/ * ctf-impl.h (ctf_assert): New. (ctf_err_warning_t): Likewise. (ctf_file_t) <ctf_errs_warnings>: Likewise. (ctf_err_warn): New prototype. (ctf_assert_fail_internal): Likewise. * ctf-inlines.h (ctf_assert_internal): Likewise. * ctf-open.c (ctf_file_close): Free ctf_errs_warnings. * ctf-create.c (ctf_serialize): Copy it on serialization. * ctf-subr.c (ctf_err_warn): New, add an error/warning. (ctf_errwarning_next): New iterator, free and pass back errors/warnings in succession. * libctf.ver (ctf_errwarning_next): Add. ld/ * ldlang.c (lang_ctf_errs_warnings): New, print CTF errors and warnings. Assert when libctf asserts. (lang_merge_ctf): Call it. (land_write_ctf): Likewise. binutils/ * objdump.c (ctf_archive_member): Print CTF errors and warnings. * readelf.c (dump_ctf_archive_member): Likewise.
2020-06-04 22:07:54 +08:00
memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t));
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
fp->ctf_add_processing = NULL;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
fp->ctf_ptrtab = NULL;
libctf: fix lookups of pointers by name in parent dicts When you look up a type by name using ctf_lookup_by_name, in most cases libctf can just strip off any qualifiers and look for the name, but for pointer types this doesn't work, since the caller will want the pointer type itself. But pointer types are nameless, and while they cite the types they point to, looking up a type by name requires a link going the *other way*, from the type pointed to to the pointer type that points to it. libctf has always built this up at open time: ctf_ptrtab is an array of type indexes pointing from the index of every type to the index of the type that points to it. But because it is built up at open time (and because it uses type indexes and not type IDs) it is restricted to working within a single dict and ignoring parent/child relationships. This is normally invisible, unless you manage to get a dict with a type in the parent but the only pointer to it in a child. The ctf_ptrtab will not track this relationship, so lookups of this pointer type by name will fail. Since which type is in the parent and which in the child is largely opaque to the user (which goes where is up to the deduplicator, and it can and does reshuffle things to save space), this leads to a very bad user experience, with an obviously-visible pointer type which ctf_lookup_by_name claims doesn't exist. The fix is to have another array, ctf_pptrtab, which is populated in child dicts: like the parent's ctf_ptrtab, it has one element per type in the parent, but is all zeroes except for those types which are pointed to by types in the child: so it maps parent dict indices to child dict indices. The array is grown, and new child types scanned, whenever a lookup happens and new types have been added to the child since the last time a lookup happened that might need the pptrtab. (So for non-writable dicts, this only happens once, since new types cannot be added to non-writable dicts at all.) Since this introduces new complexity (involving updating only part of the ctf_pptrtab) which is only seen when a writable dict is in use, we introduce a new libctf-writable testsuite that contains lookup tests with no corresponding CTF-containing .c files (which can thus be run even on platforms with no .ctf-section support in the linker yet), and add a test to check that creation of pointers in children to types in parents and a following lookup by name works as expected. The non- writable case is tested in a new libctf-regression testsuite which is used to track now-fixed outright bugs in libctf. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_pptrtab>: New. <ctf_pptrtab_len>: New. <ctf_pptrtab_typemax>: New. * ctf-create.c (ctf_serialize): Update accordingly. (ctf_add_reftype): Note that we don't need to update pptrtab here, despite updating ptrtab. * ctf-open.c (ctf_dict_close): Destroy the pptrtab. (ctf_import): Likewise. (ctf_import_unref): Likewise. * ctf-lookup.c (grow_pptrtab): New. (refresh_pptrtab): New, update a pptrtab. (ctf_lookup_by_name): Turn into a wrapper around (and rename to)... (ctf_lookup_by_name_internal): ... this: construct the pptrtab, and use it in addition to the parent's ptrtab when parent dicts are searched. * testsuite/libctf-regression/regression.exp: New testsuite for regression tests. * testsuite/libctf-regression/pptrtab*: New test. * testsuite/libctf-writable/writable.exp: New testsuite for tests of writable CTF dicts. * testsuite/libctf-writable/pptrtab*: New test.
2021-01-05 21:25:56 +08:00
fp->ctf_pptrtab = NULL;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
fp->ctf_funcidx_names = NULL;
fp->ctf_objtidx_names = NULL;
fp->ctf_funcidx_sxlate = NULL;
fp->ctf_objtidx_sxlate = NULL;
fp->ctf_objthash = NULL;
fp->ctf_funchash = NULL;
fp->ctf_dynsyms = NULL;
fp->ctf_dynsymidx = NULL;
libctf: add the ctf_link machinery This is the start of work on the core of the linking mechanism for CTF sections. This commit handles the type and string sections. The linker calls these functions in sequence: ctf_link_add_ctf: to add each CTF section in the input in turn to a newly-created ctf_file_t (which will appear in the output, and which itself will become the shared parent that contains types that all TUs have in common (in all link modes) and all types that do not have conflicting definitions between types (by default). Input files that are themselves products of ld -r are supported, though this is not heavily tested yet. ctf_link: called once all input files are added to merge the types in all the input containers into the output container, eliminating duplicates. ctf_link_add_strtab: called once the ELF string table is finalized and all its offsets are known, this calls a callback provided by the linker which returns the string content and offset of every string in the ELF strtab in turn: all these strings which appear in the input CTF strtab are eliminated from it in favour of the ELF strtab: equally, any strings that only appear in the input strtab will reappear in the internal CTF strtab of the output. ctf_link_shuffle_syms (not yet implemented): called once the ELF symtab is finalized, this calls a callback provided by the linker which returns information on every symbol in turn as a ctf_link_sym_t. This is then used to shuffle the function info and data object sections in the CTF section into symbol table order, eliminating the index sections which map those sections to symbol names before that point. Currently just returns ECTF_NOTYET. ctf_link_write: Returns a buffer containing either a serialized ctf_file_t (if there are no types with conflicting definitions in the object files in the link) or a ctf_archive_t containing a large ctf_file_t (the common types) and a bunch of small ones named after individual CUs in which conflicting types are found (containing the conflicting types, and all types that reference them). A threshold size above which compression takes place is passed as one parameter. (Currently, only gzip compression is supported, but I hope to add lzma as well.) Lifetime rules for this are simple: don't close the input CTF files until you've called ctf_link for the last time. We do not assume that symbols or strings passed in by the callback outlast the call to ctf_link_add_strtab or ctf_link_shuffle_syms. Right now, the duplicate elimination mechanism is the one already present as part of the ctf_add_type function, and is not particularly good: it misses numerous actual duplicates, and the conflicting-types detection hardly ever reports that types conflict, even when they do (one of them just tends to get silently dropped): it is also very slow. This will all be fixed in the next few weeks, but the fix hardly touches any of this code, and the linker does work without it, just not as well as it otherwise might. (And when no CTF section is present, there is no effect on performance, of course. So only people using a trunk GCC with not-yet-committed patches will even notice. By the time it gets upstream, things should be better.) v3: Fix error handling. v4: check for strdup failure. v5: fix tabdamage. include/ * ctf-api.h (struct ctf_link_sym): New, a symbol in flight to the libctf linking machinery. (CTF_LINK_SHARE_UNCONFLICTED): New. (CTF_LINK_SHARE_DUPLICATED): New. (ECTF_LINKADDEDLATE): New, replacing ECTF_UNUSED. (ECTF_NOTYET): New, a 'not yet implemented' message. (ctf_link_add_ctf): New, add an input file's CTF to the link. (ctf_link): New, merge the type and string sections. (ctf_link_strtab_string_f): New, callback for feeding strtab info. (ctf_link_iter_symbol_f): New, callback for feeding symtab info. (ctf_link_add_strtab): New, tell the CTF linker about the ELF strtab's strings. (ctf_link_shuffle_syms): New, ask the CTF linker to shuffle its symbols into symtab order. (ctf_link_write): New, ask the CTF linker to write the CTF out. libctf/ * ctf-link.c: New file, linking of the string and type sections. * Makefile.am (libctf_a_SOURCES): Add it. * Makefile.in: Regenerate. * ctf-impl.h (ctf_file_t): New fields ctf_link_inputs, ctf_link_outputs. * ctf-create.c (ctf_update): Update accordingly. * ctf-open.c (ctf_file_close): Likewise. * ctf-error.c (_ctf_errlist): Updated with new errors.
2019-07-14 04:06:55 +08:00
fp->ctf_link_inputs = NULL;
fp->ctf_link_outputs = NULL;
libctf: support getting strings from the ELF strtab The CTF file format has always supported "external strtabs", which internally are strtab offsets with their MSB on: such refs get their strings from the strtab passed in at CTF file open time: this is usually intended to be the ELF strtab, and that's what this implementation is meant to support, though in theory the external strtab could come from anywhere. This commit adds support for these external strings in the ctf-string.c strtab tracking layer. It's quite easy: we just add a field csa_offset to the atoms table that tracks all strings: this field tracks the offset of the string in the ELF strtab (with its MSB already on, courtesy of a new macro CTF_SET_STID), and adds a new function that sets the csa_offset to the specified offset (plus MSB). Then we just need to avoid writing out strings to the internal strtab if they have csa_offset set, and note that the internal strtab is shorter than it might otherwise be. (We could in theory save a little more time here by eschewing sorting such strings, since we never actually write the strings out anywhere, but that would mean storing them separately and it's just not worth the complexity cost until profiling shows it's worth doing.) We also have to go through a bit of extra effort at variable-sorting time. This was previously using direct references to the internal strtab: it couldn't use ctf_strptr or ctf_strraw because the new strtab is not yet ready to put in its usual field (in a ctf_file_t that hasn't even been allocated yet at this stage): but now we're using the external strtab, this will no longer do because it'll be looking things up in the wrong strtab, with disastrous results. Instead, pass the new internal strtab in to a new ctf_strraw_explicit function which is just like ctf_strraw except you can specify a ne winternal strtab to use. But even now that it is using a new internal strtab, this is not quite enough: it can't look up strings in the external strtab because ld hasn't written it out yet, and when it does will write it straight to disk. Instead, when we write the internal strtab, note all the offset -> string mappings that we have noted belong in the *external* strtab to a new "synthetic external strtab" dynhash, ctf_syn_ext_strtab, and look in there at ctf_strraw time if it is set. This uses minimal extra memory (because only strings in the external strtab that we actually use are stored, and even those come straight out of the atoms table), but let both variable sorting and name interning when ctf_bufopen is next called work fine. (This also means that we don't need to filter out spurious ECTF_STRTAB warnings from ctf_bufopen but can pass them back to the caller, once we wrap ctf_bufopen so that we have a new internal variant of ctf_bufopen etc that we can pass the synthetic external strtab to. That error has been filtered out since the days of Solaris libctf, which didn't try to handle the problem of getting external strtabs right at construction time at all.) v3: add the synthetic strtab and all associated machinery. v5: fix tabdamage. include/ * ctf.h (CTF_SET_STID): New. libctf/ * ctf-impl.h (ctf_str_atom_t) <csa_offset>: New field. (ctf_file_t) <ctf_syn_ext_strtab>: Likewise. (ctf_str_add_ref): Name the last arg. (ctf_str_add_external) New. (ctf_str_add_strraw_explicit): Likewise. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. * ctf-string.c (ctf_strraw_explicit): Split from... (ctf_strraw): ... here, with new support for ctf_syn_ext_strtab. (ctf_str_add_ref_internal): Return the atom, not the string. (ctf_str_add): Adjust accordingly. (ctf_str_add_ref): Likewise. Move up in the file. (ctf_str_add_external): New: update the csa_offset. (ctf_str_count_strtab): Only account for strings with no csa_offset in the internal strtab length. (ctf_str_write_strtab): If the csa_offset is set, update the string's refs without writing the string out, and update the ctf_syn_ext_strtab. Make OOM handling less ugly. * ctf-create.c (struct ctf_sort_var_arg_cb): New. (ctf_update): Handle failure to populate the strtab. Pass in the new ctf_sort_var arg. Adjust for ctf_syn_ext_strtab addition. Call ctf_simple_open_internal, not ctf_simple_open. (ctf_sort_var): Call ctf_strraw_explicit rather than looking up strings by hand. * ctf-hash.c (ctf_hash_insert_type): Likewise (but using ctf_strraw). Adjust to diagnose ECTF_STRTAB nonetheless. * ctf-open.c (init_types): No longer filter out ECTF_STRTAB. (ctf_file_close): Destroy the ctf_syn_ext_strtab. (ctf_simple_open): Rename to, and reimplement as a wrapper around... (ctf_simple_open_internal): ... this new function, which calls ctf_bufopen_internal. (ctf_bufopen): Rename to, and reimplement as a wrapper around... (ctf_bufopen_internal): ... this new function, which sets ctf_syn_ext_strtab.
2019-07-14 03:33:01 +08:00
fp->ctf_syn_ext_strtab = NULL;
libctf, link: redo cu-mapping handling Now a bunch of stuff that doesn't apply to ld or any normal use of libctf, piled into one commit so that it's easier to ignore. The cu-mapping machinery associates incoming compilation unit names with outgoing names of CTF dictionaries that should correspond to them, for non-gdb CTF consumers that would like to group multiple TUs into a single child dict if conflicting types are found in it (the existing use case is one kernel module, one child CTF dict, even if the kernel module is composed of multiple CUs). The upcoming deduplicator needs to track not only the mapping from incoming CU name to outgoing dict name, but the inverse mapping from outgoing dict name to incoming CU name, so it can work over every CTF dict we might see in the output and link into it. So rejig the ctf-link machinery to do that. Simultaneously (because they are closely associated and were written at the same time), we add a new CTF_LINK_EMPTY_CU_MAPPINGS flag to ctf_link, which tells the ctf_link machinery to create empty child dicts for each outgoing CU mapping even if no CUs that correspond to it exist in the link. This is a bit (OK, quite a lot) of a waste of space, but some existing consumers require it. (Nobody else should use it.) Its value is not consecutive with existing CTF_LINK flag values because we're about to add more flags that are conceptually closer to the existing ones than this one is. include/ * ctf-api.h (CTF_LINK_EMPTY_CU_MAPPINGS): New. libctf/ * ctf-impl.h (ctf_file_t): Improve comments. <ctf_link_cu_mapping>: Split into... <ctf_link_in_cu_mapping>: ... this... <ctf_link_out_cu_mapping>: ... and this. * ctf-create.c (ctf_serialize): Adjust. * ctf-open.c (ctf_file_close): Likewise. * ctf-link.c (ctf_create_per_cu): Look things up in the in_cu_mapping instead of the cu_mapping. (ctf_link_add_cu_mapping): The deduplicating link will define what happens if many FROMs share a TO. (ctf_link_add_cu_mapping): Create in_cu_mapping and out_cu_mapping. Do not create ctf_link_outputs here any more, or create per-CU dicts here: they are already created when needed. (ctf_link_one_variable): Log a debug message if we skip a variable due to its type being concealed in a CU-mapped link. (This is probably too common a case to make into a warning.) (ctf_link): Create empty per-CU dicts if requested.
2020-06-06 00:36:16 +08:00
fp->ctf_link_in_cu_mapping = NULL;
fp->ctf_link_out_cu_mapping = NULL;
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
fp->ctf_link_type_mapping = NULL;
fp->ctf_dedup_atoms = NULL;
fp->ctf_dedup_atoms_alloc = NULL;
libctf: sort out potential refcount loops When you link TUs that contain conflicting types together, the resulting CTF section is an archive containing many CTF dicts. These dicts appear in ctf_link_outputs of the shared dict, with each ctf_import'ing that shared dict. ctf_importing a dict bumps its refcount to stop it going away while it's in use -- but if the shared dict (whose refcount is bumped) has the child dict (doing the bumping) in its ctf_link_outputs, we have a refcount loop, since the child dict only un-ctf_imports and drops the parent's refcount when it is freed, but the child is only freed when the parent's refcount falls to zero. (In the future, this will be able to go wrong on the inputs too, when an ld -r'ed deduplicated output with conflicts is relinked. Right now this cannot happen because we don't ctf_import such dicts at all. This will be fixed in a later commit in this series.) Fix this by introducing an internal-use-only ctf_import_unref function that imports a parent dict *witthout* bumping the parent's refcount, and using it when we create per-CU outputs. This function is only safe to use if you know the parent cannot go away while the child exists: but if the parent *owns* the child, as here, this is necessarily true. Record in the ctf_file_t whether a parent was imported via ctf_import or ctf_import_unref, so that if you do another ctf_import later on (or a ctf_import_unref) it can decide whether to drop the refcount of the existing parent being replaced depending on which function you used to import that one. Adjust ctf_serialize so that rather than doing a ctf_import (which is wrong if the original import was ctf_import_unref'fed), we just copy the parent field and refcount over and forcibly flip the unref flag on on the old copy we are going to discard. ctf_file_close also needs a bit of tweaking to only close the parent if it was not imported with ctf_import_unref: while we're at it, guard against repeated closes with a refcount of zero and stop them causing double-frees, even if destruction of things freed *inside* ctf_file_close cause such recursion. Verified no leaks or accesses to freed memory after all of this with valgrind. (It was leak-happy before.) libctf/ * ctf-impl.c (ctf_file_t) <ctf_parent_unreffed>: New. (ctf_import_unref): New. * ctf-open.c (ctf_file_close) Drop the refcount all the way to zero. Don't recurse back in if the refcount is already zero. (ctf_import): Check ctf_parent_unreffed before deciding whether to close a pre-existing parent. Set it to zero. (ctf_import_unreffed): New, as above, setting ctf_parent_unreffed to 1. * ctf-create.c (ctf_serialize): Do not ctf_import into the new child: use direct assignment, and set unreffed on the new and old children. * ctf-link.c (ctf_create_per_cu): Import the parent using ctf_import_unreffed.
2020-06-05 00:30:01 +08:00
fp->ctf_parent_unreffed = 1;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_dvhash = NULL;
memset (&fp->ctf_dvdefs, 0, sizeof (ctf_list_t));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
memset (fp->ctf_lookups, 0, sizeof (fp->ctf_lookups));
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
memset (&fp->ctf_in_flight_dynsyms, 0, sizeof (fp->ctf_in_flight_dynsyms));
memset (&fp->ctf_dedup, 0, sizeof (fp->ctf_dedup));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
fp->ctf_structs.ctn_writable = NULL;
fp->ctf_unions.ctn_writable = NULL;
fp->ctf_enums.ctn_writable = NULL;
fp->ctf_names.ctn_writable = NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
memcpy (&ofp, fp, sizeof (ctf_dict_t));
memcpy (fp, nfp, sizeof (ctf_dict_t));
memcpy (nfp, &ofp, sizeof (ctf_dict_t));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
nfp->ctf_refcnt = 1; /* Force nfp to be freed. */
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_close (nfp);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return 0;
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
symerr:
ctf_err_warn (fp, 0, err, _("error serializing symtypetabs"));
goto err;
oom:
free (buf);
free (sym_name_order);
return (ctf_set_errno (fp, EAGAIN));
err:
free (buf);
free (sym_name_order);
return -1; /* errno is set for us. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
ctf_names_t *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_name_table (ctf_dict_t *fp, int kind)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
switch (kind)
{
case CTF_K_STRUCT:
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return &fp->ctf_structs;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
case CTF_K_UNION:
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return &fp->ctf_unions;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
case CTF_K_ENUM:
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return &fp->ctf_enums;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
default:
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return &fp->ctf_names;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
const char *name;
if (ctf_dynhash_insert (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type,
dtd) < 0)
{
ctf_set_errno (fp, ENOMEM);
return -1;
}
if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (ctf_dynhash_insert (ctf_name_table (fp, kind)->ctn_writable,
(char *) name, (void *) (uintptr_t)
dtd->dtd_type) < 0)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
{
ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t)
dtd->dtd_type);
ctf_set_errno (fp, ENOMEM);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return -1;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
ctf_list_append (&fp->ctf_dtdefs, dtd);
return 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
void
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dmdef_t *dmd, *nmd;
int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
int name_kind = kind;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
const char *name;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
switch (kind)
{
case CTF_K_STRUCT:
case CTF_K_UNION:
case CTF_K_ENUM:
for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
dmd != NULL; dmd = nmd)
{
if (dmd->dmd_name != NULL)
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dmd->dmd_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
nmd = ctf_list_next (dmd);
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dmd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
break;
case CTF_K_FUNCTION:
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dtd->dtd_u.dtu_argv);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
break;
case CTF_K_FORWARD:
name_kind = dtd->dtd_data.ctt_type;
break;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dynhash_remove (ctf_name_table (fp, name_kind)->ctn_writable,
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
name);
ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
ctf_list_delete (&fp->ctf_dtdefs, dtd);
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dtd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
ctf_dtdef_t *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dtd_lookup (const ctf_dict_t *fp, ctf_id_t type)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_dtdef_t *)
ctf_dynhash_lookup (fp->ctf_dthash, (void *) (uintptr_t) type);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
ctf_dtdef_t *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dynamic_type (const ctf_dict_t *fp, ctf_id_t id)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_id_t idx;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (!(fp->ctf_flags & LCTF_RDWR))
return NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT (fp, id))
fp = fp->ctf_parent;
idx = LCTF_TYPE_TO_INDEX(fp, id);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((unsigned long) idx <= fp->ctf_typemax)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return ctf_dtd_lookup (fp, id);
return NULL;
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dvd_insert (ctf_dict_t *fp, ctf_dvdef_t *dvd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
{
ctf_set_errno (fp, ENOMEM);
return -1;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_list_append (&fp->ctf_dvdefs, dvd);
return 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
void
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dvd_delete (ctf_dict_t *fp, ctf_dvdef_t *dvd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dynhash_remove (fp->ctf_dvhash, dvd->dvd_name);
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dvd->dvd_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_list_delete (&fp->ctf_dvdefs, dvd);
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dvd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
ctf_dvdef_t *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dvd_lookup (const ctf_dict_t *fp, const char *name)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_dvdef_t *) ctf_dynhash_lookup (fp->ctf_dvhash, name);
}
/* Discard all of the dynamic type definitions and variable definitions that
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
have been added to the dict since the last call to ctf_update(). We locate
such types by scanning the dtd list and deleting elements that have type IDs
greater than ctf_dtoldid, which is set by ctf_update(), above, and by
scanning the variable list and deleting elements that have update IDs equal
to the current value of the last-update snapshot count (indicating that they
were added after the most recent call to ctf_update()). */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_discard (ctf_dict_t *fp)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_snapshot_id_t last_update =
{ fp->ctf_dtoldid,
fp->ctf_snapshot_lu + 1 };
/* Update required? */
if (!(fp->ctf_flags & LCTF_DIRTY))
return 0;
return (ctf_rollback (fp, last_update));
}
ctf_snapshot_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_snapshot (ctf_dict_t *fp)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_snapshot_id_t snapid;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
snapid.dtd_id = fp->ctf_typemax;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
snapid.snapshot_id = fp->ctf_snapshots++;
return snapid;
}
/* Like ctf_discard(), only discards everything after a particular ID. */
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dtdef_t *dtd, *ntd;
ctf_dvdef_t *dvd, *nvd;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (fp->ctf_snapshot_lu >= id.snapshot_id)
return (ctf_set_errno (fp, ECTF_OVERROLLBACK));
for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
{
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
int kind;
const char *name;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ntd = ctf_list_next (dtd);
if (LCTF_TYPE_TO_INDEX (fp, dtd->dtd_type) <= id.dtd_id)
continue;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
if (kind == CTF_K_FORWARD)
kind = dtd->dtd_data.ctt_type;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
{
ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable,
name);
ctf_str_remove_ref (fp, name, &dtd->dtd_data.ctt_name);
}
ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_dtd_delete (fp, dtd);
}
for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
{
nvd = ctf_list_next (dvd);
if (dvd->dvd_snapshots <= id.snapshot_id)
continue;
ctf_dvd_delete (fp, dvd);
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
fp->ctf_typemax = id.dtd_id;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_snapshots = id.snapshot_id;
if (fp->ctf_snapshots == fp->ctf_snapshot_lu)
fp->ctf_flags &= ~LCTF_DIRTY;
return 0;
}
static ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_dtdef_t **rp)
{
ctf_dtdef_t *dtd;
ctf_id_t type;
if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
return (ctf_set_errno (fp, EINVAL));
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) >= CTF_MAX_TYPE)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, ECTF_FULL));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) == (CTF_MAX_PTYPE - 1))
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, ECTF_FULL));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
/* Make sure ptrtab always grows to be big enough for all types. */
if (ctf_grow_ptrtab (fp) < 0)
return CTF_ERR; /* errno is set for us. */
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((dtd = malloc (sizeof (ctf_dtdef_t))) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ++fp->ctf_typemax;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
type = LCTF_INDEX_TO_TYPE (fp, type, (fp->ctf_flags & LCTF_CHILD));
memset (dtd, 0, sizeof (ctf_dtdef_t));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
dtd->dtd_data.ctt_name = ctf_str_add_ref (fp, name, &dtd->dtd_data.ctt_name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
dtd->dtd_type = type;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (dtd->dtd_data.ctt_name == 0 && name != NULL && name[0] != '\0')
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dtd);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return (ctf_set_errno (fp, EAGAIN));
}
if (ctf_dtd_insert (fp, dtd, flag, kind) < 0)
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dtd);
return CTF_ERR; /* errno is set for us. */
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_flags |= LCTF_DIRTY;
*rp = dtd;
return type;
}
/* When encoding integer sizes, we want to convert a byte count in the range
1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
is a clever implementation from "Hacker's Delight" by Henry Warren, Jr. */
static size_t
clp2 (size_t x)
{
x--;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return (x + 1);
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_encoded (ctf_dict_t *fp, uint32_t flag,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const char *name, const ctf_encoding_t *ep, uint32_t kind)
{
ctf_dtdef_t *dtd;
ctf_id_t type;
if (ep == NULL)
return (ctf_set_errno (fp, EINVAL));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, name, kind, &dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
/ CHAR_BIT);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
dtd->dtd_u.dtu_enc = *ep;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_reftype (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dtdef_t *dtd;
ctf_id_t type;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
int child = fp->ctf_flags & LCTF_CHILD;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EINVAL));
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, NULL, kind, &dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, 0);
dtd->dtd_data.ctt_type = (uint32_t) ref;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (kind != CTF_K_POINTER)
return type;
/* If we are adding a pointer, update the ptrtab, both the directly pointed-to
type and (if an anonymous typedef node is being pointed at) the type that
points at too. Note that ctf_typemax is at this point one higher than we
want to check against, because it's just been incremented for the addition
libctf: fix lookups of pointers by name in parent dicts When you look up a type by name using ctf_lookup_by_name, in most cases libctf can just strip off any qualifiers and look for the name, but for pointer types this doesn't work, since the caller will want the pointer type itself. But pointer types are nameless, and while they cite the types they point to, looking up a type by name requires a link going the *other way*, from the type pointed to to the pointer type that points to it. libctf has always built this up at open time: ctf_ptrtab is an array of type indexes pointing from the index of every type to the index of the type that points to it. But because it is built up at open time (and because it uses type indexes and not type IDs) it is restricted to working within a single dict and ignoring parent/child relationships. This is normally invisible, unless you manage to get a dict with a type in the parent but the only pointer to it in a child. The ctf_ptrtab will not track this relationship, so lookups of this pointer type by name will fail. Since which type is in the parent and which in the child is largely opaque to the user (which goes where is up to the deduplicator, and it can and does reshuffle things to save space), this leads to a very bad user experience, with an obviously-visible pointer type which ctf_lookup_by_name claims doesn't exist. The fix is to have another array, ctf_pptrtab, which is populated in child dicts: like the parent's ctf_ptrtab, it has one element per type in the parent, but is all zeroes except for those types which are pointed to by types in the child: so it maps parent dict indices to child dict indices. The array is grown, and new child types scanned, whenever a lookup happens and new types have been added to the child since the last time a lookup happened that might need the pptrtab. (So for non-writable dicts, this only happens once, since new types cannot be added to non-writable dicts at all.) Since this introduces new complexity (involving updating only part of the ctf_pptrtab) which is only seen when a writable dict is in use, we introduce a new libctf-writable testsuite that contains lookup tests with no corresponding CTF-containing .c files (which can thus be run even on platforms with no .ctf-section support in the linker yet), and add a test to check that creation of pointers in children to types in parents and a following lookup by name works as expected. The non- writable case is tested in a new libctf-regression testsuite which is used to track now-fixed outright bugs in libctf. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (ctf_dict_t) <ctf_pptrtab>: New. <ctf_pptrtab_len>: New. <ctf_pptrtab_typemax>: New. * ctf-create.c (ctf_serialize): Update accordingly. (ctf_add_reftype): Note that we don't need to update pptrtab here, despite updating ptrtab. * ctf-open.c (ctf_dict_close): Destroy the pptrtab. (ctf_import): Likewise. (ctf_import_unref): Likewise. * ctf-lookup.c (grow_pptrtab): New. (refresh_pptrtab): New, update a pptrtab. (ctf_lookup_by_name): Turn into a wrapper around (and rename to)... (ctf_lookup_by_name_internal): ... this: construct the pptrtab, and use it in addition to the parent's ptrtab when parent dicts are searched. * testsuite/libctf-regression/regression.exp: New testsuite for regression tests. * testsuite/libctf-regression/pptrtab*: New test. * testsuite/libctf-writable/writable.exp: New testsuite for tests of writable CTF dicts. * testsuite/libctf-writable/pptrtab*: New test.
2021-01-05 21:25:56 +08:00
of this type. The pptrtab is lazily-updated as needed, so is not touched
here. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
uint32_t type_idx = LCTF_TYPE_TO_INDEX (fp, type);
uint32_t ref_idx = LCTF_TYPE_TO_INDEX (fp, ref);
if (LCTF_TYPE_ISCHILD (fp, ref) == child
&& ref_idx < fp->ctf_typemax)
{
fp->ctf_ptrtab[ref_idx] = type_idx;
ctf_id_t refref_idx = LCTF_TYPE_TO_INDEX (fp, dtd->dtd_data.ctt_type);
if (tmp == fp
&& (LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) == CTF_K_TYPEDEF)
&& strcmp (ctf_strptr (fp, dtd->dtd_data.ctt_name), "") == 0
&& refref_idx < fp->ctf_typemax)
fp->ctf_ptrtab[refref_idx] = type_idx;
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_slice (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const ctf_encoding_t *ep)
{
ctf_dtdef_t *dtd;
ctf_id_t resolved_ref = ref;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_id_t type;
int kind;
const ctf_type_t *tp;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (ep == NULL)
return (ctf_set_errno (fp, EINVAL));
if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
return (ctf_set_errno (fp, ECTF_SLICEOVERFLOW));
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EINVAL));
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (ref != 0 && ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL))
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
/* Make sure we ultimately point to an integral type. We also allow slices to
point to the unimplemented type, for now, because the compiler can emit
such slices, though they're not very much use. */
resolved_ref = ctf_type_resolve_unsliced (tmp, ref);
kind = ctf_type_kind_unsliced (tmp, resolved_ref);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
(kind != CTF_K_ENUM)
&& (ref != 0))
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, ECTF_NOTINTFP));
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_SLICE, &dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, CHAR_BIT)
/ CHAR_BIT);
dtd->dtd_u.dtu_slice.cts_type = (uint32_t) ref;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_integer (ctf_dict_t *fp, uint32_t flag,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const char *name, const ctf_encoding_t *ep)
{
return (ctf_add_encoded (fp, flag, name, ep, CTF_K_INTEGER));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_float (ctf_dict_t *fp, uint32_t flag,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const char *name, const ctf_encoding_t *ep)
{
return (ctf_add_encoded (fp, flag, name, ep, CTF_K_FLOAT));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_pointer (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_reftype (fp, flag, ref, CTF_K_POINTER));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_array (ctf_dict_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dtdef_t *dtd;
ctf_id_t type;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (arp == NULL)
return (ctf_set_errno (fp, EINVAL));
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (arp->ctr_contents != 0
&& ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
tmp = fp;
if (ctf_lookup_by_id (&tmp, arp->ctr_index) == NULL)
return CTF_ERR; /* errno is set for us. */
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
if (ctf_type_kind (fp, arp->ctr_index) == CTF_K_FORWARD)
{
ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
_("ctf_add_array: index type %lx is incomplete"),
arp->ctr_contents);
return (ctf_set_errno (fp, ECTF_INCOMPLETE));
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_ARRAY, &dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0);
dtd->dtd_data.ctt_size = 0;
dtd->dtd_u.dtu_arr = *arp;
return type;
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_set_array (ctf_dict_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (dtd == NULL
|| LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
return (ctf_set_errno (fp, ECTF_BADID));
fp->ctf_flags |= LCTF_DIRTY;
dtd->dtd_u.dtu_arr = *arp;
return 0;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_function (ctf_dict_t *fp, uint32_t flag,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
{
ctf_dtdef_t *dtd;
ctf_id_t type;
uint32_t vlen;
uint32_t *vdat = NULL;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
size_t i;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
|| (ctc->ctc_argc != 0 && argv == NULL))
return (ctf_set_errno (fp, EINVAL));
vlen = ctc->ctc_argc;
if (ctc->ctc_flags & CTF_FUNC_VARARG)
vlen++; /* Add trailing zero to indicate varargs (see below). */
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (ctc->ctc_return != 0
&& ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
if (vlen > CTF_MAX_VLEN)
return (ctf_set_errno (fp, EOVERFLOW));
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if (vlen != 0 && (vdat = malloc (sizeof (ctf_id_t) * vlen)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
for (i = 0; i < ctc->ctc_argc; i++)
{
tmp = fp;
if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
{
free (vdat);
return CTF_ERR; /* errno is set for us. */
}
vdat[i] = (uint32_t) argv[i];
}
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
&dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (vdat);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
}
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
if (ctc->ctc_flags & CTF_FUNC_VARARG)
vdat[vlen - 1] = 0; /* Add trailing zero to indicate varargs. */
dtd->dtd_u.dtu_argv = vdat;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_struct_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
size_t size)
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
/* Promote root-visible forwards to structs. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (name != NULL)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
dtd = ctf_dtd_lookup (fp, type);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
else if ((type = ctf_add_generic (fp, flag, name, CTF_K_STRUCT,
&dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_STRUCT, flag, 0);
if (size > CTF_MAX_SIZE)
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
}
else
dtd->dtd_data.ctt_size = (uint32_t) size;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_struct (ctf_dict_t *fp, uint32_t flag, const char *name)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_struct_sized (fp, flag, name, 0));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_union_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
size_t size)
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
/* Promote root-visible forwards to unions. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (name != NULL)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
dtd = ctf_dtd_lookup (fp, type);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
else if ((type = ctf_add_generic (fp, flag, name, CTF_K_UNION,
&dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_UNION, flag, 0);
if (size > CTF_MAX_SIZE)
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
}
else
dtd->dtd_data.ctt_size = (uint32_t) size;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_union (ctf_dict_t *fp, uint32_t flag, const char *name)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_union_sized (fp, flag, name, 0));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_enum (ctf_dict_t *fp, uint32_t flag, const char *name)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
/* Promote root-visible forwards to enums. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (name != NULL)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD)
dtd = ctf_dtd_lookup (fp, type);
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
else if ((type = ctf_add_generic (fp, flag, name, CTF_K_ENUM,
&dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0);
dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_enum_encoded (ctf_dict_t *fp, uint32_t flag, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
const ctf_encoding_t *ep)
{
ctf_id_t type = 0;
/* First, create the enum if need be, using most of the same machinery as
ctf_add_enum(), to ensure that we do not allow things past that are not
enums or forwards to them. (This includes other slices: you cannot slice a
slice, which would be a useless thing to do anyway.) */
if (name != NULL)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (type != 0)
{
if ((ctf_type_kind (fp, type) != CTF_K_FORWARD) &&
(ctf_type_kind_unsliced (fp, type) != CTF_K_ENUM))
return (ctf_set_errno (fp, ECTF_NOTINTFP));
}
else if ((type = ctf_add_enum (fp, flag, name)) == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
/* Now attach a suitable slice to it. */
return ctf_add_slice (fp, flag, type, ep);
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_forward (ctf_dict_t *fp, uint32_t flag, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
uint32_t kind)
{
ctf_dtdef_t *dtd;
ctf_id_t type = 0;
if (!ctf_forwardable_kind (kind))
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
return (ctf_set_errno (fp, ECTF_NOTSUE));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* If the type is already defined or exists as a forward tag, just
return the ctf_id_t of the existing definition. */
if (name != NULL)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
type = ctf_lookup_by_rawname (fp, kind, name);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (type)
return type;
if ((type = ctf_add_generic (fp, flag, name, kind, &dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0);
dtd->dtd_data.ctt_type = kind;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_typedef (ctf_dict_t *fp, uint32_t flag, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_id_t ref)
{
ctf_dtdef_t *dtd;
ctf_id_t type;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EINVAL));
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if ((type = ctf_add_generic (fp, flag, name, CTF_K_TYPEDEF,
&dtd)) == CTF_ERR)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return CTF_ERR; /* errno is set for us. */
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0);
dtd->dtd_data.ctt_type = (uint32_t) ref;
return type;
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_volatile (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_reftype (fp, flag, ref, CTF_K_VOLATILE));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_const (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_reftype (fp, flag, ref, CTF_K_CONST));
}
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_restrict (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
return (ctf_add_reftype (fp, flag, ref, CTF_K_RESTRICT));
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int value)
{
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid);
ctf_dmdef_t *dmd;
uint32_t kind, vlen, root;
char *s;
if (name == NULL)
return (ctf_set_errno (fp, EINVAL));
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (dtd == NULL)
return (ctf_set_errno (fp, ECTF_BADID));
kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
if (kind != CTF_K_ENUM)
return (ctf_set_errno (fp, ECTF_NOTENUM));
if (vlen == CTF_MAX_VLEN)
return (ctf_set_errno (fp, ECTF_DTFULL));
for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
dmd != NULL; dmd = ctf_list_next (dmd))
{
if (strcmp (dmd->dmd_name, name) == 0)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
}
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((s = strdup (name)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dmd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
}
dmd->dmd_name = s;
dmd->dmd_type = CTF_ERR;
dmd->dmd_offset = 0;
dmd->dmd_value = value;
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
fp->ctf_flags |= LCTF_DIRTY;
return 0;
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_id_t type, unsigned long bit_offset)
{
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, souid);
ctf_dmdef_t *dmd;
ssize_t msize, malign, ssize;
uint32_t kind, vlen, root;
char *s = NULL;
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
int is_incomplete = 0;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (dtd == NULL)
return (ctf_set_errno (fp, ECTF_BADID));
if (name != NULL && name[0] == '\0')
name = NULL;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
root = LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info);
vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info);
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (ctf_set_errno (fp, ECTF_NOTSOU));
if (vlen == CTF_MAX_VLEN)
return (ctf_set_errno (fp, ECTF_DTFULL));
if (name != NULL)
{
for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
dmd != NULL; dmd = ctf_list_next (dmd))
{
if (dmd->dmd_name != NULL && strcmp (dmd->dmd_name, name) == 0)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
}
}
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if ((msize = ctf_type_size (fp, type)) < 0 ||
(malign = ctf_type_align (fp, type)) < 0)
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
{
/* The unimplemented type, and any type that resolves to it, has no size
and no alignment: it can correspond to any number of compiler-inserted
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
types. We allow incomplete types through since they are routinely
added to the ends of structures, and can even be added elsewhere in
structures by the deduplicator. They are assumed to be zero-size with
no alignment: this is often wrong, but problems can be avoided in this
case by explicitly specifying the size of the structure via the _sized
functions. The deduplicator always does this. */
msize = 0;
malign = 0;
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
if (ctf_errno (fp) == ECTF_NONREPRESENTABLE)
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
ctf_set_errno (fp, 0);
else if (ctf_errno (fp) == ECTF_INCOMPLETE)
is_incomplete = 1;
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
else
return -1; /* errno is set for us. */
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if (name != NULL && (s = strdup (name)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dmd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
}
dmd->dmd_name = s;
dmd->dmd_type = type;
dmd->dmd_value = -1;
if (kind == CTF_K_STRUCT && vlen != 0)
{
if (bit_offset == (unsigned long) - 1)
{
/* Natural alignment. */
ctf_dmdef_t *lmd = ctf_list_prev (&dtd->dtd_u.dtu_members);
ctf_id_t ltype = ctf_type_resolve (fp, lmd->dmd_type);
size_t off = lmd->dmd_offset;
ctf_encoding_t linfo;
ssize_t lsize;
libctf, create: support addition of references to the unimplemented type The deduplicating linker adds types from the linker inputs to the output via the same API everyone else does, so it's important that we can emit everything that the compiler wants us to. Unfortunately, the compiler may represent the unimplemented type (used for compiler constructs that CTF cannot currently encode) as type zero or as a type of kind CTF_K_UNKNOWN, and we don't allow the addition of types that cite the former. Adding this support adds a tiny bit of extra complexity: additions of structure members immediately following a member of the unimplemented type must be via ctf_add_member_offset or ctf_add_member_encoded, since we have no idea how big members of the unimplemented type are. (Attempts to do otherwise return -ECTF_NONREPRESENTABLE, like other attempts to do forbidden things with the unimplemented type.) Even slices of the unimplemented type are permitted: this is the only case in which you can slice a type that terminates in a non-integral type, on the grounds that it was likely integral in the source code, it's just that we can't represent that sort of integral type properly yet. libctf/ * ctf-create.c (ctf_add_reftype): Support refs to type zero. (ctf_add_array): Support array contents of type zero. (ctf_add_function): Support arguments and return types of type zero. (ctf_add_typedef): Support typedefs to type zero. (ctf_add_member_offset): Support members of type zero, unless added at unspecified (naturally-aligned) offset.
2020-06-03 03:04:24 +08:00
/* Propagate any error from ctf_type_resolve. If the last member was
of unimplemented type, this may be -ECTF_NONREPRESENTABLE: we
cannot insert right after such a member without explicit offset
specification, because its alignment and size is not known. */
if (ltype == CTF_ERR)
{
free (dmd);
return -1; /* errno is set for us. */
}
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
if (is_incomplete)
{
ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
_("ctf_add_member_offset: cannot add member %s of "
"incomplete type %lx to struct %lx without "
"specifying explicit offset\n"),
name ? name : _("(unnamed member)"), type, souid);
return (ctf_set_errno (fp, ECTF_INCOMPLETE));
}
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if (ctf_type_encoding (fp, ltype, &linfo) == 0)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
off += linfo.cte_bits;
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
else if ((lsize = ctf_type_size (fp, ltype)) > 0)
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
off += lsize * CHAR_BIT;
libctf, ld: prohibit getting the size or alignment of forwards C allows you to do only a very few things with entities of incomplete type (as opposed to pointers to them): make pointers to them and give them cv-quals, roughly. In particular you can't sizeof them and you can't get their alignment. We cannot impose all the requirements the standard imposes on CTF users, because the deduplicator can transform any structure type into a forward for the purposes of breaking cycles: so CTF type graphs can easily contain things like arrays of forward type (if you want to figure out their size or alignment, you need to chase down the types this forward might be a forward to in child TU dicts: we will soon add API functions to make doing this much easier). Nonetheless, it is still meaningless to ask for the size or alignment of forwards: but libctf didn't prohibit this and returned nonsense from internal implementation details when you asked (it returned the kind of the pointed-to type as both the size and alignment, because forwards reuse ctt_type as a type kind, and ctt_type and ctt_size overlap). So introduce a new error, ECTF_INCOMPLETE, which is returned when you try to get the size or alignment of forwards: we also return it when you try to do things that require libctf itself to get the size or alignment of a forward, notably using a forward as an array index type (which C should never do in any case) or adding forwards to structures without specifying their offset explicitly. The dumper will not emit size or alignment info for forwards any more. (This should not be an API break since ctf_type_size and ctf_type_align could both return errors before now: any code that isn't expecting error returns is already potentially broken.) include/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ECTF_INCOMPLETE): New. (ECTF_NERR): Adjust. ld/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper changes. * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. * testsuite/ld-ctf/forward.c: New test... * testsuite/ld-ctf/forward.d: ... and results. libctf/ChangeLog 2021-01-05 Nick Alcock <nick.alcock@oracle.com> * ctf-types.c (ctf_type_resolve): Improve comment. (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. Emit errors into the right dict. (ctf_type_align): Likewise. * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE when adding a member without explicit offset when this member, or the previous member, is incomplete. * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of forwards. (ctf_dump_member): Do not try to print their alignment.
2021-01-05 21:25:56 +08:00
else if (lsize == -1 && ctf_errno (fp) == ECTF_INCOMPLETE)
{
ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
_("ctf_add_member_offset: cannot add member %s of "
"type %lx to struct %lx without specifying "
"explicit offset after member %s of type %lx, "
"which is an incomplete type\n"),
name ? name : _("(unnamed member)"), type, souid,
lmd->dmd_name ? lmd->dmd_name
: _("(unnamed member)"), ltype);
return -1; /* errno is set for us. */
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
/* Round up the offset of the end of the last member to
the next byte boundary, convert 'off' to bytes, and
then round it up again to the next multiple of the
alignment required by the new member. Finally,
convert back to bits and store the result in
dmd_offset. Technically we could do more efficient
packing if the new member is a bit-field, but we're
the "compiler" and ANSI says we can do as we choose. */
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
off = roundup (off, CHAR_BIT) / CHAR_BIT;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
off = roundup (off, MAX (malign, 1));
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
dmd->dmd_offset = off * CHAR_BIT;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ssize = off + msize;
}
else
{
/* Specified offset in bits. */
dmd->dmd_offset = bit_offset;
ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
Use CHAR_BIT instead of NBBY in libctf On x86-64 Fedora 29, I tried to build a mingw-hosted gdb that targets ppc-linux. You can do this with: ../binutils-gdb/configure --host=i686-w64-mingw32 --target=ppc-linux \ --disable-{binutils,gas,gold,gprof,ld} The build failed with these errors in libctf: In file included from ../../binutils-gdb/libctf/ctf-create.c:20: ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_encoded': ../../binutils-gdb/libctf/ctf-create.c:803:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c:803:59: note: each undeclared identifier is reported only once for each function it appears in dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_slice': ../../binutils-gdb/libctf/ctf-create.c:862:59: error: 'NBBY' undeclared (first use in this function) dtd->dtd_data.ctt_size = clp2 (P2ROUNDUP (ep->cte_bits, NBBY) / NBBY); ^~~~ ../../binutils-gdb/libctf/ctf-impl.h:254:42: note: in definition of macro 'P2ROUNDUP' #define P2ROUNDUP(x, align) (-(-(x) & -(align))) ^~~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_member_offset': ../../binutils-gdb/libctf/ctf-create.c:1341:21: error: 'NBBY' undeclared (first use in this function) off += lsize * NBBY; ^~~~ ../../binutils-gdb/libctf/ctf-create.c: In function 'ctf_add_type': ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:35: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: unknown conversion type character 'z' in format [-Wformat=] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../binutils-gdb/libctf/ctf-create.c:1823:44: note: format string is defined here "union size differs, old %zi, new %zi\n", ^ ../../binutils-gdb/libctf/ctf-create.c:1822:16: warning: too many arguments for format [-Wformat-extra-args] ctf_dprintf ("Conflict for type %s against ID %lx: " ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This patch fixes the actual errors in here. I did not try to fix the printf warnings, though I think someone ought to. Ok? libctf/ChangeLog 2019-06-04 Tom Tromey <tromey@adacore.com> * ctf-create.c (ctf_add_encoded, ctf_add_slice) (ctf_add_member_offset): Use CHAR_BIT, not NBBY.
2019-06-05 02:16:57 +08:00
ssize = MAX (ssize, ((signed) bit_offset / CHAR_BIT) + msize);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
}
}
else
{
dmd->dmd_offset = 0;
ssize = ctf_get_ctt_size (fp, &dtd->dtd_data, NULL, NULL);
ssize = MAX (ssize, msize);
}
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if ((size_t) ssize > CTF_MAX_SIZE)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (ssize);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (ssize);
}
else
dtd->dtd_data.ctt_size = (uint32_t) ssize;
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1);
ctf_list_append (&dtd->dtd_u.dtu_members, dmd);
fp->ctf_flags |= LCTF_DIRTY;
return 0;
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_member_encoded (ctf_dict_t *fp, ctf_id_t souid, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_id_t type, unsigned long bit_offset,
const ctf_encoding_t encoding)
{
ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, type);
int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
int otype = type;
if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) && (kind != CTF_K_ENUM))
return (ctf_set_errno (fp, ECTF_NOTINTFP));
if ((type = ctf_add_slice (fp, CTF_ADD_NONROOT, otype, &encoding)) == CTF_ERR)
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
return -1; /* errno is set for us. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return ctf_add_member_offset (fp, souid, name, type, bit_offset);
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_member (ctf_dict_t *fp, ctf_id_t souid, const char *name,
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ctf_id_t type)
{
return ctf_add_member_offset (fp, souid, name, type, (unsigned long) - 1);
}
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_variable (ctf_dict_t *fp, const char *name, ctf_id_t ref)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
ctf_dvdef_t *dvd;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp = fp;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (ctf_dvd_lookup (fp, name) != NULL)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
if (ctf_lookup_by_id (&tmp, ref) == NULL)
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
return -1; /* errno is set for us. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: handle nonrepresentable types at link time GCC can emit references to type 0 to indicate that this type is one that is not representable in the version of CTF it emits (for instance, version 3 cannot encode vector types). Type 0 is already used in the function section to indicate padding inserted to skip functions we do not want to encode the type of, so using zero in this way is a good extension of the format: but libctf reports such types as ECTF_BADID, which is indistinguishable from file corruption via links to truly nonexistent types with IDs like 0xDEADBEEF etc, which we really do want to stop for. In particular, this stops all traversals of types dead at this point, preventing us from even dumping CTF files containing unrepresentable types to see what's going on! So add a new error, ECTF_NONREPRESENTABLE, which is returned by recursive type resolution when a reference to a zero type is found. (No zero type is ever emitted into the CTF file by GCC, only references to one). We can't do much with types that are ultimately nonrepresentable, but we can do enough to keep functioning. Adjust ctf_add_type to ensure that top-level types of type zero and structure and union members of ultimate type zero are simply skipped without reporting an error, so we can copy structures and unions that contain nonrepresentable members (skipping them and leaving a hole where they would be, so no consumers downstream of the linker need to worry about this): adjust the dumper so that we dump members of nonrepresentable types in a simple form that indicates nonrepresentability rather than terminating the dump, and do not falsely assume all errors to be -ENOMEM: adjust the linker so that types that fail to get added are simply skipped, so that both nonrepresentable types and outright errors do not terminate the type addition, which could skip many valid types and cause further errors when variables of those types are added. In future, when we gain the ability to call back to the linker to report link-time type resolution errors, we should report failures to add all but nonrepresentable types. But we can't do that yet. v5: Fix tabdamage. include/ * ctf-api.h (ECTF_NONREPRESENTABLE): New. libctf/ * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on type zero. * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable members and types. (ctf_add_variable): Likewise for variables pointing to them. * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable type link failure, but do warn for others. * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all errors to be ENOMEM. (ctf_dump_member): Likewise. (ctf_dump_type): Likewise. (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. (ctf_dump_header): Likewise. (ctf_dump_label): likewise. (ctf_dump_objts): likewise. (ctf_dump_funcs): likewise. (ctf_dump_var): likewise. (ctf_dump_str): Likewise.
2019-08-05 18:40:33 +08:00
/* Make sure this type is representable. */
if ((ctf_type_resolve (fp, ref) == CTF_ERR)
&& (ctf_errno (fp) == ECTF_NONREPRESENTABLE))
return -1;
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((dvd = malloc (sizeof (ctf_dvdef_t))) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if (name != NULL && (dvd->dvd_name = strdup (name)) == NULL)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dvd);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return (ctf_set_errno (fp, EAGAIN));
}
dvd->dvd_type = ref;
dvd->dvd_snapshots = fp->ctf_snapshots;
if (ctf_dvd_insert (fp, dvd) < 0)
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dvd->dvd_name);
free (dvd);
return -1; /* errno is set for us. */
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
fp->ctf_flags |= LCTF_DIRTY;
return 0;
}
libctf: symbol type linking support This adds facilities to write out the function info and data object sections, which efficiently map from entries in the symbol table to types. The write-side code is entirely new: the read-side code was merely significantly changed and support for indexed tables added (pointed to by the no-longer-unused cth_objtidxoff and cth_funcidxoff header fields). With this in place, you can use ctf_lookup_by_symbol to look up the types of symbols of function and object type (and, as before, you can use ctf_lookup_variable to look up types of file-scope variables not present in the symbol table, as long as you know their name: but variables that are also data objects are now found in the data object section instead.) (Compatible) file format change: The CTF spec has always said that the function info section looks much like the CTF_K_FUNCTIONs in the type section: an info word (including an argument count) followed by a return type and N argument types. This format is suboptimal: it means function symbols cannot be deduplicated and it causes a lot of ugly code duplication in libctf. But conveniently the compiler has never emitted this! Because it has always emitted a rather different format that libctf has never accepted, we can be sure that there are no instances of this function info section in the wild, and can freely change its format without compatibility concerns or a file format version bump. (And since it has never been emitted in any code that generated any older file format version, either, we need keep no code to read the format as specified at all!) So the function info section is now specified as an array of uint32_t, exactly like the object data section: each entry is a type ID in the type section which must be of kind CTF_K_FUNCTION, the prototype of this function. This allows function types to be deduplicated and also correctly encodes the fact that all functions declared in C really are types available to the program: so they should be stored in the type section like all other types. (In format v4, we will be able to represent the types of static functions as well, but that really does require a file format change.) We introduce a new header flag, CTF_F_NEWFUNCINFO, which is set if the new function info format is in use. A sufficiently new compiler will always set this flag. New libctf will always set this flag: old libctf will refuse to open any CTF dicts that have this flag set. If the flag is not set on a dict being read in, new libctf will disregard the function info section. Format v4 will remove this flag (or, rather, the flag has no meaning there and the bit position may be recycled for some other purpose). New API: Symbol addition: ctf_add_func_sym: Add a symbol with a given name and type. The type must be of kind CTF_K_FUNCTION (a function pointer). Internally this adds a name -> type mapping to the ctf_funchash in the ctf_dict. ctf_add_objt_sym: Add a symbol with a given name and type. The type kind can be anything, including function pointers. This adds to ctf_objthash. These both treat symbols as name -> type mappings: the linker associates symbol names with symbol indexes via the ctf_link_shuffle_syms callback, which sets up the ctf_dynsyms/ctf_dynsymidx/ctf_dynsymmax fields in the ctf_dict. Repeated relinks can add more symbols. Variables that are also exposed as symbols are removed from the variable section at serialization time. CTF symbol type sections which have enough pads, defined by CTF_INDEX_PAD_THRESHOLD (whether because they are in dicts with symbols where most types are unknown, or in archive where most types are defined in some child or parent dict, not in this specific dict) are sorted by name rather than symidx and accompanied by an index which associates each symbol type entry with a name: the existing ctf_lookup_by_symbol will map symbol indexes to symbol names and look the names up in the index automatically. (This is currently ELF-symbol-table-dependent, but there is almost nothing specific to ELF in here and we can add support for other symbol table formats easily). The compiler also uses index sections to communicate the contents of object file symbol tables without relying on any specific ordering of symbols: it doesn't need to sort them, and libctf will detect an unsorted index section via the absence of the new CTF_F_IDXSORTED header flag, and sort it if needed. Iteration: ctf_symbol_next: Iterator which returns the types and names of symbols one by one, either for function or data symbols. This does not require any sorting: the ctf_link machinery uses it to pull in all the compiler-provided symbols cheaply, but it is not restricted to that use. (Compatible) changes in API: ctf_lookup_by_symbol: can now be called for object and function symbols: never returns ECTF_NOTDATA (which is now not thrown by anything, but is kept for compatibility and because it is a plausible error that we might start throwing again at some later date). Internally we also have changes to the ctf-string functionality so that "external" strings (those where we track a string -> offset mapping, but only write out an offset) can be consulted via the usual means (ctf_strptr) before the strtab is written out. This is important because ctf_link_add_linker_symbol can now be handed symbols named via strtab offsets, and ctf_link_shuffle_syms must figure out their actual names by looking in the external symtab we have just been fed by the ctf_link_add_strtab callback, long before that strtab is written out. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_symbol_next): New. (ctf_add_objt_sym): Likewise. (ctf_add_func_sym): Likewise. * ctf.h: Document new function info section format. (CTF_F_NEWFUNCINFO): New. (CTF_F_IDXSORTED): New. (CTF_F_MAX): Adjust accordingly. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h (CTF_INDEX_PAD_THRESHOLD): New. (_libctf_nonnull_): Likewise. (ctf_in_flight_dynsym_t): New. (ctf_dict_t) <ctf_funcidx_names>: Likewise. <ctf_objtidx_names>: Likewise. <ctf_nfuncidx>: Likewise. <ctf_nobjtidx>: Likewise. <ctf_funcidx_sxlate>: Likewise. <ctf_objtidx_sxlate>: Likewise. <ctf_objthash>: Likewise. <ctf_funchash>: Likewise. <ctf_dynsyms>: Likewise. <ctf_dynsymidx>: Likewise. <ctf_dynsymmax>: Likewise. <ctf_in_flight_dynsym>: Likewise. (struct ctf_next) <u.ctn_next>: Likewise. (ctf_symtab_skippable): New prototype. (ctf_add_funcobjt_sym): Likewise. (ctf_dynhash_sort_by_name): Likewise. (ctf_sym_to_elf64): Rename to... (ctf_elf32_to_link_sym): ... this, and... (ctf_elf64_to_link_sym): ... this. * ctf-open.c (init_symtab): Check for lack of CTF_F_NEWFUNCINFO flag, and presence of index sections. Refactor out ctf_symtab_skippable and ctf_elf*_to_link_sym, and use them. Use ctf_link_sym_t, not Elf64_Sym. Skip initializing objt or func sxlate sections if corresponding index section is present. Adjust for new func info section format. (ctf_bufopen_internal): Add ctf_err_warn to corrupt-file error handling. Report incorrect-length index sections. Always do an init_symtab, even if there is no symtab section (there may be index sections still). (flip_objts): Adjust comment: func and objt sections are actually identical in structure now, no need to caveat. (ctf_dict_close): Free newly-added data structures. * ctf-create.c (ctf_create): Initialize them. (ctf_symtab_skippable): New, refactored out of init_symtab, with st_nameidx_set check added. (ctf_add_funcobjt_sym): New, add a function or object symbol to the ctf_objthash or ctf_funchash, by name. (ctf_add_objt_sym): Call it. (ctf_add_func_sym): Likewise. (symtypetab_delete_nonstatic_vars): New, delete vars also present as data objects. (CTF_SYMTYPETAB_EMIT_FUNCTION): New flag to symtypetab emitters: this is a function emission, not a data object emission. (CTF_SYMTYPETAB_EMIT_PAD): New flag to symtypetab emitters: emit pads for symbols with no type (only set for unindexed sections). (CTF_SYMTYPETAB_FORCE_INDEXED): New flag to symtypetab emitters: always emit indexed. (symtypetab_density): New, figure out section sizes. (emit_symtypetab): New, emit a symtypetab. (emit_symtypetab_index): New, emit a symtypetab index. (ctf_serialize): Call them, emitting suitably sorted symtypetab sections and indexes. Set suitable header flags. Copy over new fields. * ctf-hash.c (ctf_dynhash_sort_by_name): New, used to impose an order on symtypetab index sections. * ctf-link.c (ctf_add_type_mapping): Delete erroneous comment relating to code that was never committed. (ctf_link_one_variable): Improve variable name. (check_sym): New, symtypetab analogue of check_variable. (ctf_link_deduplicating_one_symtypetab): New. (ctf_link_deduplicating_syms): Likewise. (ctf_link_deduplicating): Call them. (ctf_link_deduplicating_per_cu): Note that we don't call them in this case (yet). (ctf_link_add_strtab): Set the error on the fp correctly. (ctf_link_add_linker_symbol): New (no longer a do-nothing stub), add a linker symbol to the in-flight list. (ctf_link_shuffle_syms): New (no longer a do-nothing stub), turn the in-flight list into a mapping we can use, now its names are resolvable in the external strtab. * ctf-string.c (ctf_str_rollback_atom): Don't roll back atoms with external strtab offsets. (ctf_str_rollback): Adjust comment. (ctf_str_write_strtab): Migrate ctf_syn_ext_strtab population from writeout time... (ctf_str_add_external): ... to string addition time. * ctf-lookup.c (ctf_lookup_var_key_t): Rename to... (ctf_lookup_idx_key_t): ... this, now we use it for syms too. <clik_names>: New member, a name table. (ctf_lookup_var): Adjust accordingly. (ctf_lookup_variable): Likewise. (ctf_lookup_by_id): Shuffle further up in the file. (ctf_symidx_sort_arg_cb): New, callback for... (sort_symidx_by_name): ... this new function to sort a symidx found to be unsorted (likely originating from the compiler). (ctf_symidx_sort): New, sort a symidx. (ctf_lookup_symbol_name): Support dynamic symbols with indexes provided by the linker. Use ctf_link_sym_t, not Elf64_Sym. Check the parent if a child lookup fails. (ctf_lookup_by_symbol): Likewise. Work for function symbols too. (ctf_symbol_next): New, iterate over symbols with types (without sorting). (ctf_lookup_idx_name): New, bsearch for symbol names in indexes. (ctf_try_lookup_indexed): New, attempt an indexed lookup. (ctf_func_info): Reimplement in terms of ctf_lookup_by_symbol. (ctf_func_args): Likewise. (ctf_get_dict): Move... * ctf-types.c (ctf_get_dict): ... here. * ctf-util.c (ctf_sym_to_elf64): Re-express as... (ctf_elf64_to_link_sym): ... this. Add new st_symidx field, and st_nameidx_set (always 0, so st_nameidx can be ignored). Look in the ELF strtab for names. (ctf_elf32_to_link_sym): Likewise, for Elf32_Sym. (ctf_next_destroy): Destroy ctf_next_t.u.ctn_next if need be. * libctf.ver: Add ctf_symbol_next, ctf_add_objt_sym and ctf_add_func_sym.
2020-11-20 21:34:04 +08:00
int
ctf_add_funcobjt_sym (ctf_dict_t *fp, int is_function, const char *name, ctf_id_t id)
{
ctf_dict_t *tmp = fp;
char *dupname;
ctf_dynhash_t *h = is_function ? fp->ctf_funchash : fp->ctf_objthash;
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (fp, ECTF_RDONLY));
if (ctf_dynhash_lookup (fp->ctf_objthash, name) != NULL ||
ctf_dynhash_lookup (fp->ctf_funchash, name) != NULL)
return (ctf_set_errno (fp, ECTF_DUPLICATE));
if (ctf_lookup_by_id (&tmp, id) == NULL)
return -1; /* errno is set for us. */
if (is_function && ctf_type_kind (fp, id) != CTF_K_FUNCTION)
return (ctf_set_errno (fp, ECTF_NOTFUNC));
if ((dupname = strdup (name)) == NULL)
return (ctf_set_errno (fp, ENOMEM));
if (ctf_dynhash_insert (h, dupname, (void *) (uintptr_t) id) < 0)
{
free (dupname);
return (ctf_set_errno (fp, ENOMEM));
}
return 0;
}
int
ctf_add_objt_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
{
return (ctf_add_funcobjt_sym (fp, 0, name, id));
}
int
ctf_add_func_sym (ctf_dict_t *fp, const char *name, ctf_id_t id)
{
return (ctf_add_funcobjt_sym (fp, 1, name, id));
}
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
typedef struct ctf_bundle
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *ctb_dict; /* CTF dict handle. */
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_id_t ctb_type; /* CTF type identifier. */
ctf_dtdef_t *ctb_dtd; /* CTF dynamic type definition (if any). */
} ctf_bundle_t;
static int
enumcmp (const char *name, int value, void *arg)
{
ctf_bundle_t *ctb = arg;
int bvalue;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
if (ctf_enum_value (ctb->ctb_dict, ctb->ctb_type, name, &bvalue) < 0)
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_err_warn (ctb->ctb_dict, 0, 0,
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
_("conflict due to enum %s iteration error"), name);
return 1;
}
if (value != bvalue)
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
_("conflict due to enum value change: %i versus %i"),
value, bvalue);
return 1;
}
return 0;
}
static int
enumadd (const char *name, int value, void *arg)
{
ctf_bundle_t *ctb = arg;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
return (ctf_add_enumerator (ctb->ctb_dict, ctb->ctb_type,
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
name, value) < 0);
}
static int
membcmp (const char *name, ctf_id_t type _libctf_unused_, unsigned long offset,
void *arg)
{
ctf_bundle_t *ctb = arg;
ctf_membinfo_t ctm;
/* Don't check nameless members (e.g. anonymous structs/unions) against each
other. */
if (name[0] == 0)
return 0;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
if (ctf_member_info (ctb->ctb_dict, ctb->ctb_type, name, &ctm) < 0)
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_err_warn (ctb->ctb_dict, 0, 0,
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
_("conflict due to struct member %s iteration error"),
name);
return 1;
}
if (ctm.ctm_offset != offset)
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT,
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
_("conflict due to struct member %s offset change: "
"%lx versus %lx"),
name, ctm.ctm_offset, offset);
return 1;
}
return 0;
}
static int
membadd (const char *name, ctf_id_t type, unsigned long offset, void *arg)
{
ctf_bundle_t *ctb = arg;
ctf_dmdef_t *dmd;
char *s = NULL;
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL)
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
return (ctf_set_errno (ctb->ctb_dict, EAGAIN));
libctf, create: fix ctf_type_add of structs with unnamed members Our recent commit to support unnamed structure members better ditched the old ctf_member_iter iterator body in favour of ctf_member_next. However, these functions treat unnamed structure members differently: ctf_member_iter just returned whatever the internal representation contained, while ctf_member_next took care to always return "" rather than sometimes returning "" and sometimes NULL depending on whether the dict was dynamic (a product of ctf_create) or not (a product of ctf_open). After this commit, ctf_member_iter did the same. It was always a bug for external callers not to treat a "" return from these functions as if it were NULL, so only buggy callers could be affected -- but one of those buggy callers was ctf_add_type, which assumed that it could just take whatever name was returned from ctf_member_iter and slam it directly into the internal representation of a dynamic dict -- which expects NULL for unnamed members, not "". The net effect of all of this is that taking a struct containing unnamed members and ctf_add_type'ing it into a dynamic dict produced a dict whose unnamed members were inaccessible to ctf_member_info (though if you wrote that dict out and then ctf_open'ed it, they would magically reappear again). Compensate for this by suitably transforming a "" name into NULL in the internal representation, as should have been done all along. libctf/ChangeLog 2021-01-19 Nick Alcock <nick.alcock@oracle.com> * ctf-create.c (membadd): Transform ""-named members into NULL-named ones. * testsuite/libctf-regression/type-add-unnamed-struct*: New test.
2021-01-19 20:45:18 +08:00
/* Unnamed members in non-dynamic dicts have a name of "", while dynamic dicts
use NULL. Adapt. */
if (name[0] == 0)
name = NULL;
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if (name != NULL && (s = strdup (name)) == NULL)
{
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (dmd);
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
return (ctf_set_errno (ctb->ctb_dict, EAGAIN));
}
/* For now, dmd_type is copied as the src_fp's type; it is reset to an
equivalent dst_fp type by a final loop in ctf_add_type(), below. */
dmd->dmd_name = s;
dmd->dmd_type = type;
dmd->dmd_offset = offset;
dmd->dmd_value = -1;
ctf_list_append (&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctb->ctb_dict->ctf_flags |= LCTF_DIRTY;
return 0;
}
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* The ctf_add_type routine is used to copy a type from a source CTF dictionary
to a dynamic destination dictionary. This routine operates recursively by
following the source type's links and embedded member types. If the
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
destination dict already contains a named type which has the same attributes,
then we succeed and return this type but no changes occur. */
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
static ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type,
ctf_dict_t *proc_tracking_fp)
{
ctf_id_t dst_type = CTF_ERR;
uint32_t dst_kind = CTF_K_UNKNOWN;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *tmp_fp = dst_fp;
ctf_id_t tmp;
const char *name;
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
uint32_t kind, forward_kind, flag, vlen;
const ctf_type_t *src_tp, *dst_tp;
ctf_bundle_t src, dst;
ctf_encoding_t src_en, dst_en;
ctf_arinfo_t src_ar, dst_ar;
ctf_funcinfo_t ctc;
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
ctf_id_t orig_src_type = src_type;
if (!(dst_fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno (dst_fp, ECTF_RDONLY));
if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
libctf: handle nonrepresentable types at link time GCC can emit references to type 0 to indicate that this type is one that is not representable in the version of CTF it emits (for instance, version 3 cannot encode vector types). Type 0 is already used in the function section to indicate padding inserted to skip functions we do not want to encode the type of, so using zero in this way is a good extension of the format: but libctf reports such types as ECTF_BADID, which is indistinguishable from file corruption via links to truly nonexistent types with IDs like 0xDEADBEEF etc, which we really do want to stop for. In particular, this stops all traversals of types dead at this point, preventing us from even dumping CTF files containing unrepresentable types to see what's going on! So add a new error, ECTF_NONREPRESENTABLE, which is returned by recursive type resolution when a reference to a zero type is found. (No zero type is ever emitted into the CTF file by GCC, only references to one). We can't do much with types that are ultimately nonrepresentable, but we can do enough to keep functioning. Adjust ctf_add_type to ensure that top-level types of type zero and structure and union members of ultimate type zero are simply skipped without reporting an error, so we can copy structures and unions that contain nonrepresentable members (skipping them and leaving a hole where they would be, so no consumers downstream of the linker need to worry about this): adjust the dumper so that we dump members of nonrepresentable types in a simple form that indicates nonrepresentability rather than terminating the dump, and do not falsely assume all errors to be -ENOMEM: adjust the linker so that types that fail to get added are simply skipped, so that both nonrepresentable types and outright errors do not terminate the type addition, which could skip many valid types and cause further errors when variables of those types are added. In future, when we gain the ability to call back to the linker to report link-time type resolution errors, we should report failures to add all but nonrepresentable types. But we can't do that yet. v5: Fix tabdamage. include/ * ctf-api.h (ECTF_NONREPRESENTABLE): New. libctf/ * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on type zero. * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable members and types. (ctf_add_variable): Likewise for variables pointing to them. * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable type link failure, but do warn for others. * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all errors to be ENOMEM. (ctf_dump_member): Likewise. (ctf_dump_type): Likewise. (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. (ctf_dump_header): Likewise. (ctf_dump_label): likewise. (ctf_dump_objts): likewise. (ctf_dump_funcs): likewise. (ctf_dump_var): likewise. (ctf_dump_str): Likewise.
2019-08-05 18:40:33 +08:00
if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR)
&& (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE))
return (ctf_set_errno (dst_fp, ECTF_NONREPRESENTABLE));
name = ctf_strptr (src_fp, src_tp->ctt_name);
kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info);
vlen = LCTF_INFO_VLEN (src_fp, src_tp->ctt_info);
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
/* If this is a type we are currently in the middle of adding, hand it
straight back. (This lets us handle self-referential structures without
considering forwards and empty structures the same as their completed
forms.) */
tmp = ctf_type_mapping (src_fp, src_type, &tmp_fp);
if (tmp != 0)
{
if (ctf_dynhash_lookup (proc_tracking_fp->ctf_add_processing,
(void *) (uintptr_t) src_type))
return tmp;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* If this type has already been added from this dictionary, and is the
same kind and (if a struct or union) has the same number of members,
hand it straight back. */
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if (ctf_type_kind_unsliced (tmp_fp, tmp) == (int) kind)
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
{
if (kind == CTF_K_STRUCT || kind == CTF_K_UNION
|| kind == CTF_K_ENUM)
{
if ((dst_tp = ctf_lookup_by_id (&tmp_fp, dst_type)) != NULL)
if (vlen == LCTF_INFO_VLEN (tmp_fp, dst_tp->ctt_info))
return tmp;
}
else
return tmp;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
}
}
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
forward_kind = kind;
if (kind == CTF_K_FORWARD)
forward_kind = src_tp->ctt_type;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
/* If the source type has a name and is a root type (visible at the top-level
scope), lookup the name in the destination dictionary and verify that it is
of the same kind before we do anything else. */
if ((flag & CTF_ADD_ROOT) && name[0] != '\0'
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
&& (tmp = ctf_lookup_by_rawname (dst_fp, forward_kind, name)) != 0)
{
dst_type = tmp;
dst_kind = ctf_type_kind_unsliced (dst_fp, dst_type);
}
/* If an identically named dst_type exists, fail with ECTF_CONFLICT
unless dst_type is a forward declaration and src_type is a struct,
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
union, or enum (i.e. the definition of the previous forward decl).
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
We also allow addition in the opposite order (addition of a forward when a
struct, union, or enum already exists), which is a NOP and returns the
already-present struct, union, or enum. */
if (dst_type != CTF_ERR && dst_kind != kind)
{
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
if (kind == CTF_K_FORWARD
&& (dst_kind == CTF_K_ENUM || dst_kind == CTF_K_STRUCT
|| dst_kind == CTF_K_UNION))
{
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
return dst_type;
}
if (dst_kind != CTF_K_FORWARD
|| (kind != CTF_K_ENUM && kind != CTF_K_STRUCT
&& kind != CTF_K_UNION))
{
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
_("ctf_add_type: conflict for type %s: "
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
"kinds differ, new: %i; old (ID %lx): %i"),
name, kind, dst_type, dst_kind);
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
}
/* We take special action for an integer, float, or slice since it is
described not only by its name but also its encoding. For integers,
bit-fields exploit this degeneracy. */
if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
{
if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
if (dst_type != CTF_ERR)
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *fp = dst_fp;
if ((dst_tp = ctf_lookup_by_id (&fp, dst_type)) == NULL)
return CTF_ERR;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if (ctf_type_encoding (dst_fp, dst_type, &dst_en) != 0)
return CTF_ERR; /* errno set for us. */
if (LCTF_INFO_ISROOT (fp, dst_tp->ctt_info) & CTF_ADD_ROOT)
{
/* The type that we found in the hash is also root-visible. If
the two types match then use the existing one; otherwise,
declare a conflict. Note: slices are not certain to match
even if there is no conflict: we must check the contained type
too. */
if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
{
if (kind != CTF_K_SLICE)
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
{
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
return dst_type;
}
}
else
{
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
}
else
{
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
/* We found a non-root-visible type in the hash. If its encoding
is the same, we can reuse it, unless it is a slice. */
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if (memcmp (&src_en, &dst_en, sizeof (ctf_encoding_t)) == 0)
{
if (kind != CTF_K_SLICE)
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
{
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
return dst_type;
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
}
}
}
}
}
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
src.ctb_dict = src_fp;
src.ctb_type = src_type;
src.ctb_dtd = NULL;
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
dst.ctb_dict = dst_fp;
dst.ctb_type = dst_type;
dst.ctb_dtd = NULL;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
/* Now perform kind-specific processing. If dst_type is CTF_ERR, then we add
a new type with the same properties as src_type to dst_fp. If dst_type is
not CTF_ERR, then we verify that dst_type has the same attributes as
src_type. We recurse for embedded references. Before we start, we note
that we are processing this type, to prevent infinite recursion: we do not
re-process any type that appears in this list. The list is emptied
wholesale at the end of processing everything in this recursive stack. */
if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing,
(void *) (uintptr_t) src_type, (void *) 1) < 0)
return ctf_set_errno (dst_fp, ENOMEM);
switch (kind)
{
case CTF_K_INTEGER:
/* If we found a match we will have either returned it or declared a
conflict. */
dst_type = ctf_add_integer (dst_fp, flag, name, &src_en);
break;
case CTF_K_FLOAT:
/* If we found a match we will have either returned it or declared a
conflict. */
dst_type = ctf_add_float (dst_fp, flag, name, &src_en);
break;
case CTF_K_SLICE:
/* We have checked for conflicting encodings: now try to add the
contained type. */
src_type = ctf_type_reference (src_fp, src_type);
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
proc_tracking_fp);
if (src_type == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
dst_type = ctf_add_slice (dst_fp, flag, src_type, &src_en);
break;
case CTF_K_POINTER:
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
src_type = ctf_type_reference (src_fp, src_type);
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
proc_tracking_fp);
if (src_type == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
dst_type = ctf_add_reftype (dst_fp, flag, src_type, kind);
break;
case CTF_K_ARRAY:
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
src_ar.ctr_contents =
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents,
proc_tracking_fp);
src_ar.ctr_index = ctf_add_type_internal (dst_fp, src_fp,
src_ar.ctr_index,
proc_tracking_fp);
src_ar.ctr_nelems = src_ar.ctr_nelems;
if (src_ar.ctr_contents == CTF_ERR || src_ar.ctr_index == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
if (dst_type != CTF_ERR)
{
if (ctf_array_info (dst_fp, dst_type, &dst_ar) != 0)
return CTF_ERR; /* errno is set for us. */
if (memcmp (&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
{
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
_("conflict for type %s against ID %lx: array info "
"differs, old %lx/%lx/%x; new: %lx/%lx/%x"),
name, dst_type, src_ar.ctr_contents,
src_ar.ctr_index, src_ar.ctr_nelems,
dst_ar.ctr_contents, dst_ar.ctr_index,
dst_ar.ctr_nelems);
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
}
else
dst_type = ctf_add_array (dst_fp, flag, &src_ar);
break;
case CTF_K_FUNCTION:
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
src_tp->ctt_type,
proc_tracking_fp);
ctc.ctc_argc = 0;
ctc.ctc_flags = 0;
if (ctc.ctc_return == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
{
ctf_dmdef_t *dmd;
int errs = 0;
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
size_t size;
ssize_t ssize;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctf_dtdef_t *dtd;
/* Technically to match a struct or union we need to check both
ways (src members vs. dst, dst members vs. src) but we make
this more optimal by only checking src vs. dst and comparing
the total size of the structure (which we must do anyway)
which covers the possibility of dst members not in src.
This optimization can be defeated for unions, but is so
pathological as to render it irrelevant for our purposes. */
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
&& dst_kind != CTF_K_FORWARD)
{
if (ctf_type_size (src_fp, src_type) !=
ctf_type_size (dst_fp, dst_type))
{
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
_("conflict for type %s against ID %lx: union "
"size differs, old %li, new %li"), name,
dst_type, (long) ctf_type_size (src_fp, src_type),
(long) ctf_type_size (dst_fp, dst_type));
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
{
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
_("conflict for type %s against ID %lx: members "
"differ, see above"), name, dst_type);
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
break;
}
/* Unlike the other cases, copying structs and unions is done
manually so as to avoid repeated lookups in ctf_add_member
and to ensure the exact same member offsets as in src_type. */
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
dst_type = ctf_add_generic (dst_fp, flag, name, kind, &dtd);
if (dst_type == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
dst.ctb_type = dst_type;
dst.ctb_dtd = dtd;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
/* Pre-emptively add this struct to the type mapping so that
structures that refer to themselves work. */
ctf_add_type_mapping (src_fp, src_type, dst_fp, dst_type);
if (ctf_member_iter (src_fp, src_type, membadd, &dst) != 0)
errs++; /* Increment errs and fail at bottom of case. */
libctf: fix a number of build problems found on Solaris and NetBSD - Use of nonportable <endian.h> - Use of qsort_r - Use of zlib without appropriate magic to pull in the binutils zlib - Use of off64_t without checking (fixed by dropping the unused fields that need off64_t entirely) - signedness problems due to long being too short a type on 32-bit platforms: ctf_id_t is now 'unsigned long', and CTF_ERR must be used only for functions that return ctf_id_t - One lingering use of bzero() and of <sys/errno.h> All fixed, using code from gnulib where possible. Relatedly, set cts_size in a couple of places it was missed (string table and symbol table loading upon ctf_bfdopen()). binutils/ * objdump.c (make_ctfsect): Drop cts_type, cts_flags, and cts_offset. * readelf.c (shdr_to_ctf_sect): Likewise. include/ * ctf-api.h (ctf_sect_t): Drop cts_type, cts_flags, and cts_offset. (ctf_id_t): This is now an unsigned type. (CTF_ERR): Cast it to ctf_id_t. Note that it should only be used for ctf_id_t-returning functions. libctf/ * Makefile.am (ZLIB): New. (ZLIBINC): Likewise. (AM_CFLAGS): Use them. (libctf_a_LIBADD): New, for LIBOBJS. * configure.ac: Check for zlib, endian.h, and qsort_r. * ctf-endian.h: New, providing htole64 and le64toh. * swap.h: Code style fixes. (bswap_identity_64): New. * qsort_r.c: New, from gnulib (with one added #include). * ctf-decls.h: New, providing a conditional qsort_r declaration, and unconditional definitions of MIN and MAX. * ctf-impl.h: Use it. Do not use <sys/errno.h>. (ctf_set_errno): Now returns unsigned long. * ctf-util.c (ctf_set_errno): Adjust here too. * ctf-archive.c: Use ctf-endian.h. (ctf_arc_open_by_offset): Use memset, not bzero. Drop cts_type, cts_flags and cts_offset. (ctf_arc_write): Drop debugging dependent on the size of off_t. * ctf-create.c: Provide a definition of roundup if not defined. (ctf_create): Drop cts_type, cts_flags and cts_offset. (ctf_add_reftype): Do not check if type IDs are below zero. (ctf_add_slice): Likewise. (ctf_add_typedef): Likewise. (ctf_add_member_offset): Cast error-returning ssize_t's to size_t when known error-free. Drop CTF_ERR usage for functions returning int. (ctf_add_member_encoded): Drop CTF_ERR usage for functions returning int. (ctf_add_variable): Likewise. (enumcmp): Likewise. (enumadd): Likewise. (membcmp): Likewise. (ctf_add_type): Likewise. Cast error-returning ssize_t's to size_t when known error-free. * ctf-dump.c (ctf_is_slice): Drop CTF_ERR usage for functions returning int: use CTF_ERR for functions returning ctf_type_id. (ctf_dump_label): Likewise. (ctf_dump_objts): Likewise. * ctf-labels.c (ctf_label_topmost): Likewise. (ctf_label_iter): Likewise. (ctf_label_info): Likewise. * ctf-lookup.c (ctf_func_args): Likewise. * ctf-open.c (upgrade_types): Cast to size_t where appropriate. (ctf_bufopen): Likewise. Use zlib types as needed. * ctf-types.c (ctf_member_iter): Drop CTF_ERR usage for functions returning int. (ctf_enum_iter): Likewise. (ctf_type_size): Likewise. (ctf_type_align): Likewise. Cast to size_t where appropriate. (ctf_type_kind_unsliced): Likewise. (ctf_type_kind): Likewise. (ctf_type_encoding): Likewise. (ctf_member_info): Likewise. (ctf_array_info): Likewise. (ctf_enum_value): Likewise. (ctf_type_rvisit): Likewise. * ctf-open-bfd.c (ctf_bfdopen): Drop cts_type, cts_flags and cts_offset. (ctf_simple_open): Likewise. (ctf_bfdopen_ctfsect): Likewise. Set cts_size properly. * Makefile.in: Regenerate. * aclocal.m4: Likewise. * config.h: Likewise. * configure: Likewise.
2019-05-31 17:10:51 +08:00
if ((ssize = ctf_type_size (src_fp, src_type)) < 0)
return CTF_ERR; /* errno is set for us. */
size = (size_t) ssize;
if (size > CTF_MAX_SIZE)
{
dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
}
else
dtd->dtd_data.ctt_size = (uint32_t) size;
dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, flag, vlen);
/* Make a final pass through the members changing each dmd_type (a
src_fp type) to an equivalent type in dst_fp. We pass through all
libctf: handle nonrepresentable types at link time GCC can emit references to type 0 to indicate that this type is one that is not representable in the version of CTF it emits (for instance, version 3 cannot encode vector types). Type 0 is already used in the function section to indicate padding inserted to skip functions we do not want to encode the type of, so using zero in this way is a good extension of the format: but libctf reports such types as ECTF_BADID, which is indistinguishable from file corruption via links to truly nonexistent types with IDs like 0xDEADBEEF etc, which we really do want to stop for. In particular, this stops all traversals of types dead at this point, preventing us from even dumping CTF files containing unrepresentable types to see what's going on! So add a new error, ECTF_NONREPRESENTABLE, which is returned by recursive type resolution when a reference to a zero type is found. (No zero type is ever emitted into the CTF file by GCC, only references to one). We can't do much with types that are ultimately nonrepresentable, but we can do enough to keep functioning. Adjust ctf_add_type to ensure that top-level types of type zero and structure and union members of ultimate type zero are simply skipped without reporting an error, so we can copy structures and unions that contain nonrepresentable members (skipping them and leaving a hole where they would be, so no consumers downstream of the linker need to worry about this): adjust the dumper so that we dump members of nonrepresentable types in a simple form that indicates nonrepresentability rather than terminating the dump, and do not falsely assume all errors to be -ENOMEM: adjust the linker so that types that fail to get added are simply skipped, so that both nonrepresentable types and outright errors do not terminate the type addition, which could skip many valid types and cause further errors when variables of those types are added. In future, when we gain the ability to call back to the linker to report link-time type resolution errors, we should report failures to add all but nonrepresentable types. But we can't do that yet. v5: Fix tabdamage. include/ * ctf-api.h (ECTF_NONREPRESENTABLE): New. libctf/ * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on type zero. * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable members and types. (ctf_add_variable): Likewise for variables pointing to them. * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable type link failure, but do warn for others. * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all errors to be ENOMEM. (ctf_dump_member): Likewise. (ctf_dump_type): Likewise. (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. (ctf_dump_header): Likewise. (ctf_dump_label): likewise. (ctf_dump_objts): likewise. (ctf_dump_funcs): likewise. (ctf_dump_var): likewise. (ctf_dump_str): Likewise.
2019-08-05 18:40:33 +08:00
members, leaving any that fail set to CTF_ERR, unless they fail
because they are marking a member of type not representable in this
version of CTF, in which case we just want to silently omit them:
no consumer can do anything with them anyway. */
for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members);
dmd != NULL; dmd = ctf_list_next (dmd))
{
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_dict_t *dst = dst_fp;
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctf_id_t memb_type;
memb_type = ctf_type_mapping (src_fp, dmd->dmd_type, &dst);
if (memb_type == 0)
libctf: handle nonrepresentable types at link time GCC can emit references to type 0 to indicate that this type is one that is not representable in the version of CTF it emits (for instance, version 3 cannot encode vector types). Type 0 is already used in the function section to indicate padding inserted to skip functions we do not want to encode the type of, so using zero in this way is a good extension of the format: but libctf reports such types as ECTF_BADID, which is indistinguishable from file corruption via links to truly nonexistent types with IDs like 0xDEADBEEF etc, which we really do want to stop for. In particular, this stops all traversals of types dead at this point, preventing us from even dumping CTF files containing unrepresentable types to see what's going on! So add a new error, ECTF_NONREPRESENTABLE, which is returned by recursive type resolution when a reference to a zero type is found. (No zero type is ever emitted into the CTF file by GCC, only references to one). We can't do much with types that are ultimately nonrepresentable, but we can do enough to keep functioning. Adjust ctf_add_type to ensure that top-level types of type zero and structure and union members of ultimate type zero are simply skipped without reporting an error, so we can copy structures and unions that contain nonrepresentable members (skipping them and leaving a hole where they would be, so no consumers downstream of the linker need to worry about this): adjust the dumper so that we dump members of nonrepresentable types in a simple form that indicates nonrepresentability rather than terminating the dump, and do not falsely assume all errors to be -ENOMEM: adjust the linker so that types that fail to get added are simply skipped, so that both nonrepresentable types and outright errors do not terminate the type addition, which could skip many valid types and cause further errors when variables of those types are added. In future, when we gain the ability to call back to the linker to report link-time type resolution errors, we should report failures to add all but nonrepresentable types. But we can't do that yet. v5: Fix tabdamage. include/ * ctf-api.h (ECTF_NONREPRESENTABLE): New. libctf/ * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on type zero. * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable members and types. (ctf_add_variable): Likewise for variables pointing to them. * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable type link failure, but do warn for others. * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all errors to be ENOMEM. (ctf_dump_member): Likewise. (ctf_dump_type): Likewise. (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. (ctf_dump_header): Likewise. (ctf_dump_label): likewise. (ctf_dump_objts): likewise. (ctf_dump_funcs): likewise. (ctf_dump_var): likewise. (ctf_dump_str): Likewise.
2019-08-05 18:40:33 +08:00
{
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if ((dmd->dmd_type =
ctf_add_type_internal (dst_fp, src_fp, dmd->dmd_type,
proc_tracking_fp)) == CTF_ERR)
{
if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE)
errs++;
}
libctf: handle nonrepresentable types at link time GCC can emit references to type 0 to indicate that this type is one that is not representable in the version of CTF it emits (for instance, version 3 cannot encode vector types). Type 0 is already used in the function section to indicate padding inserted to skip functions we do not want to encode the type of, so using zero in this way is a good extension of the format: but libctf reports such types as ECTF_BADID, which is indistinguishable from file corruption via links to truly nonexistent types with IDs like 0xDEADBEEF etc, which we really do want to stop for. In particular, this stops all traversals of types dead at this point, preventing us from even dumping CTF files containing unrepresentable types to see what's going on! So add a new error, ECTF_NONREPRESENTABLE, which is returned by recursive type resolution when a reference to a zero type is found. (No zero type is ever emitted into the CTF file by GCC, only references to one). We can't do much with types that are ultimately nonrepresentable, but we can do enough to keep functioning. Adjust ctf_add_type to ensure that top-level types of type zero and structure and union members of ultimate type zero are simply skipped without reporting an error, so we can copy structures and unions that contain nonrepresentable members (skipping them and leaving a hole where they would be, so no consumers downstream of the linker need to worry about this): adjust the dumper so that we dump members of nonrepresentable types in a simple form that indicates nonrepresentability rather than terminating the dump, and do not falsely assume all errors to be -ENOMEM: adjust the linker so that types that fail to get added are simply skipped, so that both nonrepresentable types and outright errors do not terminate the type addition, which could skip many valid types and cause further errors when variables of those types are added. In future, when we gain the ability to call back to the linker to report link-time type resolution errors, we should report failures to add all but nonrepresentable types. But we can't do that yet. v5: Fix tabdamage. include/ * ctf-api.h (ECTF_NONREPRESENTABLE): New. libctf/ * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on type zero. * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable members and types. (ctf_add_variable): Likewise for variables pointing to them. * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable type link failure, but do warn for others. * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all errors to be ENOMEM. (ctf_dump_member): Likewise. (ctf_dump_type): Likewise. (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. (ctf_dump_header): Likewise. (ctf_dump_label): likewise. (ctf_dump_objts): likewise. (ctf_dump_funcs): likewise. (ctf_dump_var): likewise. (ctf_dump_str): Likewise.
2019-08-05 18:40:33 +08:00
}
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
else
dmd->dmd_type = memb_type;
}
if (errs)
return CTF_ERR; /* errno is set for us. */
break;
}
case CTF_K_ENUM:
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
if (dst_type != CTF_ERR && kind != CTF_K_FORWARD
&& dst_kind != CTF_K_FORWARD)
{
if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst)
|| ctf_enum_iter (dst_fp, dst_type, enumcmp, &src))
{
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
_("conflict for enum %s against ID %lx: members "
"differ, see above"), name, dst_type);
return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
}
}
else
{
dst_type = ctf_add_enum (dst_fp, flag, name);
if ((dst.ctb_type = dst_type) == CTF_ERR
|| ctf_enum_iter (src_fp, src_type, enumadd, &dst))
return CTF_ERR; /* errno is set for us */
}
break;
case CTF_K_FORWARD:
if (dst_type == CTF_ERR)
libctf: teach ctf_add_type how forwards work This machinery has been broken for as long as Solaris has existed. Forwards are meant to encode "struct foo;", "enum foo;" or "union foo;". Obviously these all exist in distinct namespaces, so forwards store the type kind they forward to in their ctt_type member (which makes conceptual sense if you squint at it). The addition machinery uses this to promote forwards to the appropriate type as needed. Unfortunately ctf_add_type does not: it checks the global namespace (which is always wrong), and so fails with a spurious conflict if you have, say, a typedef and then a forward comes along with the same name, even if it's a forward to something like a struct. (This was observed with <libio.h>, which has "struct _IO_FILE;" and also "typedef struct _IO_FILE _IO_FILE"). We should look at the recorded type kind and look in the appropriate namespace. We should also, when creating the forward in the new container, use that type kind, rather than just defaulting to CTF_K_STRUCT and hoping that what eventually comes along is a struct. This bug is as old as the first implementation of ctf_add_type in Solaris. But we also want a new feature for the linker, closely-related and touching the same code so we add it here: not only do we want a forward followed by a struct/union/enum to promote the forward, but we want want a struct/union/enum followed by a forward to act as a NOP and return the existing type, because when we're adding many files in succession to a target link, there will often be already-promoted forwards (in the shape of a struct/union/enum) that want to unify with duplicate forwards coming from other object files. v5: fix tabdamage. libctf/ * ctf-create.c (ctf_add_type): Look up and use the forwarded-to type kind. Allow forwards to unify with pre-existing structs/ unions/enums.
2019-08-03 07:46:01 +08:00
dst_type = ctf_add_forward (dst_fp, flag, name, forward_kind);
break;
case CTF_K_TYPEDEF:
src_type = ctf_type_reference (src_fp, src_type);
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
src_type = ctf_add_type_internal (dst_fp, src_fp, src_type,
proc_tracking_fp);
if (src_type == CTF_ERR)
return CTF_ERR; /* errno is set for us. */
/* If dst_type is not CTF_ERR at this point, we should check if
ctf_type_reference(dst_fp, dst_type) != src_type and if so fail with
ECTF_CONFLICT. However, this causes problems with bitness typedefs
that vary based on things like if 32-bit then pid_t is int otherwise
long. We therefore omit this check and assume that if the identically
named typedef already exists in dst_fp, it is correct or
equivalent. */
if (dst_type == CTF_ERR)
dst_type = ctf_add_typedef (dst_fp, flag, name, src_type);
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
break;
default:
return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
}
libctf: map from old to corresponding newly-added types in ctf_add_type This lets you call ctf_type_mapping (dest_fp, src_fp, src_type_id) and get told what type ID the corresponding type has in the target ctf_file_t. This works even if it was added by a recursive call, and because it is stored in the target ctf_file_t it works even if we had to add one type to multiple ctf_file_t's as part of conflicting type handling. We empty out this mapping after every archive is linked: because it maps input to output fps, and we only visit each input fp once, its contents are rendered entirely useless every time the source fp changes. v3: add several missing mapping additions. Add ctf_dynhash_empty, and empty after every input archive. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t): New field ctf_link_type_mapping. (struct ctf_link_type_mapping_key): New. (ctf_hash_type_mapping_key): Likewise. (ctf_hash_eq_type_mapping_key): Likewise. (ctf_add_type_mapping): Likewise. (ctf_type_mapping): Likewise. (ctf_dynhash_empty): Likewise. * ctf-open.c (ctf_file_close): Update accordingly. * ctf-create.c (ctf_update): Likewise. (ctf_add_type): Populate the mapping. * ctf-hash.c (ctf_hash_type_mapping_key): Hash a type mapping key. (ctf_hash_eq_type_mapping_key): Check the key for equality. (ctf_dynhash_insert): Fix comment typo. (ctf_dynhash_empty): New. * ctf-link.c (ctf_add_type_mapping): New. (ctf_type_mapping): Likewise. (empty_link_type_mapping): New. (ctf_link_one_input_archive): Call it.
2019-07-14 04:31:26 +08:00
if (dst_type != CTF_ERR)
ctf_add_type_mapping (src_fp, orig_src_type, dst_fp, dst_type);
return dst_type;
}
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
ctf_id_t
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_add_type (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type)
libctf: properly handle ctf_add_type of forwards and self-reffing structs The code to handle structures (and unions) that refer to themselves in ctf_add_type is extremely dodgy. It works by looking through the list of not-yet-committed types for a structure with the same name as the structure in question and assuming, if it finds it, that this must be a reference to the same type. This is a linear search that gets ever slower as the dictionary grows, requiring you to call ctf_update at intervals to keep performance tolerable: but if you do that, you run into the problem that if a forward declared before the ctf_update is changed to a structure afterwards, ctf_update explodes. The last commit fixed most of this: this commit can use it, adding a new ctf_add_processing hash that tracks source type IDs that are currently being processed and uses it to avoid infinite recursion rather than the dynamic type list: we split ctf_add_type into a ctf_add_type_internal, so that ctf_add_type itself can become a wrapper that empties out this being-processed hash once the entire recursive type addition is over. Structure additions themselves avoid adding their dependent types quite so much by checking the type mapping and avoiding re-adding types we already know we have added. We also add support for adding forwards to dictionaries that already contain the thing they are a forward to: we just silently return the original type. v4: return existing struct/union/enum types properly, rather than using an uninitialized variable: shrinks sizes of CTF sections back down to roughly where they were in v1/v2 of this patch series. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_file_t) <ctf_add_processing>: New. * ctf-open.c (ctf_file_close): Free it. * ctf-create.c (ctf_serialize): Adjust. (membcmp): When reporting a conflict due to an error, report the error. (ctf_add_type): Turn into a ctf_add_processing wrapper. Rename to... (ctf_add_type_internal): ... this. Hand back types we are already in the middle of adding immediately. Hand back structs/unions with the same number of members immediately. Do not walk the dynamic list. Call ctf_add_type_internal, not ctf_add_type. Handle forwards promoted to other types and the inverse case identically. Add structs to the mapping as soon as we intern them, before they gain any members.
2019-08-08 01:01:08 +08:00
{
ctf_id_t id;
if (!src_fp->ctf_add_processing)
src_fp->ctf_add_processing = ctf_dynhash_create (ctf_hash_integer,
ctf_hash_eq_integer,
NULL, NULL);
/* We store the hash on the source, because it contains only source type IDs:
but callers will invariably expect errors to appear on the dest. */
if (!src_fp->ctf_add_processing)
return (ctf_set_errno (dst_fp, ENOMEM));
id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp);
ctf_dynhash_empty (src_fp->ctf_add_processing);
return id;
}
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
/* Write the compressed CTF data stream to the specified gzFile descriptor. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_gzwrite (ctf_dict_t *fp, gzFile fd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
const unsigned char *buf;
ssize_t resid;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ssize_t len;
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
resid = sizeof (ctf_header_t);
buf = (unsigned char *) fp->ctf_header;
while (resid != 0)
{
if ((len = gzwrite (fd, buf, resid)) <= 0)
return (ctf_set_errno (fp, errno));
resid -= len;
buf += len;
}
resid = fp->ctf_size;
buf = fp->ctf_buf;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
while (resid != 0)
{
if ((len = gzwrite (fd, buf, resid)) <= 0)
return (ctf_set_errno (fp, errno));
resid -= len;
buf += len;
}
return 0;
}
/* Compress the specified CTF data stream and write it to the specified file
descriptor. */
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_compress_write (ctf_dict_t *fp, int fd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
unsigned char *buf;
unsigned char *bp;
ctf_header_t h;
ctf_header_t *hp = &h;
ssize_t header_len = sizeof (ctf_header_t);
ssize_t compress_len;
ssize_t len;
int rc;
int err = 0;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (ctf_serialize (fp) < 0)
return -1; /* errno is set for us. */
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
memcpy (hp, fp->ctf_header, header_len);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
hp->cth_flags |= CTF_F_COMPRESS;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
compress_len = compressBound (fp->ctf_size);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
if ((buf = malloc (compress_len)) == NULL)
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
{
ctf_err_warn (fp, 0, 0, _("ctf_compress_write: cannot allocate %li bytes"),
(unsigned long) compress_len);
return (ctf_set_errno (fp, ECTF_ZALLOC));
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
libctf: drop mmap()-based CTF data allocator This allocator has the ostensible benefit that it lets us mprotect() the memory used for CTF storage: but in exchange for this it adds considerable complexity, since we have to track allocation sizes ourselves for use at freeing time, note whether the data we are storing was ctf_data_alloc()ed or not so we know if we can safely mprotect() it... and while the mprotect()ing has found few bugs, it *has* been the cause of more than one due to errors in all this tracking leading to us mprotect()ing bits of the heap and stuff like that. We are about to start composing CTF buffers from pieces so that we can do usage-based optimizations on the strtab. This means we need realloc(), which needs nonportable mremap() and *more* tracking of the *original* allocation size, and the complexity and bureaucracy of all of this is just too high for its negligible benefits. Drop the whole thing and just use malloc() like everyone else. It knows better than we do when it is safe to use mmap() under the covers, anyway. While we're at it, don't leak the entire buffer if ctf_compress_write() fails to compress it. libctf/ * ctf-subr.c (_PAGESIZE): Remove. (ctf_data_alloc): Likewise. (ctf_data_free): Likewise. (ctf_data_protect): Likewise. * ctf-impl.h: Remove declarations. * ctf-create.c (ctf_update): No longer call ctf_data_protect: use ctf_free, not ctf_data_free. (ctf_compress_write): Use ctf_data_alloc, not ctf_alloc. Free the buffer again on compression error. * ctf-open.c (ctf_set_base): No longer track the size: call ctf_free, not ctf_data_free. (upgrade_types): Likewise. Call ctf_alloc, not ctf_data_alloc. (ctf_bufopen): Likewise. No longer call ctf_data_protect.
2019-06-19 19:20:47 +08:00
if ((rc = compress (buf, (uLongf *) &compress_len,
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
fp->ctf_buf, fp->ctf_size)) != Z_OK)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
err = ctf_set_errno (fp, ECTF_COMPRESS);
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
goto ret;
}
while (header_len > 0)
{
if ((len = write (fd, hp, header_len)) < 0)
{
err = ctf_set_errno (fp, errno);
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing header"));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
goto ret;
}
header_len -= len;
hp += len;
}
bp = buf;
while (compress_len > 0)
{
if ((len = write (fd, bp, compress_len)) < 0)
{
err = ctf_set_errno (fp, errno);
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (fp, 0, 0, _("ctf_compress_write: error writing"));
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
goto ret;
}
compress_len -= len;
bp += len;
}
ret:
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (buf);
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
return err;
}
/* Optionally compress the specified CTF data stream and return it as a new
dynamically-allocated string. */
unsigned char *
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_write_mem (ctf_dict_t *fp, size_t *size, size_t threshold)
{
unsigned char *buf;
unsigned char *bp;
ctf_header_t *hp;
ssize_t header_len = sizeof (ctf_header_t);
ssize_t compress_len;
int rc;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (ctf_serialize (fp) < 0)
return NULL; /* errno is set for us. */
compress_len = compressBound (fp->ctf_size);
if (fp->ctf_size < threshold)
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
compress_len = fp->ctf_size;
if ((buf = malloc (compress_len
+ sizeof (struct ctf_header))) == NULL)
{
ctf_set_errno (fp, ENOMEM);
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (fp, 0, 0, _("ctf_write_mem: cannot allocate %li bytes"),
(unsigned long) (compress_len + sizeof (struct ctf_header)));
return NULL;
}
hp = (ctf_header_t *) buf;
memcpy (hp, fp->ctf_header, header_len);
bp = buf + sizeof (struct ctf_header);
*size = sizeof (struct ctf_header);
if (fp->ctf_size < threshold)
{
hp->cth_flags &= ~CTF_F_COMPRESS;
memcpy (bp, fp->ctf_buf, fp->ctf_size);
*size += fp->ctf_size;
}
else
{
hp->cth_flags |= CTF_F_COMPRESS;
if ((rc = compress (bp, (uLongf *) &compress_len,
fp->ctf_buf, fp->ctf_size)) != Z_OK)
{
ctf_set_errno (fp, ECTF_COMPRESS);
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
ctf_err_warn (fp, 0, 0, _("zlib deflate err: %s"), zError (rc));
libctf: remove ctf_malloc, ctf_free and ctf_strdup These just get in the way of auditing for erroneous usage of strdup and add a huge irregular surface of "ctf_malloc or malloc? ctf_free or free? ctf_strdup or strdup?" ctf_malloc and ctf_free usage has not reliably matched up for many years, if ever, making the whole game pointless. Go back to malloc, free, and strdup like everyone else: while we're at it, fix a bunch of places where we weren't properly checking for OOM. This changes the interface of ctf_cuname_set and ctf_parent_name_set, which could strdup but could not return errors (like ENOMEM). New in v4. include/ * ctf-api.h (ctf_cuname_set): Can now fail, returning int. (ctf_parent_name_set): Likewise. libctf/ * ctf-impl.h (ctf_alloc): Remove. (ctf_free): Likewise. (ctf_strdup): Likewise. * ctf-subr.c (ctf_alloc): Remove. (ctf_free): Likewise. * ctf-util.c (ctf_strdup): Remove. * ctf-create.c (ctf_serialize): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dtd_delete): Likewise. (ctf_dvd_delete): Likewise. (ctf_add_generic): Likewise. (ctf_add_function): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_variable): Likewise. (membadd): Likewise. (ctf_compress_write): Likewise. (ctf_write_mem): Likewise. * ctf-decl.c (ctf_decl_push): Likewise. (ctf_decl_fini): Likewise. (ctf_decl_sprintf): Likewise. Check for OOM. * ctf-dump.c (ctf_dump_append): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_dump_free): Likewise. (ctf_dump): Likewise. * ctf-open.c (upgrade_types_v1): Likewise. (init_types): Likewise. (ctf_file_close): Likewise. (ctf_bufopen_internal): Likewise. Check for OOM. (ctf_parent_name_set): Likewise: report the OOM to the caller. (ctf_cuname_set): Likewise. (ctf_import): Likewise. * ctf-string.c (ctf_str_purge_atom_refs): Use malloc, not ctf_alloc; free, not ctf_free; strdup, not ctf_strdup. (ctf_str_free_atom): Likewise. (ctf_str_create_atoms): Likewise. (ctf_str_add_ref_internal): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_write_strtab): Likewise.
2019-09-17 13:54:23 +08:00
free (buf);
return NULL;
}
*size += compress_len;
}
return buf;
}
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
/* Write the uncompressed CTF data stream to the specified file descriptor. */
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
int
libctf, include, binutils, gdb, ld: rename ctf_file_t to ctf_dict_t The naming of the ctf_file_t type in libctf is a historical curiosity. Back in the Solaris days, CTF dictionaries were originally generated as a separate file and then (sometimes) merged into objects: hence the datatype was named ctf_file_t, and known as a "CTF file". Nowadays, raw CTF is essentially never written to a file on its own, and the datatype changed name to a "CTF dictionary" years ago. So the term "CTF file" refers to something that is never a file! This is at best confusing. The type has also historically been known as a 'CTF container", which is even more confusing now that we have CTF archives which are *also* a sort of container (they contain CTF dictionaries), but which are never referred to as containers in the source code. So fix this by completing the renaming, renaming ctf_file_t to ctf_dict_t throughout, and renaming those few functions that refer to CTF files by name (keeping compatibility aliases) to refer to dicts instead. Old users who still refer to ctf_file_t will see (harmless) pointer-compatibility warnings at compile time, but the ABI is unchanged (since C doesn't mangle names, and ctf_file_t was always an opaque type) and things will still compile fine as long as -Werror is not specified. All references to CTF containers and CTF files in the source code are fixed to refer to CTF dicts instead. Further (smaller) renamings of annoyingly-named functions to come, as part of the process of souping up queries across whole archives at once (needed for the function info and data object sections). binutils/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. * readelf.c (dump_ctf_errs): Rename ctf_file_t to ctf_dict_t. (dump_ctf_archive_member): Likewise. (dump_section_as_ctf): Likewise. Use ctf_dict_close, not ctf_file_close. gdb/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctfread.c: Change uses of ctf_file_t to ctf_dict_t. (ctf_fp_info::~ctf_fp_info): Call ctf_dict_close, not ctf_file_close. include/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_file_t): Rename to... (ctf_dict_t): ... this. Keep ctf_file_t around for compatibility. (struct ctf_file): Likewise rename to... (struct ctf_dict): ... this. (ctf_file_close): Rename to... (ctf_dict_close): ... this, keeping compatibility function. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this, keeping compatibility function. All callers adjusted. * ctf.h: Rename references to ctf_file_t to ctf_dict_t. (struct ctf_archive) <ctfa_nfiles>: Rename to... <ctfa_ndicts>: ... this. ld/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (ctf_output): This is a ctf_dict_t now. (lang_ctf_errs_warnings): Rename ctf_file_t to ctf_dict_t. (ldlang_open_ctf): Adjust comment. (lang_merge_ctf): Use ctf_dict_close, not ctf_file_close. * ldelfgen.h (ldelf_examine_strtab_for_ctf): Rename ctf_file_t to ctf_dict_t. Change opaque declaration accordingly. * ldelfgen.c (ldelf_examine_strtab_for_ctf): Adjust. * ldemul.h (examine_strtab_for_ctf): Likewise. (ldemul_examine_strtab_for_ctf): Likewise. * ldeuml.c (ldemul_examine_strtab_for_ctf): Likewise. libctf/ChangeLog 2020-11-20 Nick Alcock <nick.alcock@oracle.com> * ctf-impl.h: Rename ctf_file_t to ctf_dict_t: all declarations adjusted. (ctf_fileops): Rename to... (ctf_dictops): ... this. (ctf_dedup_t) <cd_id_to_file_t>: Rename to... <cd_id_to_dict_t>: ... this. (ctf_file_t): Fix outdated comment. <ctf_fileops>: Rename to... <ctf_dictops>: ... this. (struct ctf_archive_internal) <ctfi_file>: Rename to... <ctfi_dict>: ... this. * ctf-archive.c: Rename ctf_file_t to ctf_dict_t. Rename ctf_archive.ctfa_nfiles to ctfa_ndicts. Rename ctf_file_close to ctf_dict_close. All users adjusted. * ctf-create.c: Likewise. Refer to CTF dicts, not CTF containers. (ctf_bundle_t) <ctb_file>: Rename to... <ctb_dict): ... this. * ctf-decl.c: Rename ctf_file_t to ctf_dict_t. * ctf-dedup.c: Likewise. Rename ctf_file_close to ctf_dict_close. Refer to CTF dicts, not CTF containers. * ctf-dump.c: Likewise. * ctf-error.c: Likewise. * ctf-hash.c: Likewise. * ctf-inlines.h: Likewise. * ctf-labels.c: Likewise. * ctf-link.c: Likewise. * ctf-lookup.c: Likewise. * ctf-open-bfd.c: Likewise. * ctf-string.c: Likewise. * ctf-subr.c: Likewise. * ctf-types.c: Likewise. * ctf-util.c: Likewise. * ctf-open.c: Likewise. (ctf_file_close): Rename to... (ctf_dict_close): ...this. (ctf_file_close): New trivial wrapper around ctf_dict_close, for compatibility. (ctf_parent_file): Rename to... (ctf_parent_dict): ... this. (ctf_parent_file): New trivial wrapper around ctf_parent_dict, for compatibility. * libctf.ver: Add ctf_dict_close and ctf_parent_dict.
2020-11-20 21:34:04 +08:00
ctf_write (ctf_dict_t *fp, int fd)
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
{
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
const unsigned char *buf;
ssize_t resid;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
ssize_t len;
libctf: avoid the need to ever use ctf_update The method of operation of libctf when the dictionary is writable has before now been that types that are added land in the dynamic type section, which is a linked list and hash of IDs -> dynamic type definitions (and, recently a hash of names): the DTDs are a bit of CTF representing the ctf_type_t and ad hoc C structures representing the vlen. Historically, libctf was unable to do anything with these types, not even look them up by ID, let alone by name: if you wanted to do that say if you were adding a type that depended on one you just added) you called ctf_update, which serializes all the DTDs into a CTF file and reopens it, copying its guts over the fp it's called with. The ctf_updated types are then frozen in amber and unchangeable: all lookups will return the types in the static portion in preference to the dynamic portion, and we will refuse to re-add things that already exist in the static portion (and, of late, in the dynamic portion too). The libctf machinery remembers the boundary between static and dynamic types and looks in the right portion for each type. Lots of things still don't quite work with dynamic types (e.g. getting their size), but enough works to do a bunch of additions and then a ctf_update, most of the time. Except it doesn't, because ctf_add_type finds it necessary to walk the full dynamic type definition list looking for types with matching names, so it gets slower and slower with every type you add: fixing this requires calling ctf_update periodically for no other reason than to avoid massively slowing things down. This is all clunky and very slow but kind of works, until you consider that it is in fact possible and indeed necessary to modify one sort of type after it has been added: forwards. These are necessarily promoted to structs, unions or enums, and when they do so *their type ID does not change*. So all of a sudden we are changing types that already exist in the static portion. ctf_update gets massively confused by this and allocates space enough for the forward (with no members), but then emits the new dynamic type (with all the members) into it. You get an assertion failure after that, if you're lucky, or a coredump. So this commit rejigs things a bit and arranges to exclusively use the dynamic type definitions in writable dictionaries, and the static type definitions in readable dictionaries: we don't at any time have a mixture of static and dynamic types, and you don't need to call ctf_update to make things "appear". The ctf_dtbyname hash I introduced a few months ago, which maps things like "struct foo" to DTDs, is removed, replaced instead by a change of type of the four dictionaries which track names. Rather than just being (unresizable) ctf_hash_t's populated only at ctf_bufopen time, they are now a ctf_names_t structure, which is a pair of ctf_hash_t and ctf_dynhash_t, with the ctf_hash_t portion being used in readonly dictionaries, and the ctf_dynhash_t being used in writable ones. The decision as to which to use is centralized in the new functions ctf_lookup_by_rawname (which takes a type kind) and ctf_lookup_by_rawhash, which it calls (which takes a ctf_names_t *.) This change lets us switch from using static to dynamic name hashes on the fly across the entirety of libctf without complexifying anything: in fact, because we now centralize the knowledge about how to map from type kind to name hash, it actually simplifies things and lets us throw out quite a lot of now-unnecessary complexity, from ctf_dtnyname (replaced by the dynamic half of the name tables), through to ctf_dtnextid (now that a dictionary's static portion is never referenced if the dictionary is writable, we can just use ctf_typemax to indicate the maximum type: dynamic or non-dynamic does not matter, and we no longer need to track the boundary between the types). You can now ctf_rollback() as far as you like, even past a ctf_update or for that matter a full writeout; all the iteration functions work just as well on writable as on read-only dictionaries; ctf_add_type no longer needs expensive duplicated code to run over the dynamic types hunting for ones it might be interested in; and the linker no longer needs a hack to call ctf_update so that calling ctf_add_type is not impossibly expensive. There is still a bit more complexity: some new code paths in ctf-types.c need to know how to extract information from dynamic types. This complexity will go away again in a few months when libctf acquires a proper intermediate representation. You can still call ctf_update if you like (it's public API, after all), but its only effect now is to set the point to which ctf_discard rolls back. Obviously *something* still needs to serialize the CTF file before writeout, and this job is done by ctf_serialize, which does everything ctf_update used to except set the counter used by ctf_discard. It is automatically called by the various functions that do CTF writeout: nobody else ever needs to call it. With this in place, forwards that are promoted to non-forwards no longer crash the link, even if it happens tens of thousands of types later. v5: fix tabdamage. libctf/ * ctf-impl.h (ctf_names_t): New. (ctf_lookup_t) <ctf_hash>: Now a ctf_names_t, not a ctf_hash_t. (ctf_file_t) <ctf_structs>: Likewise. <ctf_unions>: Likewise. <ctf_enums>: Likewise. <ctf_names>: Likewise. <ctf_lookups>: Improve comment. <ctf_ptrtab_len>: New. <ctf_prov_strtab>: New. <ctf_str_prov_offset>: New. <ctf_dtbyname>: Remove, redundant to the names hashes. <ctf_dtnextid>: Remove, redundant to ctf_typemax. (ctf_dtdef_t) <dtd_name>: Remove. <dtd_data>: Note that the ctt_name is now populated. (ctf_str_atom_t) <csa_offset>: This is now the strtab offset for internal strings too. <csa_external_offset>: New, the external strtab offset. (CTF_INDEX_TO_TYPEPTR): Handle the LCTF_RDWR case. (ctf_name_table): New declaration. (ctf_lookup_by_rawname): Likewise. (ctf_lookup_by_rawhash): Likewise. (ctf_set_ctl_hashes): Likewise. (ctf_serialize): Likewise. (ctf_dtd_insert): Adjust. (ctf_simple_open_internal): Likewise. (ctf_bufopen_internal): Likewise. (ctf_list_empty_p): Likewise. (ctf_str_remove_ref): Likewise. (ctf_str_add): Returns uint32_t now. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Now returns a boolean (int). * ctf-string.c (ctf_strraw_explicit): Check the ctf_prov_strtab for strings in the appropriate range. (ctf_str_create_atoms): Create the ctf_prov_strtab. Detect OOM when adding the null string to the new strtab. (ctf_str_free_atoms): Destroy the ctf_prov_strtab. (ctf_str_add_ref_internal): Add make_provisional argument. If make_provisional, populate the offset and fill in the ctf_prov_strtab accordingly. (ctf_str_add): Return the offset, not the string. (ctf_str_add_ref): Likewise. (ctf_str_add_external): Return a success integer. (ctf_str_remove_ref): New, remove a single ref. (ctf_str_count_strtab): Do not count the initial null string's length or the existence or length of any unreferenced internal atoms. (ctf_str_populate_sorttab): Skip atoms with no refs. (ctf_str_write_strtab): Populate the nullstr earlier. Add one to the cts_len for the null string, since it is no longer done in ctf_str_count_strtab. Adjust for csa_external_offset rename. Populate the csa_offset for both internal and external cases. Flush the ctf_prov_strtab afterwards, and reset the ctf_str_prov_offset. * ctf-create.c (ctf_grow_ptrtab): New. (ctf_create): Call it. Initialize new fields rather than old ones. Tell ctf_bufopen_internal that this is a writable dictionary. Set the ctl hashes and data model. (ctf_update): Rename to... (ctf_serialize): ... this. Leave a compatibility function behind. Tell ctf_simple_open_internal that this is a writable dictionary. Pass the new fields along from the old dictionary. Drop ctf_dtnextid and ctf_dtbyname. Use ctf_strraw, not dtd_name. Do not zero out the DTD's ctt_name. (ctf_prefixed_name): Rename to... (ctf_name_table): ... this. No longer return a prefixed name: return the applicable name table instead. (ctf_dtd_insert): Use it, and use the right name table. Pass in the kind we're adding. Migrate away from dtd_name. (ctf_dtd_delete): Adjust similarly. Remove the ref to the deleted ctt_name. (ctf_dtd_lookup_type_by_name): Remove. (ctf_dynamic_type): Always return NULL on read-only dictionaries. No longer check ctf_dtnextid: check ctf_typemax instead. (ctf_snapshot): No longer use ctf_dtnextid: use ctf_typemax instead. (ctf_rollback): Likewise. No longer fail with ECTF_OVERROLLBACK. Use ctf_name_table and the right name table, and migrate away from dtd_name as in ctf_dtd_delete. (ctf_add_generic): Pass in the kind explicitly and pass it to ctf_dtd_insert. Use ctf_typemax, not ctf_dtnextid. Migrate away from dtd_name to using ctf_str_add_ref to populate the ctt_name. Grow the ptrtab if needed. (ctf_add_encoded): Pass in the kind. (ctf_add_slice): Likewise. (ctf_add_array): Likewise. (ctf_add_function): Likewise. (ctf_add_typedef): Likewise. (ctf_add_reftype): Likewise. Initialize the ctf_ptrtab, checking ctt_name rather than dtd_name. (ctf_add_struct_sized): Pass in the kind. Use ctf_lookup_by_rawname, not ctf_hash_lookup_type / ctf_dtd_lookup_type_by_name. (ctf_add_union_sized): Likewise. (ctf_add_enum): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_forward): Likewise. (ctf_add_type): Likewise. (ctf_compress_write): Call ctf_serialize: adjust for ctf_size not being initialized until after the call. (ctf_write_mem): Likewise. (ctf_write): Likewise. * ctf-archive.c (arc_write_one_ctf): Likewise. * ctf-lookup.c (ctf_lookup_by_name): Use ctf_lookuup_by_rawhash, not ctf_hash_lookup_type. (ctf_lookup_by_id): No longer check the readonly types if the dictionary is writable. * ctf-open.c (init_types): Assert that this dictionary is not writable. Adjust to use the new name hashes, ctf_name_table, and ctf_ptrtab_len. GNU style fix for the final ptrtab scan. (ctf_bufopen_internal): New 'writable' parameter. Flip on LCTF_RDWR if set. Drop out early when dictionary is writable. Split the ctf_lookups initialization into... (ctf_set_cth_hashes): ... this new function. (ctf_simple_open_internal): Adjust. New 'writable' parameter. (ctf_simple_open): Adjust accordingly. (ctf_bufopen): Likewise. (ctf_file_close): Destroy the appropriate name hashes. No longer destroy ctf_dtbyname, which is gone. (ctf_getdatasect): Remove spurious "extern". * ctf-types.c (ctf_lookup_by_rawname): New, look up types in the specified name table, given a kind. (ctf_lookup_by_rawhash): Likewise, given a ctf_names_t *. (ctf_member_iter): Add support for iterating over the dynamic type list. (ctf_enum_iter): Likewise. (ctf_variable_iter): Likewise. (ctf_type_rvisit): Likewise. (ctf_member_info): Add support for types in the dynamic type list. (ctf_enum_name): Likewise. (ctf_enum_value): Likewise. (ctf_func_type_info): Likewise. (ctf_func_type_args): Likewise. * ctf-link.c (ctf_accumulate_archive_names): No longer call ctf_update. (ctf_link_write): Likewise. (ctf_link_intern_extern_string): Adjust for new ctf_str_add_external return value. (ctf_link_add_strtab): Likewise. * ctf-util.c (ctf_list_empty_p): New.
2019-08-08 00:55:09 +08:00
if (ctf_serialize (fp) < 0)
return -1; /* errno is set for us. */
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
resid = sizeof (ctf_header_t);
buf = (unsigned char *) fp->ctf_header;
while (resid != 0)
{
if ((len = write (fd, buf, resid)) <= 0)
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
{
ctf_err_warn (fp, 0, errno, _("ctf_write: error writing header"));
return (ctf_set_errno (fp, errno));
}
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
resid -= len;
buf += len;
}
resid = fp->ctf_size;
buf = fp->ctf_buf;
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
while (resid != 0)
{
libctf: allow the header to change between versions libctf supports dynamic upgrading of the type table as file format versions change, but before now has not supported changes to the CTF header. Doing this is complicated by the baroque storage method used: the CTF header is kept prepended to the rest of the CTF data, just as when read from the file, and written out from there, and is endian-flipped in place. This makes accessing it needlessly hard and makes it almost impossible to make the header larger if we add fields. The general storage machinery around the malloced ctf pointer (the 'ctf_base') is also overcomplicated: the pointer is sometimes malloced locally and sometimes assigned from a parameter, so freeing it requires checking to see if that parameter was used, needlessly coupling ctf_bufopen and ctf_file_close together. So split the header out into a new ctf_file_t.ctf_header, which is written out explicitly: squeeze it out of the CTF buffer whenever we reallocate it, and use ctf_file_t.ctf_buf to skip past the header when we do not need to reallocate (when no upgrading or endian-flipping is required). We now track whether the CTF base can be freed explicitly via a new ctf_dynbase pointer which is non-NULL only when freeing is possible. With all this done, we can upgrade the header on the fly and add new fields as desired, via a new upgrade_header function in ctf-open. As with other forms of upgrading, libctf upgrades older headers automatically to the latest supported version at open time. For a first use of this field, we add a new string field cth_cuname, and a corresponding setter/getter pair ctf_cuname_set and ctf_cuname: this is used by debuggers to determine whether a CTF section's types relate to a single compilation unit, or to all compilation units in the program. (Types with ambiguous definitions in different CUs have only one of these types placed in the top-level shared .ctf container: the rest are placed in much smaller per-CU containers, which have the shared container as their parent. Since CTF must be useful in the absence of DWARF, we store the names of the relevant CUs ourselves, so the debugger can look them up.) v5: fix tabdamage. include/ * ctf-api.h (ctf_cuname): New function. (ctf_cuname_set): Likewise. * ctf.h: Improve comment around upgrading, no longer implying that v2 is the target of upgrades (it is v3 now). (ctf_header_v2_t): New, old-format header for backward compatibility. (ctf_header_t): Add cth_cuname: this is the first of several header changes in format v3. libctf/ * ctf-impl.h (ctf_file_t): New fields ctf_header, ctf_dynbase, ctf_cuname, ctf_dyncuname: ctf_base and ctf_buf are no longer const. * ctf-open.c (ctf_set_base): Preserve the gap between ctf_buf and ctf_base: do not assume that it is always sizeof (ctf_header_t). Print out ctf_cuname: only print out ctf_parname if set. (ctf_free_base): Removed, ctf_base is no longer freed: free ctf_dynbase instead. (ctf_set_version): Fix spacing. (upgrade_header): New, in-place header upgrading. (upgrade_types): Rename to... (upgrade_types_v1): ... this. Free ctf_dynbase, not ctf_base. No longer track old and new headers separately. No longer allow for header sizes explicitly: squeeze the headers out on upgrade (they are preserved in fp->ctf_header). Set ctf_dynbase, ctf_base and ctf_buf explicitly. Use ctf_free, not ctf_free_base. (upgrade_types): New, also handle ctf_parmax updating. (flip_header): Flip ctf_cuname. (flip_types): Flip BUF explicitly rather than deriving BUF from BASE. (ctf_bufopen): Store the header in fp->ctf_header. Correct minimum required alignment of objtoff and funcoff. No longer store it in the ctf_buf unless that buf is derived unmodified from the input. Set ctf_dynbase where ctf_base is dynamically allocated. Drop locals that duplicate fields in ctf_file: move allocation of ctf_file further up instead. Call upgrade_header as needed. Move version-specific ctf_parmax initialization into upgrade_types. More concise error handling. (ctf_file_close): No longer test for null pointers before freeing. Free ctf_dyncuname, ctf_dynbase, and ctf_header. Do not call ctf_free_base. (ctf_cuname): New. (ctf_cuname_set): New. * ctf-create.c (ctf_update): Populate ctf_cuname. (ctf_gzwrite): Write out the header explicitly. Remove obsolescent comment. (ctf_write): Likewise. (ctf_compress_write): Get the header from ctf_header, not ctf_base. Fix the compression length: fp->ctf_size never counted the CTF header. Simplify the compress call accordingly.
2019-07-07 00:36:21 +08:00
if ((len = write (fd, buf, resid)) <= 0)
libctf, binutils, include, ld: gettextize and improve error handling This commit follows on from the earlier commit "libctf, ld, binutils: add textual error/warning reporting for libctf" and converts every error in libctf that was reported using ctf_dprintf to use ctf_err_warn instead, gettextizing them in the process, using N_() where necessary to avoid doing gettext calls unless an error message is actually generated, and rephrasing some error messages for ease of translation. This requires a slight change in the ctf_errwarning_next API: this API is public but has not been in a release yet, so can still change freely. The problem is that many errors are emitted at open time (whether opening of a CTF dict, or opening of a CTF archive): the former of these throws away its incompletely-initialized ctf_file_t rather than return it, and the latter has no ctf_file_t at all. So errors and warnings emitted at open time cannot be stored in the ctf_file_t, and have to go elsewhere. We put them in a static local in ctf-subr.c (which is not very thread-safe: a later commit will improve things here): ctf_err_warn with a NULL fp adds to this list, and the public interface ctf_errwarning_next with a NULL fp retrieves from it. We need a slight exception from the usual iterator rules in this case: with a NULL fp, there is nowhere to store the ECTF_NEXT_END "error" which signifies the end of iteration, so we add a new err parameter to ctf_errwarning_next which is used to report such iteration-related errors. (If an fp is provided -- i.e., if not reporting open errors -- this is optional, but even if it's optional it's still an API change. This is actually useful from a usability POV as well, since ctf_errwarning_next is usually called when there's been an error, so overwriting the error code with ECTF_NEXT_END is not very helpful! So, unusually, ctf_errwarning_next now uses the passed fp for its error code *only* if no errp pointer is passed in, and leaves it untouched otherwise.) ld, objdump and readelf are adapted to call ctf_errwarning_next with a NULL fp to report open errors where appropriate. The ctf_err_warn API also has to change, gaining a new error-number parameter which is used to add the error message corresponding to that error number into the debug stream when LIBCTF_DEBUG is enabled: changing this API is easy at this point since we are already touching all existing calls to gettextize them. We need this because the debug stream should contain the errno's message, but the error reported in the error/warning stream should *not*, because the caller will probably report it themselves at failure time regardless, and reporting it in every error message that leads up to it leads to a ridiculous chattering on failure, which is likely to end up as ridiculous chattering on stderr (trimmed a bit): CTF error: `ld/testsuite/ld-ctf/A.c (0): lookup failure for type 3: flags 1: The parent CTF dictionary is unavailable' CTF error: `ld/testsuite/ld-ctf/A.c (0): struct/union member type hashing error during type hashing for type 80000001, kind 6: The parent CTF dictionary is unavailable' CTF error: `deduplicating link variable emission failed for ld/testsuite/ld-ctf/A.c: The parent CTF dictionary is unavailable' ld/.libs/lt-ld-new: warning: CTF linking failed; output will have no CTF section: `The parent CTF dictionary is unavailable' We only need to be told that the parent CTF dictionary is unavailable *once*, not over and over again! errmsgs are still emitted on warning generation, because warnings do not usually lead to a failure propagated up to the caller and reported there. Debug-stream messages are not translated. If translation is turned on, there will be a mixture of English and translated messages in the debug stream, but rather that than burden the translators with debug-only output. binutils/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * objdump.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. (dump_ctf): Call it on open errors. * readelf.c (dump_ctf_archive_member): Move error- reporting... (dump_ctf_errs): ... into this separate function. Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. (dump_section_as_ctf): Call it on open errors. include/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h (ctf_errwarning_next): New err parameter. ld/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ldlang.c (lang_ctf_errs_warnings): Support calls with NULL fp. Adjust for new err parameter to ctf_errwarning_next. Only check for assertion failures when fp is non-NULL. (ldlang_open_ctf): Call it on open errors. * testsuite/ld-ctf/ctf.exp: Always use the C locale to avoid breaking the diags tests. libctf/ChangeLog 2020-08-27 Nick Alcock <nick.alcock@oracle.com> * ctf-subr.c (open_errors): New list. (ctf_err_warn): Calls with NULL fp append to open_errors. Add err parameter, and use it to decorate the debug stream with errmsgs. (ctf_err_warn_to_open): Splice errors from a CTF dict into the open_errors. (ctf_errwarning_next): Calls with NULL fp report from open_errors. New err param to report iteration errors (including end-of-iteration) when fp is NULL. (ctf_assert_fail_internal): Adjust ctf_err_warn call for new err parameter: gettextize. * ctf-impl.h (ctfo_get_vbytes): Add ctf_file_t parameter. (LCTF_VBYTES): Adjust. (ctf_err_warn_to_open): New. (ctf_err_warn): Adjust. (ctf_bundle): Used in only one place: move... * ctf-create.c: ... here. (enumcmp): Use ctf_err_warn, not ctf_dprintf, passing the err number down as needed. Don't emit the errmsg. Gettextize. (membcmp): Likewise. (ctf_add_type_internal): Likewise. (ctf_write_mem): Likewise. (ctf_compress_write): Likewise. Report errors writing the header or body. (ctf_write): Likewise. * ctf-archive.c (ctf_arc_write_fd): Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (ctf_arc_write): Likewise. (ctf_arc_bufopen): Likewise. (ctf_arc_open_internal): Likewise. * ctf-labels.c (ctf_label_iter): Likewise. * ctf-open-bfd.c (ctf_bfdclose): Likewise. (ctf_bfdopen): Likewise. (ctf_bfdopen_ctfsect): Likewise. (ctf_fdopen): Likewise. * ctf-string.c (ctf_str_write_strtab): Likewise. * ctf-types.c (ctf_type_resolve): Likewise. * ctf-open.c (get_vbytes_common): Likewise. Pass down the ctf dict. (get_vbytes_v1): Pass down the ctf dict. (get_vbytes_v2): Likewise. (flip_ctf): Likewise. (flip_types): Likewise. Use ctf_err_warn, not ctf_dprintf, and gettextize, as above. (upgrade_types_v1): Adjust calls. (init_types): Use ctf_err_warn, not ctf_dprintf, as above. (ctf_bufopen_internal): Likewise. Adjust calls. Transplant errors emitted into individual dicts into the open errors if this turns out to be a failed open in the end. * ctf-dump.c (ctf_dump_format_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dump_funcs): Likewise. Collapse err label into its only case. (ctf_dump_type): Likewise. * ctf-link.c (ctf_create_per_cu): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_link_one_type): Likewise. (ctf_link_lazy_open): Likewise. (ctf_link_one_input_archive): Likewise. (ctf_link_deduplicating_count_inputs): Likewise. (ctf_link_deduplicating_open_inputs): Likewise. (ctf_link_deduplicating_close_inputs): Likewise. (ctf_link_deduplicating): Likewise. (ctf_link): Likewise. (ctf_link_deduplicating_per_cu): Likewise. Add some missed ctf_set_errnos to obscure error cases. * ctf-dedup.c (ctf_dedup_rhash_type): Adjust ctf_err_warn for new err argument. Gettextize. Don't emit the errmsg. (ctf_dedup_populate_mappings): Likewise. (ctf_dedup_detect_name_ambiguity): Likewise. (ctf_dedup_init): Likewise. (ctf_dedup_multiple_input_dicts): Likewise. (ctf_dedup_conflictify_unshared): Likewise. (ctf_dedup): Likewise. (ctf_dedup_rwalk_one_output_mapping): Likewise. (ctf_dedup_id_to_target): Likewise. (ctf_dedup_emit_type): Likewise. (ctf_dedup_emit_struct_members): Likewise. (ctf_dedup_populate_type_mapping): Likewise. (ctf_dedup_populate_type_mappings): Likewise. (ctf_dedup_emit): Likewise. (ctf_dedup_hash_type): Likewise. Fix a bit of messed-up error status setting. (ctf_dedup_rwalk_one_output_mapping): Likewise. Don't hide unknown-type-kind messages (which signify file corruption).
2020-07-27 23:45:15 +08:00
{
ctf_err_warn (fp, 0, errno, _("ctf_write: error writing"));
return (ctf_set_errno (fp, errno));
}
libctf: creation functions The CTF creation process looks roughly like (error handling elided): int err; ctf_file_t *foo = ctf_create (&err); ctf_id_t type = ctf_add_THING (foo, ...); ctf_update (foo); ctf_*write (...); Some ctf_add_THING functions accept other type IDs as arguments, depending on the type: cv-quals, pointers, and structure and union members all take other types as arguments. So do 'slices', which let you take an existing integral type and recast it as a type with a different bitness or offset within a byte, for bitfields. One class of THING is not a type: "variables", which are mappings of names (in the internal string table) to types. These are mostly useful when encoding variables that do not appear in a symbol table but which some external user has some other way to figure out the address of at runtime (dynamic symbol lookup or querying a VM interpreter or something). You can snapshot the creation process at any point: rolling back to a snapshot deletes all types and variables added since that point. You can make arbitrary type queries on the CTF container during the creation process, but you must call ctf_update() first, which translates the growing dynamic container into a static one (this uses the CTF opening machinery, added in a later commit), which is quite expensive. This function must also be called after adding types and before writing the container out. Because addition of types involves looking up existing types, we add a little of the type lookup machinery here, as well: only enough to look up types in dynamic containers under construction. libctf/ * ctf-create.c: New file. * ctf-lookup.c: New file. include/ * ctf-api.h (zlib.h): New include. (ctf_sect_t): New. (ctf_sect_names_t): Likewise. (ctf_encoding_t): Likewise. (ctf_membinfo_t): Likewise. (ctf_arinfo_t): Likewise. (ctf_funcinfo_t): Likewise. (ctf_lblinfo_t): Likewise. (ctf_snapshot_id_t): Likewise. (CTF_FUNC_VARARG): Likewise. (ctf_simple_open): Likewise. (ctf_bufopen): Likewise. (ctf_create): Likewise. (ctf_add_array): Likewise. (ctf_add_const): Likewise. (ctf_add_enum_encoded): Likewise. (ctf_add_enum): Likewise. (ctf_add_float): Likewise. (ctf_add_forward): Likewise. (ctf_add_function): Likewise. (ctf_add_integer): Likewise. (ctf_add_slice): Likewise. (ctf_add_pointer): Likewise. (ctf_add_type): Likewise. (ctf_add_typedef): Likewise. (ctf_add_restrict): Likewise. (ctf_add_struct): Likewise. (ctf_add_union): Likewise. (ctf_add_struct_sized): Likewise. (ctf_add_union_sized): Likewise. (ctf_add_volatile): Likewise. (ctf_add_enumerator): Likewise. (ctf_add_member): Likewise. (ctf_add_member_offset): Likewise. (ctf_add_member_encoded): Likewise. (ctf_add_variable): Likewise. (ctf_set_array): Likewise. (ctf_update): Likewise. (ctf_snapshot): Likewise. (ctf_rollback): Likewise. (ctf_discard): Likewise. (ctf_write): Likewise. (ctf_gzwrite): Likewise. (ctf_compress_write): Likewise.
2019-04-24 05:45:46 +08:00
resid -= len;
buf += len;
}
return 0;
}