/* Opening CTF files. Copyright (C) 2019-2026 Free Software Foundation, Inc. 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 <stddef.h>#include <string.h>#include <sys/types.h>#include <elf.h>#include "swap.h"#include <bfd.h>#include <zlib.h> static const ctf_dmodel_t _libctf_models[] = { {"ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4}, {"LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8}, {NULL, 0, 0, 0, 0, 0, 0}}; const char _CTF_SECTION[] = ".ctf";const char _CTF_NULLSTR[] = ""; /* Version-sensitive accessors. */ static uint32_tget_kind_v1 (uint32_t info){ return (CTF_V1_INFO_KIND (info));} static uint32_tget_root_v1 (uint32_t info){ return (CTF_V1_INFO_ISROOT (info));} static uint32_tget_vlen_v1 (uint32_t info){ return (CTF_V1_INFO_VLEN (info));} static uint32_tget_kind_v2 (uint32_t info){ return (CTF_V2_INFO_KIND (info));} static uint32_tget_root_v2 (uint32_t info){ return (CTF_V2_INFO_ISROOT (info));} static uint32_tget_vlen_v2 (uint32_t info){ return (CTF_V2_INFO_VLEN (info));} static inline ssize_tget_ctt_size_common (const ctf_dict_t *fp _libctf_unused_, const ctf_type_t *tp _libctf_unused_, ssize_t *sizep, ssize_t *incrementp, size_t lsize, size_t csize, size_t ctf_type_size, size_t ctf_stype_size, size_t ctf_lsize_sent){ ssize_t size, increment; if (csize == ctf_lsize_sent) { size = lsize; increment = ctf_type_size; } else { size = csize; increment = ctf_stype_size; } if (sizep) *sizep = size; if (incrementp) *incrementp = increment; return size;} static ssize_tget_ctt_size_v1 (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp){ ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp; return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (t1p), t1p->ctt_size, sizeof (ctf_type_v1_t), sizeof (ctf_stype_v1_t), CTF_LSIZE_SENT_V1));} /* Return the size that a v1 will be once it is converted to v2. */ static ssize_tget_ctt_size_v2_unconverted (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp){ ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp; return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (t1p), t1p->ctt_size, sizeof (ctf_type_t), sizeof (ctf_stype_t), CTF_LSIZE_SENT));} static ssize_tget_ctt_size_v2 (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp){ return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (tp), tp->ctt_size, sizeof (ctf_type_t), sizeof (ctf_stype_t), CTF_LSIZE_SENT));} static ssize_tget_vbytes_common (ctf_dict_t *fp, unsigned short kind, ssize_t size _libctf_unused_, size_t vlen){ switch (kind) { case CTF_K_INTEGER: case CTF_K_FLOAT: return (sizeof (uint32_t)); case CTF_K_SLICE: return (sizeof (ctf_slice_t)); case CTF_K_ENUM: return (sizeof (ctf_enum_t) * vlen); case CTF_K_FORWARD: case CTF_K_UNKNOWN: case CTF_K_POINTER: case CTF_K_TYPEDEF: case CTF_K_VOLATILE: case CTF_K_CONST: case CTF_K_RESTRICT: return 0; default: ctf_set_errno (fp, ECTF_CORRUPT); ctf_err_warn (fp, 0, 0, _("detected invalid CTF kind: %x"), kind); return -1; }} static ssize_tget_vbytes_v1 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen){ switch (kind) { case CTF_K_ARRAY: return (sizeof (ctf_array_v1_t)); case CTF_K_FUNCTION: return (sizeof (unsigned short) * (vlen + (vlen & 1))); case CTF_K_STRUCT: case CTF_K_UNION: if (size < CTF_LSTRUCT_THRESH_V1) return (sizeof (ctf_member_v1_t) * vlen); else return (sizeof (ctf_lmember_v1_t) * vlen); } return (get_vbytes_common (fp, kind, size, vlen));} static ssize_tget_vbytes_v2 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen){ switch (kind) { case CTF_K_ARRAY: return (sizeof (ctf_array_t)); case CTF_K_FUNCTION: return (sizeof (uint32_t) * (vlen + (vlen & 1))); case CTF_K_STRUCT: case CTF_K_UNION: if (size < CTF_LSTRUCT_THRESH) return (sizeof (ctf_member_t) * vlen); else return (sizeof (ctf_lmember_t) * vlen); } return (get_vbytes_common (fp, kind, size, vlen));} static const ctf_dictops_t ctf_dictops[] = { {NULL, NULL, NULL, NULL, NULL}, /* CTF_VERSION_1 */ {get_kind_v1, get_root_v1, get_vlen_v1, get_ctt_size_v1, get_vbytes_v1}, /* CTF_VERSION_1_UPGRADED_3 */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2}, /* CTF_VERSION_2 */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2}, /* CTF_VERSION_3, identical to 2: only new type kinds */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},}; /* Initialize the symtab translation table as appropriate for its indexing state. For unindexed symtypetabs, fill each entry with the offset of the CTF type or function data corresponding to each STT_FUNC or STT_OBJECT entry in the symbol table. For indexed symtypetabs, do nothing: the needed initialization for indexed lookups may be quite expensive, so it is done only as needed, when lookups happen. (In particular, the majority of indexed symtypetabs come from the compiler, and all the linker does is iteration over all entries, which doesn't need this initialization.) The SP symbol table section may be NULL if there is no symtab. If init_symtab works on one call, it cannot fail on future calls to the same fp: ctf_symsect_endianness relies on this. */ static intinit_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp){ const unsigned char *symp; int skip_func_info = 0; int i; uint32_t *xp = fp->ctf_sxlate; uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms); uint32_t objtoff = hp->cth_objtoff; uint32_t funcoff = hp->cth_funcoff; /* If the CTF_F_NEWFUNCINFO flag is not set, pretend the func info section is empty: this compiler is too old to emit a function info section we understand. */ if (!(hp->cth_flags & CTF_F_NEWFUNCINFO)) skip_func_info = 1; if (hp->cth_objtidxoff < hp->cth_funcidxoff) fp->ctf_objtidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_objtidxoff); if (hp->cth_funcidxoff < hp->cth_varoff && !skip_func_info) fp->ctf_funcidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidxoff); /* Don't bother doing the rest if everything is indexed, or if we don't have a symbol table: we will never use it. */ if ((fp->ctf_objtidx_names && fp->ctf_funcidx_names) || !sp || !sp->cts_data) return 0; /* The CTF data object and function type sections are ordered to match the relative order of the respective symbol types in the symtab, unless there is an index section, in which case the order is arbitrary and the index gives the mapping. If no type information is available for a symbol table entry, a pad is inserted in the CTF section. As a further optimization, anonymous or undefined symbols are omitted from the CTF data. If an index is available for function symbols but not object symbols, or vice versa, we populate the xslate table for the unindexed symbols only. */ for (i = 0, symp = sp->cts_data; xp < xend; xp++, symp += sp->cts_entsize, i++) { ctf_link_sym_t sym; switch (sp->cts_entsize) { case sizeof (Elf64_Sym): { const Elf64_Sym *symp64 = (Elf64_Sym *) (uintptr_t) symp; ctf_elf64_to_link_sym (fp, &sym, symp64, i); } break; case sizeof (Elf32_Sym): { const Elf32_Sym *symp32 = (Elf32_Sym *) (uintptr_t) symp; ctf_elf32_to_link_sym (fp, &sym, symp32, i); } break; default: return ECTF_SYMTAB; } /* This call may be led astray if our idea of the symtab's endianness is wrong, but when this is fixed by a call to ctf_symsect_endianness, init_symtab will be called again with the right endianness in force. */ if (ctf_symtab_skippable (&sym)) { *xp = -1u; continue; } switch (sym.st_type) { case STT_OBJECT: if (fp->ctf_objtidx_names || objtoff >= hp->cth_funcoff) { *xp = -1u; break; } *xp = objtoff; objtoff += sizeof (uint32_t); break; case STT_FUNC: if (fp->ctf_funcidx_names || funcoff >= hp->cth_objtidxoff || skip_func_info) { *xp = -1u; break; } *xp = funcoff; funcoff += sizeof (uint32_t); break; default: *xp = -1u; break; } } ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms); return 0;} /* Reset the CTF base pointer and derive the buf pointer from it, initializing everything in the ctf_dict that depends on the base or buf pointers. The original gap between the buf and base pointers, if any -- the original, unconverted CTF header -- is kept, but its contents are not specified and are never used. */ static voidctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base){ fp->ctf_buf = base + (fp->ctf_buf - fp->ctf_base); fp->ctf_base = base; fp->ctf_vars = (ctf_varent_t *) ((const char *) fp->ctf_buf + hp->cth_varoff); fp->ctf_nvars = (hp->cth_typeoff - hp->cth_varoff) / sizeof (ctf_varent_t); fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf + hp->cth_stroff; fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen; /* If we have a parent dict name and label, store the relocated string pointers in the CTF dict for easy access later. */ /* Note: before conversion, these will be set to values that will be immediately invalidated by the conversion process, but the conversion process will call ctf_set_base() again to fix things up. */ if (hp->cth_parlabel != 0) fp->ctf_parlabel = ctf_strptr (fp, hp->cth_parlabel); if (hp->cth_parname != 0) fp->ctf_parname = ctf_strptr (fp, hp->cth_parname); if (hp->cth_cuname != 0) fp->ctf_cuname = ctf_strptr (fp, hp->cth_cuname); if (fp->ctf_cuname) ctf_dprintf ("ctf_set_base: CU name %s\n", fp->ctf_cuname); if (fp->ctf_parname) ctf_dprintf ("ctf_set_base: parent name %s (label %s)\n", fp->ctf_parname, fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");} /* Set the version of the CTF file. */ /* When this is reset, LCTF_* changes behaviour, but there is no guarantee that the variable data list associated with each type has been upgraded: the caller must ensure this has been done in advance. */ static voidctf_set_version (ctf_dict_t *fp, ctf_header_t *cth, int ctf_version){ fp->ctf_version = ctf_version; cth->cth_version = ctf_version; fp->ctf_dictops = &ctf_dictops[ctf_version];} /* Upgrade the header to CTF_VERSION_3. The upgrade is done in-place. */static voidupgrade_header (ctf_header_t *hp){ ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp; hp->cth_strlen = oldhp->cth_strlen; hp->cth_stroff = oldhp->cth_stroff; hp->cth_typeoff = oldhp->cth_typeoff; hp->cth_varoff = oldhp->cth_varoff; hp->cth_funcidxoff = hp->cth_varoff; /* No index sections. */ hp->cth_objtidxoff = hp->cth_funcidxoff; hp->cth_funcoff = oldhp->cth_funcoff; hp->cth_objtoff = oldhp->cth_objtoff; hp->cth_lbloff = oldhp->cth_lbloff; hp->cth_cuname = 0; /* No CU name. */} /* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3) from CTF_VERSION_1. The upgrade is not done in-place: the ctf_base is moved. ctf_strptr() must not be called before reallocation is complete. Sections not checked here due to nonexistence or nonpopulated state in older formats: objtidx, funcidx. Type kinds not checked here due to nonexistence in older formats: CTF_K_SLICE. */static intupgrade_types_v1 (ctf_dict_t *fp, ctf_header_t *cth){ const ctf_type_v1_t *tbuf; const ctf_type_v1_t *tend; unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_dynbase; ctf_type_t *t2buf; ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes; const ctf_type_v1_t *tp; ctf_type_t *t2p; tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff); tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff); /* Much like init_static_types(), this is a two-pass process. First, figure out the new type-section size needed. (It is possible, in theory, for it to be less than the old size, but this is very unlikely. It cannot be so small that cth_typeoff ends up of negative size. We validate this with an assertion below.) We must cater not only for changes in vlen and types sizes but also for changes in 'increment', which happen because v2 places some types into ctf_stype_t where v1 would be forced to use the larger non-stype. */ for (tp = tbuf; tp < tend; tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes)) { unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info); unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info); size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment); vbytes = get_vbytes_v1 (fp, kind, size, vlen); get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL, &v2increment); v2bytes = get_vbytes_v2 (fp, kind, size, vlen); if ((vbytes < 0) || (size < 0)) return ECTF_CORRUPT; increase += v2increment - increment; /* May be negative. */ increase += v2bytes - vbytes; } /* Allocate enough room for the new buffer, then copy everything but the type section into place, and reset the base accordingly. Leave the version number unchanged, so that LCTF_INFO_* still works on the as-yet-untranslated type info. */ if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL) return ECTF_ZALLOC; /* Start at ctf_buf, not ctf_base, to squeeze out the original header: we never use it and it is unconverted. */ memcpy (ctf_base, fp->ctf_buf, cth->cth_typeoff); memcpy (ctf_base + cth->cth_stroff + increase, fp->ctf_buf + cth->cth_stroff, cth->cth_strlen); memset (ctf_base + cth->cth_typeoff, 0, cth->cth_stroff - cth->cth_typeoff + increase); cth->cth_stroff += increase; fp->ctf_size += increase; assert (cth->cth_stroff >= cth->cth_typeoff); fp->ctf_base = ctf_base; fp->ctf_buf = ctf_base; fp->ctf_dynbase = ctf_base; ctf_set_base (fp, cth, ctf_base); t2buf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff); /* Iterate through all the types again, upgrading them.Lines 1–500 of 2171. Load more
/* Opening CTF files. Copyright (C) 2019-2026 Free Software Foundation, Inc. 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 <stddef.h> #include <string.h> #include <sys/types.h> #include <elf.h> #include "swap.h" #include <bfd.h> #include <zlib.h> static const ctf_dmodel_t _libctf_models[] = { {"ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4}, {"LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8}, {NULL, 0, 0, 0, 0, 0, 0} }; const char _CTF_SECTION[] = ".ctf"; const char _CTF_NULLSTR[] = ""; /* Version-sensitive accessors. */ static uint32_t get_kind_v1 (uint32_t info) { return (CTF_V1_INFO_KIND (info)); } static uint32_t get_root_v1 (uint32_t info) { return (CTF_V1_INFO_ISROOT (info)); } static uint32_t get_vlen_v1 (uint32_t info) { return (CTF_V1_INFO_VLEN (info)); } static uint32_t get_kind_v2 (uint32_t info) { return (CTF_V2_INFO_KIND (info)); } static uint32_t get_root_v2 (uint32_t info) { return (CTF_V2_INFO_ISROOT (info)); } static uint32_t get_vlen_v2 (uint32_t info) { return (CTF_V2_INFO_VLEN (info)); } static inline ssize_t get_ctt_size_common (const ctf_dict_t *fp _libctf_unused_, const ctf_type_t *tp _libctf_unused_, ssize_t *sizep, ssize_t *incrementp, size_t lsize, size_t csize, size_t ctf_type_size, size_t ctf_stype_size, size_t ctf_lsize_sent) { ssize_t size, increment; if (csize == ctf_lsize_sent) { size = lsize; increment = ctf_type_size; } else { size = csize; increment = ctf_stype_size; } if (sizep) *sizep = size; if (incrementp) *incrementp = increment; return size; } static ssize_t get_ctt_size_v1 (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp) { ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp; return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (t1p), t1p->ctt_size, sizeof (ctf_type_v1_t), sizeof (ctf_stype_v1_t), CTF_LSIZE_SENT_V1)); } /* Return the size that a v1 will be once it is converted to v2. */ static ssize_t get_ctt_size_v2_unconverted (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp) { ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp; return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (t1p), t1p->ctt_size, sizeof (ctf_type_t), sizeof (ctf_stype_t), CTF_LSIZE_SENT)); } static ssize_t get_ctt_size_v2 (const ctf_dict_t *fp, const ctf_type_t *tp, ssize_t *sizep, ssize_t *incrementp) { return (get_ctt_size_common (fp, tp, sizep, incrementp, CTF_TYPE_LSIZE (tp), tp->ctt_size, sizeof (ctf_type_t), sizeof (ctf_stype_t), CTF_LSIZE_SENT)); } static ssize_t get_vbytes_common (ctf_dict_t *fp, unsigned short kind, ssize_t size _libctf_unused_, size_t vlen) { switch (kind) { case CTF_K_INTEGER: case CTF_K_FLOAT: return (sizeof (uint32_t)); case CTF_K_SLICE: return (sizeof (ctf_slice_t)); case CTF_K_ENUM: return (sizeof (ctf_enum_t) * vlen); case CTF_K_FORWARD: case CTF_K_UNKNOWN: case CTF_K_POINTER: case CTF_K_TYPEDEF: case CTF_K_VOLATILE: case CTF_K_CONST: case CTF_K_RESTRICT: return 0; default: ctf_set_errno (fp, ECTF_CORRUPT); ctf_err_warn (fp, 0, 0, _("detected invalid CTF kind: %x"), kind); return -1; } } static ssize_t get_vbytes_v1 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen) { switch (kind) { case CTF_K_ARRAY: return (sizeof (ctf_array_v1_t)); case CTF_K_FUNCTION: return (sizeof (unsigned short) * (vlen + (vlen & 1))); case CTF_K_STRUCT: case CTF_K_UNION: if (size < CTF_LSTRUCT_THRESH_V1) return (sizeof (ctf_member_v1_t) * vlen); else return (sizeof (ctf_lmember_v1_t) * vlen); } return (get_vbytes_common (fp, kind, size, vlen)); } static ssize_t get_vbytes_v2 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen) { switch (kind) { case CTF_K_ARRAY: return (sizeof (ctf_array_t)); case CTF_K_FUNCTION: return (sizeof (uint32_t) * (vlen + (vlen & 1))); case CTF_K_STRUCT: case CTF_K_UNION: if (size < CTF_LSTRUCT_THRESH) return (sizeof (ctf_member_t) * vlen); else return (sizeof (ctf_lmember_t) * vlen); } return (get_vbytes_common (fp, kind, size, vlen)); } static const ctf_dictops_t ctf_dictops[] = { {NULL, NULL, NULL, NULL, NULL}, /* CTF_VERSION_1 */ {get_kind_v1, get_root_v1, get_vlen_v1, get_ctt_size_v1, get_vbytes_v1}, /* CTF_VERSION_1_UPGRADED_3 */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2}, /* CTF_VERSION_2 */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2}, /* CTF_VERSION_3, identical to 2: only new type kinds */ {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2}, }; /* Initialize the symtab translation table as appropriate for its indexing state. For unindexed symtypetabs, fill each entry with the offset of the CTF type or function data corresponding to each STT_FUNC or STT_OBJECT entry in the symbol table. For indexed symtypetabs, do nothing: the needed initialization for indexed lookups may be quite expensive, so it is done only as needed, when lookups happen. (In particular, the majority of indexed symtypetabs come from the compiler, and all the linker does is iteration over all entries, which doesn't need this initialization.) The SP symbol table section may be NULL if there is no symtab. If init_symtab works on one call, it cannot fail on future calls to the same fp: ctf_symsect_endianness relies on this. */ static int init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp) { const unsigned char *symp; int skip_func_info = 0; int i; uint32_t *xp = fp->ctf_sxlate; uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms); uint32_t objtoff = hp->cth_objtoff; uint32_t funcoff = hp->cth_funcoff; /* If the CTF_F_NEWFUNCINFO flag is not set, pretend the func info section is empty: this compiler is too old to emit a function info section we understand. */ if (!(hp->cth_flags & CTF_F_NEWFUNCINFO)) skip_func_info = 1; if (hp->cth_objtidxoff < hp->cth_funcidxoff) fp->ctf_objtidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_objtidxoff); if (hp->cth_funcidxoff < hp->cth_varoff && !skip_func_info) fp->ctf_funcidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidxoff); /* Don't bother doing the rest if everything is indexed, or if we don't have a symbol table: we will never use it. */ if ((fp->ctf_objtidx_names && fp->ctf_funcidx_names) || !sp || !sp->cts_data) return 0; /* The CTF data object and function type sections are ordered to match the relative order of the respective symbol types in the symtab, unless there is an index section, in which case the order is arbitrary and the index gives the mapping. If no type information is available for a symbol table entry, a pad is inserted in the CTF section. As a further optimization, anonymous or undefined symbols are omitted from the CTF data. If an index is available for function symbols but not object symbols, or vice versa, we populate the xslate table for the unindexed symbols only. */ for (i = 0, symp = sp->cts_data; xp < xend; xp++, symp += sp->cts_entsize, i++) { ctf_link_sym_t sym; switch (sp->cts_entsize) { case sizeof (Elf64_Sym): { const Elf64_Sym *symp64 = (Elf64_Sym *) (uintptr_t) symp; ctf_elf64_to_link_sym (fp, &sym, symp64, i); } break; case sizeof (Elf32_Sym): { const Elf32_Sym *symp32 = (Elf32_Sym *) (uintptr_t) symp; ctf_elf32_to_link_sym (fp, &sym, symp32, i); } break; default: return ECTF_SYMTAB; } /* This call may be led astray if our idea of the symtab's endianness is wrong, but when this is fixed by a call to ctf_symsect_endianness, init_symtab will be called again with the right endianness in force. */ if (ctf_symtab_skippable (&sym)) { *xp = -1u; continue; } switch (sym.st_type) { case STT_OBJECT: if (fp->ctf_objtidx_names || objtoff >= hp->cth_funcoff) { *xp = -1u; break; } *xp = objtoff; objtoff += sizeof (uint32_t); break; case STT_FUNC: if (fp->ctf_funcidx_names || funcoff >= hp->cth_objtidxoff || skip_func_info) { *xp = -1u; break; } *xp = funcoff; funcoff += sizeof (uint32_t); break; default: *xp = -1u; break; } } ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms); return 0; } /* Reset the CTF base pointer and derive the buf pointer from it, initializing everything in the ctf_dict that depends on the base or buf pointers. The original gap between the buf and base pointers, if any -- the original, unconverted CTF header -- is kept, but its contents are not specified and are never used. */ static void ctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base) { fp->ctf_buf = base + (fp->ctf_buf - fp->ctf_base); fp->ctf_base = base; fp->ctf_vars = (ctf_varent_t *) ((const char *) fp->ctf_buf + hp->cth_varoff); fp->ctf_nvars = (hp->cth_typeoff - hp->cth_varoff) / sizeof (ctf_varent_t); fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf + hp->cth_stroff; fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen; /* If we have a parent dict name and label, store the relocated string pointers in the CTF dict for easy access later. */ /* Note: before conversion, these will be set to values that will be immediately invalidated by the conversion process, but the conversion process will call ctf_set_base() again to fix things up. */ if (hp->cth_parlabel != 0) fp->ctf_parlabel = ctf_strptr (fp, hp->cth_parlabel); if (hp->cth_parname != 0) fp->ctf_parname = ctf_strptr (fp, hp->cth_parname); if (hp->cth_cuname != 0) fp->ctf_cuname = ctf_strptr (fp, hp->cth_cuname); if (fp->ctf_cuname) ctf_dprintf ("ctf_set_base: CU name %s\n", fp->ctf_cuname); if (fp->ctf_parname) ctf_dprintf ("ctf_set_base: parent name %s (label %s)\n", fp->ctf_parname, fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>"); } /* Set the version of the CTF file. */ /* When this is reset, LCTF_* changes behaviour, but there is no guarantee that the variable data list associated with each type has been upgraded: the caller must ensure this has been done in advance. */ static void ctf_set_version (ctf_dict_t *fp, ctf_header_t *cth, int ctf_version) { fp->ctf_version = ctf_version; cth->cth_version = ctf_version; fp->ctf_dictops = &ctf_dictops[ctf_version]; } /* Upgrade the header to CTF_VERSION_3. The upgrade is done in-place. */ static void upgrade_header (ctf_header_t *hp) { ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp; hp->cth_strlen = oldhp->cth_strlen; hp->cth_stroff = oldhp->cth_stroff; hp->cth_typeoff = oldhp->cth_typeoff; hp->cth_varoff = oldhp->cth_varoff; hp->cth_funcidxoff = hp->cth_varoff; /* No index sections. */ hp->cth_objtidxoff = hp->cth_funcidxoff; hp->cth_funcoff = oldhp->cth_funcoff; hp->cth_objtoff = oldhp->cth_objtoff; hp->cth_lbloff = oldhp->cth_lbloff; hp->cth_cuname = 0; /* No CU name. */ } /* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3) from CTF_VERSION_1. The upgrade is not done in-place: the ctf_base is moved. ctf_strptr() must not be called before reallocation is complete. Sections not checked here due to nonexistence or nonpopulated state in older formats: objtidx, funcidx. Type kinds not checked here due to nonexistence in older formats: CTF_K_SLICE. */ static int upgrade_types_v1 (ctf_dict_t *fp, ctf_header_t *cth) { const ctf_type_v1_t *tbuf; const ctf_type_v1_t *tend; unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_dynbase; ctf_type_t *t2buf; ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes; const ctf_type_v1_t *tp; ctf_type_t *t2p; tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff); tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff); /* Much like init_static_types(), this is a two-pass process. First, figure out the new type-section size needed. (It is possible, in theory, for it to be less than the old size, but this is very unlikely. It cannot be so small that cth_typeoff ends up of negative size. We validate this with an assertion below.) We must cater not only for changes in vlen and types sizes but also for changes in 'increment', which happen because v2 places some types into ctf_stype_t where v1 would be forced to use the larger non-stype. */ for (tp = tbuf; tp < tend; tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes)) { unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info); unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info); size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment); vbytes = get_vbytes_v1 (fp, kind, size, vlen); get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL, &v2increment); v2bytes = get_vbytes_v2 (fp, kind, size, vlen); if ((vbytes < 0) || (size < 0)) return ECTF_CORRUPT; increase += v2increment - increment; /* May be negative. */ increase += v2bytes - vbytes; } /* Allocate enough room for the new buffer, then copy everything but the type section into place, and reset the base accordingly. Leave the version number unchanged, so that LCTF_INFO_* still works on the as-yet-untranslated type info. */ if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL) return ECTF_ZALLOC; /* Start at ctf_buf, not ctf_base, to squeeze out the original header: we never use it and it is unconverted. */ memcpy (ctf_base, fp->ctf_buf, cth->cth_typeoff); memcpy (ctf_base + cth->cth_stroff + increase, fp->ctf_buf + cth->cth_stroff, cth->cth_strlen); memset (ctf_base + cth->cth_typeoff, 0, cth->cth_stroff - cth->cth_typeoff + increase); cth->cth_stroff += increase; fp->ctf_size += increase; assert (cth->cth_stroff >= cth->cth_typeoff); fp->ctf_base = ctf_base; fp->ctf_buf = ctf_base; fp->ctf_dynbase = ctf_base; ctf_set_base (fp, cth, ctf_base); t2buf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff); /* Iterate through all the types again, upgrading them.