1867d70fcSchristos /* Opening CTF files.
2*c42dbd0eSchristos Copyright (C) 2019-2022 Free Software Foundation, Inc.
3867d70fcSchristos
4867d70fcSchristos This file is part of libctf.
5867d70fcSchristos
6867d70fcSchristos libctf is free software; you can redistribute it and/or modify it under
7867d70fcSchristos the terms of the GNU General Public License as published by the Free
8867d70fcSchristos Software Foundation; either version 3, or (at your option) any later
9867d70fcSchristos version.
10867d70fcSchristos
11867d70fcSchristos This program is distributed in the hope that it will be useful, but
12867d70fcSchristos WITHOUT ANY WARRANTY; without even the implied warranty of
13867d70fcSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14867d70fcSchristos See the GNU General Public License for more details.
15867d70fcSchristos
16867d70fcSchristos You should have received a copy of the GNU General Public License
17867d70fcSchristos along with this program; see the file COPYING. If not see
18867d70fcSchristos <http://www.gnu.org/licenses/>. */
19867d70fcSchristos
20867d70fcSchristos #include <ctf-impl.h>
21867d70fcSchristos #include <stddef.h>
22867d70fcSchristos #include <string.h>
23867d70fcSchristos #include <sys/types.h>
24867d70fcSchristos #include <elf.h>
25867d70fcSchristos #include "swap.h"
26867d70fcSchristos #include <bfd.h>
27867d70fcSchristos #include <zlib.h>
28867d70fcSchristos
29867d70fcSchristos static const ctf_dmodel_t _libctf_models[] = {
30867d70fcSchristos {"ILP32", CTF_MODEL_ILP32, 4, 1, 2, 4, 4},
31867d70fcSchristos {"LP64", CTF_MODEL_LP64, 8, 1, 2, 4, 8},
32867d70fcSchristos {NULL, 0, 0, 0, 0, 0, 0}
33867d70fcSchristos };
34867d70fcSchristos
35867d70fcSchristos const char _CTF_SECTION[] = ".ctf";
36867d70fcSchristos const char _CTF_NULLSTR[] = "";
37867d70fcSchristos
38867d70fcSchristos /* Version-sensitive accessors. */
39867d70fcSchristos
40867d70fcSchristos static uint32_t
get_kind_v1(uint32_t info)41867d70fcSchristos get_kind_v1 (uint32_t info)
42867d70fcSchristos {
43867d70fcSchristos return (CTF_V1_INFO_KIND (info));
44867d70fcSchristos }
45867d70fcSchristos
46867d70fcSchristos static uint32_t
get_root_v1(uint32_t info)47867d70fcSchristos get_root_v1 (uint32_t info)
48867d70fcSchristos {
49867d70fcSchristos return (CTF_V1_INFO_ISROOT (info));
50867d70fcSchristos }
51867d70fcSchristos
52867d70fcSchristos static uint32_t
get_vlen_v1(uint32_t info)53867d70fcSchristos get_vlen_v1 (uint32_t info)
54867d70fcSchristos {
55867d70fcSchristos return (CTF_V1_INFO_VLEN (info));
56867d70fcSchristos }
57867d70fcSchristos
58867d70fcSchristos static uint32_t
get_kind_v2(uint32_t info)59867d70fcSchristos get_kind_v2 (uint32_t info)
60867d70fcSchristos {
61867d70fcSchristos return (CTF_V2_INFO_KIND (info));
62867d70fcSchristos }
63867d70fcSchristos
64867d70fcSchristos static uint32_t
get_root_v2(uint32_t info)65867d70fcSchristos get_root_v2 (uint32_t info)
66867d70fcSchristos {
67867d70fcSchristos return (CTF_V2_INFO_ISROOT (info));
68867d70fcSchristos }
69867d70fcSchristos
70867d70fcSchristos static uint32_t
get_vlen_v2(uint32_t info)71867d70fcSchristos get_vlen_v2 (uint32_t info)
72867d70fcSchristos {
73867d70fcSchristos return (CTF_V2_INFO_VLEN (info));
74867d70fcSchristos }
75867d70fcSchristos
76867d70fcSchristos 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)77*c42dbd0eSchristos get_ctt_size_common (const ctf_dict_t *fp _libctf_unused_,
78867d70fcSchristos const ctf_type_t *tp _libctf_unused_,
79867d70fcSchristos ssize_t *sizep, ssize_t *incrementp, size_t lsize,
80867d70fcSchristos size_t csize, size_t ctf_type_size,
81867d70fcSchristos size_t ctf_stype_size, size_t ctf_lsize_sent)
82867d70fcSchristos {
83867d70fcSchristos ssize_t size, increment;
84867d70fcSchristos
85867d70fcSchristos if (csize == ctf_lsize_sent)
86867d70fcSchristos {
87867d70fcSchristos size = lsize;
88867d70fcSchristos increment = ctf_type_size;
89867d70fcSchristos }
90867d70fcSchristos else
91867d70fcSchristos {
92867d70fcSchristos size = csize;
93867d70fcSchristos increment = ctf_stype_size;
94867d70fcSchristos }
95867d70fcSchristos
96867d70fcSchristos if (sizep)
97867d70fcSchristos *sizep = size;
98867d70fcSchristos if (incrementp)
99867d70fcSchristos *incrementp = increment;
100867d70fcSchristos
101867d70fcSchristos return size;
102867d70fcSchristos }
103867d70fcSchristos
104867d70fcSchristos static ssize_t
get_ctt_size_v1(const ctf_dict_t * fp,const ctf_type_t * tp,ssize_t * sizep,ssize_t * incrementp)105*c42dbd0eSchristos get_ctt_size_v1 (const ctf_dict_t *fp, const ctf_type_t *tp,
106867d70fcSchristos ssize_t *sizep, ssize_t *incrementp)
107867d70fcSchristos {
108867d70fcSchristos ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp;
109867d70fcSchristos
110867d70fcSchristos return (get_ctt_size_common (fp, tp, sizep, incrementp,
111867d70fcSchristos CTF_TYPE_LSIZE (t1p), t1p->ctt_size,
112867d70fcSchristos sizeof (ctf_type_v1_t), sizeof (ctf_stype_v1_t),
113867d70fcSchristos CTF_LSIZE_SENT_V1));
114867d70fcSchristos }
115867d70fcSchristos
116867d70fcSchristos /* Return the size that a v1 will be once it is converted to v2. */
117867d70fcSchristos
118867d70fcSchristos static ssize_t
get_ctt_size_v2_unconverted(const ctf_dict_t * fp,const ctf_type_t * tp,ssize_t * sizep,ssize_t * incrementp)119*c42dbd0eSchristos get_ctt_size_v2_unconverted (const ctf_dict_t *fp, const ctf_type_t *tp,
120867d70fcSchristos ssize_t *sizep, ssize_t *incrementp)
121867d70fcSchristos {
122867d70fcSchristos ctf_type_v1_t *t1p = (ctf_type_v1_t *) tp;
123867d70fcSchristos
124867d70fcSchristos return (get_ctt_size_common (fp, tp, sizep, incrementp,
125867d70fcSchristos CTF_TYPE_LSIZE (t1p), t1p->ctt_size,
126867d70fcSchristos sizeof (ctf_type_t), sizeof (ctf_stype_t),
127867d70fcSchristos CTF_LSIZE_SENT));
128867d70fcSchristos }
129867d70fcSchristos
130867d70fcSchristos static ssize_t
get_ctt_size_v2(const ctf_dict_t * fp,const ctf_type_t * tp,ssize_t * sizep,ssize_t * incrementp)131*c42dbd0eSchristos get_ctt_size_v2 (const ctf_dict_t *fp, const ctf_type_t *tp,
132867d70fcSchristos ssize_t *sizep, ssize_t *incrementp)
133867d70fcSchristos {
134867d70fcSchristos return (get_ctt_size_common (fp, tp, sizep, incrementp,
135867d70fcSchristos CTF_TYPE_LSIZE (tp), tp->ctt_size,
136867d70fcSchristos sizeof (ctf_type_t), sizeof (ctf_stype_t),
137867d70fcSchristos CTF_LSIZE_SENT));
138867d70fcSchristos }
139867d70fcSchristos
140867d70fcSchristos static ssize_t
get_vbytes_common(ctf_dict_t * fp,unsigned short kind,ssize_t size _libctf_unused_,size_t vlen)141*c42dbd0eSchristos get_vbytes_common (ctf_dict_t *fp, unsigned short kind,
142*c42dbd0eSchristos ssize_t size _libctf_unused_, size_t vlen)
143867d70fcSchristos {
144867d70fcSchristos switch (kind)
145867d70fcSchristos {
146867d70fcSchristos case CTF_K_INTEGER:
147867d70fcSchristos case CTF_K_FLOAT:
148867d70fcSchristos return (sizeof (uint32_t));
149867d70fcSchristos case CTF_K_SLICE:
150867d70fcSchristos return (sizeof (ctf_slice_t));
151867d70fcSchristos case CTF_K_ENUM:
152867d70fcSchristos return (sizeof (ctf_enum_t) * vlen);
153867d70fcSchristos case CTF_K_FORWARD:
154867d70fcSchristos case CTF_K_UNKNOWN:
155867d70fcSchristos case CTF_K_POINTER:
156867d70fcSchristos case CTF_K_TYPEDEF:
157867d70fcSchristos case CTF_K_VOLATILE:
158867d70fcSchristos case CTF_K_CONST:
159867d70fcSchristos case CTF_K_RESTRICT:
160867d70fcSchristos return 0;
161867d70fcSchristos default:
162*c42dbd0eSchristos ctf_set_errno (fp, ECTF_CORRUPT);
163*c42dbd0eSchristos ctf_err_warn (fp, 0, 0, _("detected invalid CTF kind: %x"), kind);
164*c42dbd0eSchristos return -1;
165867d70fcSchristos }
166867d70fcSchristos }
167867d70fcSchristos
168867d70fcSchristos static ssize_t
get_vbytes_v1(ctf_dict_t * fp,unsigned short kind,ssize_t size,size_t vlen)169*c42dbd0eSchristos get_vbytes_v1 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen)
170867d70fcSchristos {
171867d70fcSchristos switch (kind)
172867d70fcSchristos {
173867d70fcSchristos case CTF_K_ARRAY:
174867d70fcSchristos return (sizeof (ctf_array_v1_t));
175867d70fcSchristos case CTF_K_FUNCTION:
176867d70fcSchristos return (sizeof (unsigned short) * (vlen + (vlen & 1)));
177867d70fcSchristos case CTF_K_STRUCT:
178867d70fcSchristos case CTF_K_UNION:
179867d70fcSchristos if (size < CTF_LSTRUCT_THRESH_V1)
180867d70fcSchristos return (sizeof (ctf_member_v1_t) * vlen);
181867d70fcSchristos else
182867d70fcSchristos return (sizeof (ctf_lmember_v1_t) * vlen);
183867d70fcSchristos }
184867d70fcSchristos
185*c42dbd0eSchristos return (get_vbytes_common (fp, kind, size, vlen));
186867d70fcSchristos }
187867d70fcSchristos
188867d70fcSchristos static ssize_t
get_vbytes_v2(ctf_dict_t * fp,unsigned short kind,ssize_t size,size_t vlen)189*c42dbd0eSchristos get_vbytes_v2 (ctf_dict_t *fp, unsigned short kind, ssize_t size, size_t vlen)
190867d70fcSchristos {
191867d70fcSchristos switch (kind)
192867d70fcSchristos {
193867d70fcSchristos case CTF_K_ARRAY:
194867d70fcSchristos return (sizeof (ctf_array_t));
195867d70fcSchristos case CTF_K_FUNCTION:
196867d70fcSchristos return (sizeof (uint32_t) * (vlen + (vlen & 1)));
197867d70fcSchristos case CTF_K_STRUCT:
198867d70fcSchristos case CTF_K_UNION:
199867d70fcSchristos if (size < CTF_LSTRUCT_THRESH)
200867d70fcSchristos return (sizeof (ctf_member_t) * vlen);
201867d70fcSchristos else
202867d70fcSchristos return (sizeof (ctf_lmember_t) * vlen);
203867d70fcSchristos }
204867d70fcSchristos
205*c42dbd0eSchristos return (get_vbytes_common (fp, kind, size, vlen));
206867d70fcSchristos }
207867d70fcSchristos
208*c42dbd0eSchristos static const ctf_dictops_t ctf_dictops[] = {
209867d70fcSchristos {NULL, NULL, NULL, NULL, NULL},
210867d70fcSchristos /* CTF_VERSION_1 */
211867d70fcSchristos {get_kind_v1, get_root_v1, get_vlen_v1, get_ctt_size_v1, get_vbytes_v1},
212867d70fcSchristos /* CTF_VERSION_1_UPGRADED_3 */
213867d70fcSchristos {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
214867d70fcSchristos /* CTF_VERSION_2 */
215867d70fcSchristos {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
216867d70fcSchristos /* CTF_VERSION_3, identical to 2: only new type kinds */
217867d70fcSchristos {get_kind_v2, get_root_v2, get_vlen_v2, get_ctt_size_v2, get_vbytes_v2},
218867d70fcSchristos };
219867d70fcSchristos
220*c42dbd0eSchristos /* Initialize the symtab translation table as appropriate for its indexing
221*c42dbd0eSchristos state. For unindexed symtypetabs, fill each entry with the offset of the CTF
222*c42dbd0eSchristos type or function data corresponding to each STT_FUNC or STT_OBJECT entry in
223*c42dbd0eSchristos the symbol table. For indexed symtypetabs, do nothing: the needed
224*c42dbd0eSchristos initialization for indexed lookups may be quite expensive, so it is done only
225*c42dbd0eSchristos as needed, when lookups happen. (In particular, the majority of indexed
226*c42dbd0eSchristos symtypetabs come from the compiler, and all the linker does is iteration over
227*c42dbd0eSchristos all entries, which doesn't need this initialization.)
228*c42dbd0eSchristos
229*c42dbd0eSchristos The SP symbol table section may be NULL if there is no symtab.
230*c42dbd0eSchristos
231*c42dbd0eSchristos If init_symtab works on one call, it cannot fail on future calls to the same
232*c42dbd0eSchristos fp: ctf_symsect_endianness relies on this. */
233867d70fcSchristos
234867d70fcSchristos static int
init_symtab(ctf_dict_t * fp,const ctf_header_t * hp,const ctf_sect_t * sp)235*c42dbd0eSchristos init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
236867d70fcSchristos {
237*c42dbd0eSchristos const unsigned char *symp;
238*c42dbd0eSchristos int skip_func_info = 0;
239*c42dbd0eSchristos int i;
240867d70fcSchristos uint32_t *xp = fp->ctf_sxlate;
241*c42dbd0eSchristos uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms);
242867d70fcSchristos
243867d70fcSchristos uint32_t objtoff = hp->cth_objtoff;
244867d70fcSchristos uint32_t funcoff = hp->cth_funcoff;
245867d70fcSchristos
246*c42dbd0eSchristos /* If the CTF_F_NEWFUNCINFO flag is not set, pretend the func info section
247*c42dbd0eSchristos is empty: this compiler is too old to emit a function info section we
248*c42dbd0eSchristos understand. */
249867d70fcSchristos
250*c42dbd0eSchristos if (!(hp->cth_flags & CTF_F_NEWFUNCINFO))
251*c42dbd0eSchristos skip_func_info = 1;
252867d70fcSchristos
253*c42dbd0eSchristos if (hp->cth_objtidxoff < hp->cth_funcidxoff)
254*c42dbd0eSchristos fp->ctf_objtidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_objtidxoff);
255*c42dbd0eSchristos if (hp->cth_funcidxoff < hp->cth_varoff && !skip_func_info)
256*c42dbd0eSchristos fp->ctf_funcidx_names = (uint32_t *) (fp->ctf_buf + hp->cth_funcidxoff);
257*c42dbd0eSchristos
258*c42dbd0eSchristos /* Don't bother doing the rest if everything is indexed, or if we don't have a
259*c42dbd0eSchristos symbol table: we will never use it. */
260*c42dbd0eSchristos if ((fp->ctf_objtidx_names && fp->ctf_funcidx_names) || !sp || !sp->cts_data)
261*c42dbd0eSchristos return 0;
262*c42dbd0eSchristos
263*c42dbd0eSchristos /* The CTF data object and function type sections are ordered to match the
264*c42dbd0eSchristos relative order of the respective symbol types in the symtab, unless there
265*c42dbd0eSchristos is an index section, in which case the order is arbitrary and the index
266*c42dbd0eSchristos gives the mapping. If no type information is available for a symbol table
267*c42dbd0eSchristos entry, a pad is inserted in the CTF section. As a further optimization,
268*c42dbd0eSchristos anonymous or undefined symbols are omitted from the CTF data. If an
269*c42dbd0eSchristos index is available for function symbols but not object symbols, or vice
270*c42dbd0eSchristos versa, we populate the xslate table for the unindexed symbols only. */
271*c42dbd0eSchristos
272*c42dbd0eSchristos for (i = 0, symp = sp->cts_data; xp < xend; xp++, symp += sp->cts_entsize,
273*c42dbd0eSchristos i++)
274867d70fcSchristos {
275*c42dbd0eSchristos ctf_link_sym_t sym;
276867d70fcSchristos
277*c42dbd0eSchristos switch (sp->cts_entsize)
278*c42dbd0eSchristos {
279*c42dbd0eSchristos case sizeof (Elf64_Sym):
280*c42dbd0eSchristos {
281*c42dbd0eSchristos const Elf64_Sym *symp64 = (Elf64_Sym *) (uintptr_t) symp;
282*c42dbd0eSchristos ctf_elf64_to_link_sym (fp, &sym, symp64, i);
283*c42dbd0eSchristos }
284*c42dbd0eSchristos break;
285*c42dbd0eSchristos case sizeof (Elf32_Sym):
286*c42dbd0eSchristos {
287*c42dbd0eSchristos const Elf32_Sym *symp32 = (Elf32_Sym *) (uintptr_t) symp;
288*c42dbd0eSchristos ctf_elf32_to_link_sym (fp, &sym, symp32, i);
289*c42dbd0eSchristos }
290*c42dbd0eSchristos break;
291*c42dbd0eSchristos default:
292*c42dbd0eSchristos return ECTF_SYMTAB;
293*c42dbd0eSchristos }
294867d70fcSchristos
295*c42dbd0eSchristos /* This call may be led astray if our idea of the symtab's endianness is
296*c42dbd0eSchristos wrong, but when this is fixed by a call to ctf_symsect_endianness,
297*c42dbd0eSchristos init_symtab will be called again with the right endianness in
298*c42dbd0eSchristos force. */
299*c42dbd0eSchristos if (ctf_symtab_skippable (&sym))
300867d70fcSchristos {
301867d70fcSchristos *xp = -1u;
302867d70fcSchristos continue;
303867d70fcSchristos }
304867d70fcSchristos
305*c42dbd0eSchristos switch (sym.st_type)
306867d70fcSchristos {
307867d70fcSchristos case STT_OBJECT:
308*c42dbd0eSchristos if (fp->ctf_objtidx_names || objtoff >= hp->cth_funcoff)
309867d70fcSchristos {
310867d70fcSchristos *xp = -1u;
311867d70fcSchristos break;
312867d70fcSchristos }
313867d70fcSchristos
314867d70fcSchristos *xp = objtoff;
315867d70fcSchristos objtoff += sizeof (uint32_t);
316867d70fcSchristos break;
317867d70fcSchristos
318867d70fcSchristos case STT_FUNC:
319*c42dbd0eSchristos if (fp->ctf_funcidx_names || funcoff >= hp->cth_objtidxoff
320*c42dbd0eSchristos || skip_func_info)
321867d70fcSchristos {
322867d70fcSchristos *xp = -1u;
323867d70fcSchristos break;
324867d70fcSchristos }
325867d70fcSchristos
326867d70fcSchristos *xp = funcoff;
327*c42dbd0eSchristos funcoff += sizeof (uint32_t);
328867d70fcSchristos break;
329867d70fcSchristos
330867d70fcSchristos default:
331867d70fcSchristos *xp = -1u;
332867d70fcSchristos break;
333867d70fcSchristos }
334867d70fcSchristos }
335867d70fcSchristos
336867d70fcSchristos ctf_dprintf ("loaded %lu symtab entries\n", fp->ctf_nsyms);
337867d70fcSchristos return 0;
338867d70fcSchristos }
339867d70fcSchristos
340867d70fcSchristos /* Reset the CTF base pointer and derive the buf pointer from it, initializing
341*c42dbd0eSchristos everything in the ctf_dict that depends on the base or buf pointers.
342867d70fcSchristos
343867d70fcSchristos The original gap between the buf and base pointers, if any -- the original,
344867d70fcSchristos unconverted CTF header -- is kept, but its contents are not specified and are
345867d70fcSchristos never used. */
346867d70fcSchristos
347867d70fcSchristos static void
ctf_set_base(ctf_dict_t * fp,const ctf_header_t * hp,unsigned char * base)348*c42dbd0eSchristos ctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base)
349867d70fcSchristos {
350867d70fcSchristos fp->ctf_buf = base + (fp->ctf_buf - fp->ctf_base);
351867d70fcSchristos fp->ctf_base = base;
352867d70fcSchristos fp->ctf_vars = (ctf_varent_t *) ((const char *) fp->ctf_buf +
353867d70fcSchristos hp->cth_varoff);
354867d70fcSchristos fp->ctf_nvars = (hp->cth_typeoff - hp->cth_varoff) / sizeof (ctf_varent_t);
355867d70fcSchristos
356867d70fcSchristos fp->ctf_str[CTF_STRTAB_0].cts_strs = (const char *) fp->ctf_buf
357867d70fcSchristos + hp->cth_stroff;
358867d70fcSchristos fp->ctf_str[CTF_STRTAB_0].cts_len = hp->cth_strlen;
359867d70fcSchristos
360*c42dbd0eSchristos /* If we have a parent dict name and label, store the relocated string
361*c42dbd0eSchristos pointers in the CTF dict for easy access later. */
362867d70fcSchristos
363867d70fcSchristos /* Note: before conversion, these will be set to values that will be
364867d70fcSchristos immediately invalidated by the conversion process, but the conversion
365867d70fcSchristos process will call ctf_set_base() again to fix things up. */
366867d70fcSchristos
367867d70fcSchristos if (hp->cth_parlabel != 0)
368867d70fcSchristos fp->ctf_parlabel = ctf_strptr (fp, hp->cth_parlabel);
369867d70fcSchristos if (hp->cth_parname != 0)
370867d70fcSchristos fp->ctf_parname = ctf_strptr (fp, hp->cth_parname);
371867d70fcSchristos if (hp->cth_cuname != 0)
372867d70fcSchristos fp->ctf_cuname = ctf_strptr (fp, hp->cth_cuname);
373867d70fcSchristos
374867d70fcSchristos if (fp->ctf_cuname)
375867d70fcSchristos ctf_dprintf ("ctf_set_base: CU name %s\n", fp->ctf_cuname);
376867d70fcSchristos if (fp->ctf_parname)
377867d70fcSchristos ctf_dprintf ("ctf_set_base: parent name %s (label %s)\n",
378867d70fcSchristos fp->ctf_parname,
379867d70fcSchristos fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");
380867d70fcSchristos }
381867d70fcSchristos
382867d70fcSchristos /* Set the version of the CTF file. */
383867d70fcSchristos
384867d70fcSchristos /* When this is reset, LCTF_* changes behaviour, but there is no guarantee that
385867d70fcSchristos the variable data list associated with each type has been upgraded: the
386867d70fcSchristos caller must ensure this has been done in advance. */
387867d70fcSchristos
388867d70fcSchristos static void
ctf_set_version(ctf_dict_t * fp,ctf_header_t * cth,int ctf_version)389*c42dbd0eSchristos ctf_set_version (ctf_dict_t *fp, ctf_header_t *cth, int ctf_version)
390867d70fcSchristos {
391867d70fcSchristos fp->ctf_version = ctf_version;
392867d70fcSchristos cth->cth_version = ctf_version;
393*c42dbd0eSchristos fp->ctf_dictops = &ctf_dictops[ctf_version];
394867d70fcSchristos }
395867d70fcSchristos
396867d70fcSchristos
397867d70fcSchristos /* Upgrade the header to CTF_VERSION_3. The upgrade is done in-place. */
398867d70fcSchristos static void
upgrade_header(ctf_header_t * hp)399867d70fcSchristos upgrade_header (ctf_header_t *hp)
400867d70fcSchristos {
401867d70fcSchristos ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp;
402867d70fcSchristos
403867d70fcSchristos hp->cth_strlen = oldhp->cth_strlen;
404867d70fcSchristos hp->cth_stroff = oldhp->cth_stroff;
405867d70fcSchristos hp->cth_typeoff = oldhp->cth_typeoff;
406867d70fcSchristos hp->cth_varoff = oldhp->cth_varoff;
407867d70fcSchristos hp->cth_funcidxoff = hp->cth_varoff; /* No index sections. */
408867d70fcSchristos hp->cth_objtidxoff = hp->cth_funcidxoff;
409867d70fcSchristos hp->cth_funcoff = oldhp->cth_funcoff;
410867d70fcSchristos hp->cth_objtoff = oldhp->cth_objtoff;
411867d70fcSchristos hp->cth_lbloff = oldhp->cth_lbloff;
412867d70fcSchristos hp->cth_cuname = 0; /* No CU name. */
413867d70fcSchristos }
414867d70fcSchristos
415867d70fcSchristos /* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3)
416867d70fcSchristos from CTF_VERSION_1.
417867d70fcSchristos
418867d70fcSchristos The upgrade is not done in-place: the ctf_base is moved. ctf_strptr() must
419867d70fcSchristos not be called before reallocation is complete.
420867d70fcSchristos
421867d70fcSchristos Sections not checked here due to nonexistence or nonpopulated state in older
422867d70fcSchristos formats: objtidx, funcidx.
423867d70fcSchristos
424867d70fcSchristos Type kinds not checked here due to nonexistence in older formats:
425867d70fcSchristos CTF_K_SLICE. */
426867d70fcSchristos static int
upgrade_types_v1(ctf_dict_t * fp,ctf_header_t * cth)427*c42dbd0eSchristos upgrade_types_v1 (ctf_dict_t *fp, ctf_header_t *cth)
428867d70fcSchristos {
429867d70fcSchristos const ctf_type_v1_t *tbuf;
430867d70fcSchristos const ctf_type_v1_t *tend;
431867d70fcSchristos unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_dynbase;
432867d70fcSchristos ctf_type_t *t2buf;
433867d70fcSchristos
434867d70fcSchristos ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes;
435867d70fcSchristos const ctf_type_v1_t *tp;
436867d70fcSchristos ctf_type_t *t2p;
437867d70fcSchristos
438867d70fcSchristos tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff);
439867d70fcSchristos tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff);
440867d70fcSchristos
441867d70fcSchristos /* Much like init_types(), this is a two-pass process.
442867d70fcSchristos
443867d70fcSchristos First, figure out the new type-section size needed. (It is possible,
444867d70fcSchristos in theory, for it to be less than the old size, but this is very
445867d70fcSchristos unlikely. It cannot be so small that cth_typeoff ends up of negative
446867d70fcSchristos size. We validate this with an assertion below.)
447867d70fcSchristos
448867d70fcSchristos We must cater not only for changes in vlen and types sizes but also
449867d70fcSchristos for changes in 'increment', which happen because v2 places some types
450867d70fcSchristos into ctf_stype_t where v1 would be forced to use the larger non-stype. */
451867d70fcSchristos
452867d70fcSchristos for (tp = tbuf; tp < tend;
453867d70fcSchristos tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes))
454867d70fcSchristos {
455867d70fcSchristos unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
456867d70fcSchristos unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
457867d70fcSchristos
458867d70fcSchristos size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
459*c42dbd0eSchristos vbytes = get_vbytes_v1 (fp, kind, size, vlen);
460867d70fcSchristos
461867d70fcSchristos get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL,
462867d70fcSchristos &v2increment);
463*c42dbd0eSchristos v2bytes = get_vbytes_v2 (fp, kind, size, vlen);
464867d70fcSchristos
465867d70fcSchristos if ((vbytes < 0) || (size < 0))
466867d70fcSchristos return ECTF_CORRUPT;
467867d70fcSchristos
468867d70fcSchristos increase += v2increment - increment; /* May be negative. */
469867d70fcSchristos increase += v2bytes - vbytes;
470867d70fcSchristos }
471867d70fcSchristos
472867d70fcSchristos /* Allocate enough room for the new buffer, then copy everything but the type
473867d70fcSchristos section into place, and reset the base accordingly. Leave the version
474867d70fcSchristos number unchanged, so that LCTF_INFO_* still works on the
475867d70fcSchristos as-yet-untranslated type info. */
476867d70fcSchristos
477867d70fcSchristos if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL)
478867d70fcSchristos return ECTF_ZALLOC;
479867d70fcSchristos
480867d70fcSchristos /* Start at ctf_buf, not ctf_base, to squeeze out the original header: we
481867d70fcSchristos never use it and it is unconverted. */
482867d70fcSchristos
483867d70fcSchristos memcpy (ctf_base, fp->ctf_buf, cth->cth_typeoff);
484867d70fcSchristos memcpy (ctf_base + cth->cth_stroff + increase,
485867d70fcSchristos fp->ctf_buf + cth->cth_stroff, cth->cth_strlen);
486867d70fcSchristos
487867d70fcSchristos memset (ctf_base + cth->cth_typeoff, 0, cth->cth_stroff - cth->cth_typeoff
488867d70fcSchristos + increase);
489867d70fcSchristos
490867d70fcSchristos cth->cth_stroff += increase;
491867d70fcSchristos fp->ctf_size += increase;
492867d70fcSchristos assert (cth->cth_stroff >= cth->cth_typeoff);
493867d70fcSchristos fp->ctf_base = ctf_base;
494867d70fcSchristos fp->ctf_buf = ctf_base;
495867d70fcSchristos fp->ctf_dynbase = ctf_base;
496867d70fcSchristos ctf_set_base (fp, cth, ctf_base);
497867d70fcSchristos
498867d70fcSchristos t2buf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
499867d70fcSchristos
500867d70fcSchristos /* Iterate through all the types again, upgrading them.
501867d70fcSchristos
502867d70fcSchristos Everything that hasn't changed can just be outright memcpy()ed.
503867d70fcSchristos Things that have changed need field-by-field consideration. */
504867d70fcSchristos
505867d70fcSchristos for (tp = tbuf, t2p = t2buf; tp < tend;
506867d70fcSchristos tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes),
507867d70fcSchristos t2p = (ctf_type_t *) ((uintptr_t) t2p + v2increment + v2bytes))
508867d70fcSchristos {
509867d70fcSchristos unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
510867d70fcSchristos int isroot = CTF_V1_INFO_ISROOT (tp->ctt_info);
511867d70fcSchristos unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
512867d70fcSchristos ssize_t v2size;
513867d70fcSchristos void *vdata, *v2data;
514867d70fcSchristos
515867d70fcSchristos size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
516*c42dbd0eSchristos vbytes = get_vbytes_v1 (fp, kind, size, vlen);
517867d70fcSchristos
518867d70fcSchristos t2p->ctt_name = tp->ctt_name;
519867d70fcSchristos t2p->ctt_info = CTF_TYPE_INFO (kind, isroot, vlen);
520867d70fcSchristos
521867d70fcSchristos switch (kind)
522867d70fcSchristos {
523867d70fcSchristos case CTF_K_FUNCTION:
524867d70fcSchristos case CTF_K_FORWARD:
525867d70fcSchristos case CTF_K_TYPEDEF:
526867d70fcSchristos case CTF_K_POINTER:
527867d70fcSchristos case CTF_K_VOLATILE:
528867d70fcSchristos case CTF_K_CONST:
529867d70fcSchristos case CTF_K_RESTRICT:
530867d70fcSchristos t2p->ctt_type = tp->ctt_type;
531867d70fcSchristos break;
532867d70fcSchristos case CTF_K_INTEGER:
533867d70fcSchristos case CTF_K_FLOAT:
534867d70fcSchristos case CTF_K_ARRAY:
535867d70fcSchristos case CTF_K_STRUCT:
536867d70fcSchristos case CTF_K_UNION:
537867d70fcSchristos case CTF_K_ENUM:
538867d70fcSchristos case CTF_K_UNKNOWN:
539867d70fcSchristos if ((size_t) size <= CTF_MAX_SIZE)
540867d70fcSchristos t2p->ctt_size = size;
541867d70fcSchristos else
542867d70fcSchristos {
543867d70fcSchristos t2p->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
544867d70fcSchristos t2p->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
545867d70fcSchristos }
546867d70fcSchristos break;
547867d70fcSchristos }
548867d70fcSchristos
549867d70fcSchristos v2size = get_ctt_size_v2 (fp, t2p, NULL, &v2increment);
550*c42dbd0eSchristos v2bytes = get_vbytes_v2 (fp, kind, v2size, vlen);
551867d70fcSchristos
552867d70fcSchristos /* Catch out-of-sync get_ctt_size_*(). The count goes wrong if
553867d70fcSchristos these are not identical (and having them different makes no
554867d70fcSchristos sense semantically). */
555867d70fcSchristos
556867d70fcSchristos assert (size == v2size);
557867d70fcSchristos
558867d70fcSchristos /* Now the varlen info. */
559867d70fcSchristos
560867d70fcSchristos vdata = (void *) ((uintptr_t) tp + increment);
561867d70fcSchristos v2data = (void *) ((uintptr_t) t2p + v2increment);
562867d70fcSchristos
563867d70fcSchristos switch (kind)
564867d70fcSchristos {
565867d70fcSchristos case CTF_K_ARRAY:
566867d70fcSchristos {
567867d70fcSchristos const ctf_array_v1_t *ap = (const ctf_array_v1_t *) vdata;
568867d70fcSchristos ctf_array_t *a2p = (ctf_array_t *) v2data;
569867d70fcSchristos
570867d70fcSchristos a2p->cta_contents = ap->cta_contents;
571867d70fcSchristos a2p->cta_index = ap->cta_index;
572867d70fcSchristos a2p->cta_nelems = ap->cta_nelems;
573867d70fcSchristos break;
574867d70fcSchristos }
575867d70fcSchristos case CTF_K_STRUCT:
576867d70fcSchristos case CTF_K_UNION:
577867d70fcSchristos {
578867d70fcSchristos ctf_member_t tmp;
579867d70fcSchristos const ctf_member_v1_t *m1 = (const ctf_member_v1_t *) vdata;
580867d70fcSchristos const ctf_lmember_v1_t *lm1 = (const ctf_lmember_v1_t *) m1;
581867d70fcSchristos ctf_member_t *m2 = (ctf_member_t *) v2data;
582867d70fcSchristos ctf_lmember_t *lm2 = (ctf_lmember_t *) m2;
583867d70fcSchristos unsigned long i;
584867d70fcSchristos
585867d70fcSchristos /* We walk all four pointers forward, but only reference the two
586867d70fcSchristos that are valid for the given size, to avoid quadruplicating all
587867d70fcSchristos the code. */
588867d70fcSchristos
589867d70fcSchristos for (i = vlen; i != 0; i--, m1++, lm1++, m2++, lm2++)
590867d70fcSchristos {
591867d70fcSchristos size_t offset;
592867d70fcSchristos if (size < CTF_LSTRUCT_THRESH_V1)
593867d70fcSchristos {
594867d70fcSchristos offset = m1->ctm_offset;
595867d70fcSchristos tmp.ctm_name = m1->ctm_name;
596867d70fcSchristos tmp.ctm_type = m1->ctm_type;
597867d70fcSchristos }
598867d70fcSchristos else
599867d70fcSchristos {
600867d70fcSchristos offset = CTF_LMEM_OFFSET (lm1);
601867d70fcSchristos tmp.ctm_name = lm1->ctlm_name;
602867d70fcSchristos tmp.ctm_type = lm1->ctlm_type;
603867d70fcSchristos }
604867d70fcSchristos if (size < CTF_LSTRUCT_THRESH)
605867d70fcSchristos {
606867d70fcSchristos m2->ctm_name = tmp.ctm_name;
607867d70fcSchristos m2->ctm_type = tmp.ctm_type;
608867d70fcSchristos m2->ctm_offset = offset;
609867d70fcSchristos }
610867d70fcSchristos else
611867d70fcSchristos {
612867d70fcSchristos lm2->ctlm_name = tmp.ctm_name;
613867d70fcSchristos lm2->ctlm_type = tmp.ctm_type;
614867d70fcSchristos lm2->ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (offset);
615867d70fcSchristos lm2->ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (offset);
616867d70fcSchristos }
617867d70fcSchristos }
618867d70fcSchristos break;
619867d70fcSchristos }
620867d70fcSchristos case CTF_K_FUNCTION:
621867d70fcSchristos {
622867d70fcSchristos unsigned long i;
623867d70fcSchristos unsigned short *a1 = (unsigned short *) vdata;
624867d70fcSchristos uint32_t *a2 = (uint32_t *) v2data;
625867d70fcSchristos
626867d70fcSchristos for (i = vlen; i != 0; i--, a1++, a2++)
627867d70fcSchristos *a2 = *a1;
628867d70fcSchristos }
629867d70fcSchristos /* FALLTHRU */
630867d70fcSchristos default:
631867d70fcSchristos /* Catch out-of-sync get_vbytes_*(). */
632867d70fcSchristos assert (vbytes == v2bytes);
633867d70fcSchristos memcpy (v2data, vdata, vbytes);
634867d70fcSchristos }
635867d70fcSchristos }
636867d70fcSchristos
637867d70fcSchristos /* Verify that the entire region was converted. If not, we are either
638867d70fcSchristos converting too much, or too little (leading to a buffer overrun either here
639867d70fcSchristos or at read time, in init_types().) */
640867d70fcSchristos
641867d70fcSchristos assert ((size_t) t2p - (size_t) fp->ctf_buf == cth->cth_stroff);
642867d70fcSchristos
643867d70fcSchristos ctf_set_version (fp, cth, CTF_VERSION_1_UPGRADED_3);
644867d70fcSchristos free (old_ctf_base);
645867d70fcSchristos
646867d70fcSchristos return 0;
647867d70fcSchristos }
648867d70fcSchristos
649867d70fcSchristos /* Upgrade from any earlier version. */
650867d70fcSchristos static int
upgrade_types(ctf_dict_t * fp,ctf_header_t * cth)651*c42dbd0eSchristos upgrade_types (ctf_dict_t *fp, ctf_header_t *cth)
652867d70fcSchristos {
653867d70fcSchristos switch (cth->cth_version)
654867d70fcSchristos {
655867d70fcSchristos /* v1 requires a full pass and reformatting. */
656867d70fcSchristos case CTF_VERSION_1:
657867d70fcSchristos upgrade_types_v1 (fp, cth);
658867d70fcSchristos /* FALLTHRU */
659867d70fcSchristos /* Already-converted v1 is just like later versions except that its
660867d70fcSchristos parent/child boundary is unchanged (and much lower). */
661867d70fcSchristos
662867d70fcSchristos case CTF_VERSION_1_UPGRADED_3:
663867d70fcSchristos fp->ctf_parmax = CTF_MAX_PTYPE_V1;
664867d70fcSchristos
665867d70fcSchristos /* v2 is just the same as v3 except for new types and sections:
666867d70fcSchristos no upgrading required. */
667867d70fcSchristos case CTF_VERSION_2: ;
668867d70fcSchristos /* FALLTHRU */
669867d70fcSchristos }
670867d70fcSchristos return 0;
671867d70fcSchristos }
672867d70fcSchristos
673867d70fcSchristos /* Initialize the type ID translation table with the byte offset of each type,
674867d70fcSchristos and initialize the hash tables of each named type. Upgrade the type table to
675867d70fcSchristos the latest supported representation in the process, if needed, and if this
676867d70fcSchristos recension of libctf supports upgrading. */
677867d70fcSchristos
678867d70fcSchristos static int
init_types(ctf_dict_t * fp,ctf_header_t * cth)679*c42dbd0eSchristos init_types (ctf_dict_t *fp, ctf_header_t *cth)
680867d70fcSchristos {
681867d70fcSchristos const ctf_type_t *tbuf;
682867d70fcSchristos const ctf_type_t *tend;
683867d70fcSchristos
684867d70fcSchristos unsigned long pop[CTF_K_MAX + 1] = { 0 };
685867d70fcSchristos const ctf_type_t *tp;
686*c42dbd0eSchristos uint32_t id;
687867d70fcSchristos uint32_t *xp;
688867d70fcSchristos
689*c42dbd0eSchristos /* We determine whether the dict is a child or a parent based on the value of
690*c42dbd0eSchristos cth_parname. */
691867d70fcSchristos
692867d70fcSchristos int child = cth->cth_parname != 0;
693867d70fcSchristos int nlstructs = 0, nlunions = 0;
694867d70fcSchristos int err;
695867d70fcSchristos
696867d70fcSchristos assert (!(fp->ctf_flags & LCTF_RDWR));
697867d70fcSchristos
698867d70fcSchristos if (_libctf_unlikely_ (fp->ctf_version == CTF_VERSION_1))
699867d70fcSchristos {
700867d70fcSchristos int err;
701867d70fcSchristos if ((err = upgrade_types (fp, cth)) != 0)
702867d70fcSchristos return err; /* Upgrade failed. */
703867d70fcSchristos }
704867d70fcSchristos
705867d70fcSchristos tbuf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
706867d70fcSchristos tend = (ctf_type_t *) (fp->ctf_buf + cth->cth_stroff);
707867d70fcSchristos
708867d70fcSchristos /* We make two passes through the entire type section. In this first
709867d70fcSchristos pass, we count the number of each type and the total number of types. */
710867d70fcSchristos
711867d70fcSchristos for (tp = tbuf; tp < tend; fp->ctf_typemax++)
712867d70fcSchristos {
713867d70fcSchristos unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
714867d70fcSchristos unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
715867d70fcSchristos ssize_t size, increment, vbytes;
716867d70fcSchristos
717867d70fcSchristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
718867d70fcSchristos vbytes = LCTF_VBYTES (fp, kind, size, vlen);
719867d70fcSchristos
720867d70fcSchristos if (vbytes < 0)
721867d70fcSchristos return ECTF_CORRUPT;
722867d70fcSchristos
723867d70fcSchristos /* For forward declarations, ctt_type is the CTF_K_* kind for the tag,
724*c42dbd0eSchristos so bump that population count too. */
725*c42dbd0eSchristos if (kind == CTF_K_FORWARD)
726867d70fcSchristos pop[tp->ctt_type]++;
727*c42dbd0eSchristos
728867d70fcSchristos tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
729867d70fcSchristos pop[kind]++;
730867d70fcSchristos }
731867d70fcSchristos
732867d70fcSchristos if (child)
733867d70fcSchristos {
734*c42dbd0eSchristos ctf_dprintf ("CTF dict %p is a child\n", (void *) fp);
735867d70fcSchristos fp->ctf_flags |= LCTF_CHILD;
736867d70fcSchristos }
737867d70fcSchristos else
738*c42dbd0eSchristos ctf_dprintf ("CTF dict %p is a parent\n", (void *) fp);
739867d70fcSchristos
740867d70fcSchristos /* Now that we've counted up the number of each type, we can allocate
741867d70fcSchristos the hash tables, type translation table, and pointer table. */
742867d70fcSchristos
743867d70fcSchristos if ((fp->ctf_structs.ctn_readonly
744867d70fcSchristos = ctf_hash_create (pop[CTF_K_STRUCT], ctf_hash_string,
745867d70fcSchristos ctf_hash_eq_string)) == NULL)
746867d70fcSchristos return ENOMEM;
747867d70fcSchristos
748867d70fcSchristos if ((fp->ctf_unions.ctn_readonly
749867d70fcSchristos = ctf_hash_create (pop[CTF_K_UNION], ctf_hash_string,
750867d70fcSchristos ctf_hash_eq_string)) == NULL)
751867d70fcSchristos return ENOMEM;
752867d70fcSchristos
753867d70fcSchristos if ((fp->ctf_enums.ctn_readonly
754867d70fcSchristos = ctf_hash_create (pop[CTF_K_ENUM], ctf_hash_string,
755867d70fcSchristos ctf_hash_eq_string)) == NULL)
756867d70fcSchristos return ENOMEM;
757867d70fcSchristos
758867d70fcSchristos if ((fp->ctf_names.ctn_readonly
759*c42dbd0eSchristos = ctf_hash_create (pop[CTF_K_UNKNOWN] +
760*c42dbd0eSchristos pop[CTF_K_INTEGER] +
761867d70fcSchristos pop[CTF_K_FLOAT] +
762867d70fcSchristos pop[CTF_K_FUNCTION] +
763867d70fcSchristos pop[CTF_K_TYPEDEF] +
764867d70fcSchristos pop[CTF_K_POINTER] +
765867d70fcSchristos pop[CTF_K_VOLATILE] +
766867d70fcSchristos pop[CTF_K_CONST] +
767867d70fcSchristos pop[CTF_K_RESTRICT],
768867d70fcSchristos ctf_hash_string,
769867d70fcSchristos ctf_hash_eq_string)) == NULL)
770867d70fcSchristos return ENOMEM;
771867d70fcSchristos
772867d70fcSchristos fp->ctf_txlate = malloc (sizeof (uint32_t) * (fp->ctf_typemax + 1));
773867d70fcSchristos fp->ctf_ptrtab_len = fp->ctf_typemax + 1;
774867d70fcSchristos fp->ctf_ptrtab = malloc (sizeof (uint32_t) * fp->ctf_ptrtab_len);
775867d70fcSchristos
776867d70fcSchristos if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
777867d70fcSchristos return ENOMEM; /* Memory allocation failed. */
778867d70fcSchristos
779867d70fcSchristos xp = fp->ctf_txlate;
780867d70fcSchristos *xp++ = 0; /* Type id 0 is used as a sentinel value. */
781867d70fcSchristos
782867d70fcSchristos memset (fp->ctf_txlate, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1));
783867d70fcSchristos memset (fp->ctf_ptrtab, 0, sizeof (uint32_t) * (fp->ctf_typemax + 1));
784867d70fcSchristos
785867d70fcSchristos /* In the second pass through the types, we fill in each entry of the
786867d70fcSchristos type and pointer tables and add names to the appropriate hashes. */
787867d70fcSchristos
788867d70fcSchristos for (id = 1, tp = tbuf; tp < tend; xp++, id++)
789867d70fcSchristos {
790867d70fcSchristos unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
791*c42dbd0eSchristos unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info);
792867d70fcSchristos unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
793867d70fcSchristos ssize_t size, increment, vbytes;
794867d70fcSchristos
795867d70fcSchristos const char *name;
796867d70fcSchristos
797867d70fcSchristos (void) ctf_get_ctt_size (fp, tp, &size, &increment);
798867d70fcSchristos name = ctf_strptr (fp, tp->ctt_name);
799*c42dbd0eSchristos /* Cannot fail: shielded by call in loop above. */
800867d70fcSchristos vbytes = LCTF_VBYTES (fp, kind, size, vlen);
801867d70fcSchristos
802867d70fcSchristos switch (kind)
803867d70fcSchristos {
804*c42dbd0eSchristos case CTF_K_UNKNOWN:
805867d70fcSchristos case CTF_K_INTEGER:
806867d70fcSchristos case CTF_K_FLOAT:
807867d70fcSchristos /* Names are reused by bit-fields, which are differentiated by their
808867d70fcSchristos encodings, and so typically we'd record only the first instance of
809867d70fcSchristos a given intrinsic. However, we replace an existing type with a
810867d70fcSchristos root-visible version so that we can be sure to find it when
811867d70fcSchristos checking for conflicting definitions in ctf_add_type(). */
812867d70fcSchristos
813867d70fcSchristos if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly,
814867d70fcSchristos fp, name)) == 0)
815*c42dbd0eSchristos || isroot)
816867d70fcSchristos {
817867d70fcSchristos err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp,
818867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
819867d70fcSchristos tp->ctt_name);
820867d70fcSchristos if (err != 0)
821867d70fcSchristos return err;
822867d70fcSchristos }
823867d70fcSchristos break;
824867d70fcSchristos
825867d70fcSchristos /* These kinds have no name, so do not need interning into any
826867d70fcSchristos hashtables. */
827867d70fcSchristos case CTF_K_ARRAY:
828867d70fcSchristos case CTF_K_SLICE:
829867d70fcSchristos break;
830867d70fcSchristos
831867d70fcSchristos case CTF_K_FUNCTION:
832*c42dbd0eSchristos if (!isroot)
833*c42dbd0eSchristos break;
834*c42dbd0eSchristos
835867d70fcSchristos err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
836867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
837867d70fcSchristos tp->ctt_name);
838867d70fcSchristos if (err != 0)
839867d70fcSchristos return err;
840867d70fcSchristos break;
841867d70fcSchristos
842867d70fcSchristos case CTF_K_STRUCT:
843*c42dbd0eSchristos if (size >= CTF_LSTRUCT_THRESH)
844*c42dbd0eSchristos nlstructs++;
845*c42dbd0eSchristos
846*c42dbd0eSchristos if (!isroot)
847*c42dbd0eSchristos break;
848*c42dbd0eSchristos
849867d70fcSchristos err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp,
850867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
851867d70fcSchristos tp->ctt_name);
852867d70fcSchristos
853867d70fcSchristos if (err != 0)
854867d70fcSchristos return err;
855867d70fcSchristos
856867d70fcSchristos break;
857867d70fcSchristos
858867d70fcSchristos case CTF_K_UNION:
859*c42dbd0eSchristos if (size >= CTF_LSTRUCT_THRESH)
860*c42dbd0eSchristos nlunions++;
861*c42dbd0eSchristos
862*c42dbd0eSchristos if (!isroot)
863*c42dbd0eSchristos break;
864*c42dbd0eSchristos
865867d70fcSchristos err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp,
866867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
867867d70fcSchristos tp->ctt_name);
868867d70fcSchristos
869867d70fcSchristos if (err != 0)
870867d70fcSchristos return err;
871867d70fcSchristos break;
872867d70fcSchristos
873867d70fcSchristos case CTF_K_ENUM:
874*c42dbd0eSchristos if (!isroot)
875*c42dbd0eSchristos break;
876*c42dbd0eSchristos
877867d70fcSchristos err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp,
878867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
879867d70fcSchristos tp->ctt_name);
880867d70fcSchristos
881867d70fcSchristos if (err != 0)
882867d70fcSchristos return err;
883867d70fcSchristos break;
884867d70fcSchristos
885867d70fcSchristos case CTF_K_TYPEDEF:
886*c42dbd0eSchristos if (!isroot)
887*c42dbd0eSchristos break;
888*c42dbd0eSchristos
889867d70fcSchristos err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
890867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
891867d70fcSchristos tp->ctt_name);
892867d70fcSchristos if (err != 0)
893867d70fcSchristos return err;
894867d70fcSchristos break;
895867d70fcSchristos
896867d70fcSchristos case CTF_K_FORWARD:
897867d70fcSchristos {
898867d70fcSchristos ctf_names_t *np = ctf_name_table (fp, tp->ctt_type);
899*c42dbd0eSchristos
900*c42dbd0eSchristos if (!isroot)
901*c42dbd0eSchristos break;
902*c42dbd0eSchristos
903867d70fcSchristos /* Only insert forward tags into the given hash if the type or tag
904867d70fcSchristos name is not already present. */
905867d70fcSchristos if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0)
906867d70fcSchristos {
907867d70fcSchristos err = ctf_hash_insert_type (np->ctn_readonly, fp,
908867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
909867d70fcSchristos tp->ctt_name);
910867d70fcSchristos if (err != 0)
911867d70fcSchristos return err;
912867d70fcSchristos }
913867d70fcSchristos break;
914867d70fcSchristos }
915867d70fcSchristos
916867d70fcSchristos case CTF_K_POINTER:
917*c42dbd0eSchristos /* If the type referenced by the pointer is in this CTF dict, then
918*c42dbd0eSchristos store the index of the pointer type in fp->ctf_ptrtab[ index of
919*c42dbd0eSchristos referenced type ]. */
920867d70fcSchristos
921867d70fcSchristos if (LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child
922867d70fcSchristos && LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
923867d70fcSchristos fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = id;
924867d70fcSchristos /*FALLTHRU*/
925867d70fcSchristos
926867d70fcSchristos case CTF_K_VOLATILE:
927867d70fcSchristos case CTF_K_CONST:
928867d70fcSchristos case CTF_K_RESTRICT:
929*c42dbd0eSchristos if (!isroot)
930*c42dbd0eSchristos break;
931*c42dbd0eSchristos
932867d70fcSchristos err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
933867d70fcSchristos LCTF_INDEX_TO_TYPE (fp, id, child),
934867d70fcSchristos tp->ctt_name);
935867d70fcSchristos if (err != 0)
936867d70fcSchristos return err;
937867d70fcSchristos break;
938867d70fcSchristos default:
939*c42dbd0eSchristos ctf_err_warn (fp, 0, ECTF_CORRUPT,
940*c42dbd0eSchristos _("init_types(): unhandled CTF kind: %x"), kind);
941867d70fcSchristos return ECTF_CORRUPT;
942867d70fcSchristos }
943867d70fcSchristos
944867d70fcSchristos *xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf);
945867d70fcSchristos tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
946867d70fcSchristos }
947867d70fcSchristos
948867d70fcSchristos ctf_dprintf ("%lu total types processed\n", fp->ctf_typemax);
949867d70fcSchristos ctf_dprintf ("%u enum names hashed\n",
950867d70fcSchristos ctf_hash_size (fp->ctf_enums.ctn_readonly));
951867d70fcSchristos ctf_dprintf ("%u struct names hashed (%d long)\n",
952867d70fcSchristos ctf_hash_size (fp->ctf_structs.ctn_readonly), nlstructs);
953867d70fcSchristos ctf_dprintf ("%u union names hashed (%d long)\n",
954867d70fcSchristos ctf_hash_size (fp->ctf_unions.ctn_readonly), nlunions);
955867d70fcSchristos ctf_dprintf ("%u base type names hashed\n",
956867d70fcSchristos ctf_hash_size (fp->ctf_names.ctn_readonly));
957867d70fcSchristos
958867d70fcSchristos return 0;
959867d70fcSchristos }
960867d70fcSchristos
961867d70fcSchristos /* Endianness-flipping routines.
962867d70fcSchristos
963867d70fcSchristos We flip everything, mindlessly, even 1-byte entities, so that future
964867d70fcSchristos expansions do not require changes to this code. */
965867d70fcSchristos
966867d70fcSchristos /* Flip the endianness of the CTF header. */
967867d70fcSchristos
968*c42dbd0eSchristos void
ctf_flip_header(ctf_header_t * cth)969*c42dbd0eSchristos ctf_flip_header (ctf_header_t *cth)
970867d70fcSchristos {
971867d70fcSchristos swap_thing (cth->cth_preamble.ctp_magic);
972867d70fcSchristos swap_thing (cth->cth_preamble.ctp_version);
973867d70fcSchristos swap_thing (cth->cth_preamble.ctp_flags);
974867d70fcSchristos swap_thing (cth->cth_parlabel);
975867d70fcSchristos swap_thing (cth->cth_parname);
976867d70fcSchristos swap_thing (cth->cth_cuname);
977867d70fcSchristos swap_thing (cth->cth_objtoff);
978867d70fcSchristos swap_thing (cth->cth_funcoff);
979867d70fcSchristos swap_thing (cth->cth_objtidxoff);
980867d70fcSchristos swap_thing (cth->cth_funcidxoff);
981867d70fcSchristos swap_thing (cth->cth_varoff);
982867d70fcSchristos swap_thing (cth->cth_typeoff);
983867d70fcSchristos swap_thing (cth->cth_stroff);
984867d70fcSchristos swap_thing (cth->cth_strlen);
985867d70fcSchristos }
986867d70fcSchristos
987867d70fcSchristos /* Flip the endianness of the label section, an array of ctf_lblent_t. */
988867d70fcSchristos
989867d70fcSchristos static void
flip_lbls(void * start,size_t len)990867d70fcSchristos flip_lbls (void *start, size_t len)
991867d70fcSchristos {
992867d70fcSchristos ctf_lblent_t *lbl = start;
993867d70fcSchristos ssize_t i;
994867d70fcSchristos
995867d70fcSchristos for (i = len / sizeof (struct ctf_lblent); i > 0; lbl++, i--)
996867d70fcSchristos {
997867d70fcSchristos swap_thing (lbl->ctl_label);
998867d70fcSchristos swap_thing (lbl->ctl_type);
999867d70fcSchristos }
1000867d70fcSchristos }
1001867d70fcSchristos
1002867d70fcSchristos /* Flip the endianness of the data-object or function sections or their indexes,
1003*c42dbd0eSchristos all arrays of uint32_t. */
1004867d70fcSchristos
1005867d70fcSchristos static void
flip_objts(void * start,size_t len)1006867d70fcSchristos flip_objts (void *start, size_t len)
1007867d70fcSchristos {
1008867d70fcSchristos uint32_t *obj = start;
1009867d70fcSchristos ssize_t i;
1010867d70fcSchristos
1011867d70fcSchristos for (i = len / sizeof (uint32_t); i > 0; obj++, i--)
1012867d70fcSchristos swap_thing (*obj);
1013867d70fcSchristos }
1014867d70fcSchristos
1015867d70fcSchristos /* Flip the endianness of the variable section, an array of ctf_varent_t. */
1016867d70fcSchristos
1017867d70fcSchristos static void
flip_vars(void * start,size_t len)1018867d70fcSchristos flip_vars (void *start, size_t len)
1019867d70fcSchristos {
1020867d70fcSchristos ctf_varent_t *var = start;
1021867d70fcSchristos ssize_t i;
1022867d70fcSchristos
1023867d70fcSchristos for (i = len / sizeof (struct ctf_varent); i > 0; var++, i--)
1024867d70fcSchristos {
1025867d70fcSchristos swap_thing (var->ctv_name);
1026867d70fcSchristos swap_thing (var->ctv_type);
1027867d70fcSchristos }
1028867d70fcSchristos }
1029867d70fcSchristos
1030867d70fcSchristos /* Flip the endianness of the type section, a tagged array of ctf_type or
1031867d70fcSchristos ctf_stype followed by variable data. */
1032867d70fcSchristos
1033867d70fcSchristos static int
flip_types(ctf_dict_t * fp,void * start,size_t len,int to_foreign)1034*c42dbd0eSchristos flip_types (ctf_dict_t *fp, void *start, size_t len, int to_foreign)
1035867d70fcSchristos {
1036867d70fcSchristos ctf_type_t *t = start;
1037867d70fcSchristos
1038867d70fcSchristos while ((uintptr_t) t < ((uintptr_t) start) + len)
1039867d70fcSchristos {
1040*c42dbd0eSchristos uint32_t kind;
1041*c42dbd0eSchristos size_t size;
1042*c42dbd0eSchristos uint32_t vlen;
1043*c42dbd0eSchristos size_t vbytes;
1044*c42dbd0eSchristos
1045*c42dbd0eSchristos if (to_foreign)
1046*c42dbd0eSchristos {
1047*c42dbd0eSchristos kind = CTF_V2_INFO_KIND (t->ctt_info);
1048*c42dbd0eSchristos size = t->ctt_size;
1049*c42dbd0eSchristos vlen = CTF_V2_INFO_VLEN (t->ctt_info);
1050*c42dbd0eSchristos vbytes = get_vbytes_v2 (fp, kind, size, vlen);
1051*c42dbd0eSchristos }
1052*c42dbd0eSchristos
1053867d70fcSchristos swap_thing (t->ctt_name);
1054867d70fcSchristos swap_thing (t->ctt_info);
1055867d70fcSchristos swap_thing (t->ctt_size);
1056867d70fcSchristos
1057*c42dbd0eSchristos if (!to_foreign)
1058*c42dbd0eSchristos {
1059*c42dbd0eSchristos kind = CTF_V2_INFO_KIND (t->ctt_info);
1060*c42dbd0eSchristos size = t->ctt_size;
1061*c42dbd0eSchristos vlen = CTF_V2_INFO_VLEN (t->ctt_info);
1062*c42dbd0eSchristos vbytes = get_vbytes_v2 (fp, kind, size, vlen);
1063*c42dbd0eSchristos }
1064867d70fcSchristos
1065867d70fcSchristos if (_libctf_unlikely_ (size == CTF_LSIZE_SENT))
1066867d70fcSchristos {
1067*c42dbd0eSchristos if (to_foreign)
1068*c42dbd0eSchristos size = CTF_TYPE_LSIZE (t);
1069*c42dbd0eSchristos
1070867d70fcSchristos swap_thing (t->ctt_lsizehi);
1071867d70fcSchristos swap_thing (t->ctt_lsizelo);
1072*c42dbd0eSchristos
1073*c42dbd0eSchristos if (!to_foreign)
1074867d70fcSchristos size = CTF_TYPE_LSIZE (t);
1075*c42dbd0eSchristos
1076867d70fcSchristos t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_type_t));
1077867d70fcSchristos }
1078867d70fcSchristos else
1079867d70fcSchristos t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_stype_t));
1080867d70fcSchristos
1081867d70fcSchristos switch (kind)
1082867d70fcSchristos {
1083867d70fcSchristos case CTF_K_FORWARD:
1084867d70fcSchristos case CTF_K_UNKNOWN:
1085867d70fcSchristos case CTF_K_POINTER:
1086867d70fcSchristos case CTF_K_TYPEDEF:
1087867d70fcSchristos case CTF_K_VOLATILE:
1088867d70fcSchristos case CTF_K_CONST:
1089867d70fcSchristos case CTF_K_RESTRICT:
1090867d70fcSchristos /* These types have no vlen data to swap. */
1091867d70fcSchristos assert (vbytes == 0);
1092867d70fcSchristos break;
1093867d70fcSchristos
1094867d70fcSchristos case CTF_K_INTEGER:
1095867d70fcSchristos case CTF_K_FLOAT:
1096867d70fcSchristos {
1097867d70fcSchristos /* These types have a single uint32_t. */
1098867d70fcSchristos
1099867d70fcSchristos uint32_t *item = (uint32_t *) t;
1100867d70fcSchristos
1101867d70fcSchristos swap_thing (*item);
1102867d70fcSchristos break;
1103867d70fcSchristos }
1104867d70fcSchristos
1105867d70fcSchristos case CTF_K_FUNCTION:
1106867d70fcSchristos {
1107867d70fcSchristos /* This type has a bunch of uint32_ts. */
1108867d70fcSchristos
1109867d70fcSchristos uint32_t *item = (uint32_t *) t;
1110867d70fcSchristos ssize_t i;
1111867d70fcSchristos
1112867d70fcSchristos for (i = vlen; i > 0; item++, i--)
1113867d70fcSchristos swap_thing (*item);
1114867d70fcSchristos break;
1115867d70fcSchristos }
1116867d70fcSchristos
1117867d70fcSchristos case CTF_K_ARRAY:
1118867d70fcSchristos {
1119867d70fcSchristos /* This has a single ctf_array_t. */
1120867d70fcSchristos
1121867d70fcSchristos ctf_array_t *a = (ctf_array_t *) t;
1122867d70fcSchristos
1123867d70fcSchristos assert (vbytes == sizeof (ctf_array_t));
1124867d70fcSchristos swap_thing (a->cta_contents);
1125867d70fcSchristos swap_thing (a->cta_index);
1126867d70fcSchristos swap_thing (a->cta_nelems);
1127867d70fcSchristos
1128867d70fcSchristos break;
1129867d70fcSchristos }
1130867d70fcSchristos
1131867d70fcSchristos case CTF_K_SLICE:
1132867d70fcSchristos {
1133867d70fcSchristos /* This has a single ctf_slice_t. */
1134867d70fcSchristos
1135867d70fcSchristos ctf_slice_t *s = (ctf_slice_t *) t;
1136867d70fcSchristos
1137867d70fcSchristos assert (vbytes == sizeof (ctf_slice_t));
1138867d70fcSchristos swap_thing (s->cts_type);
1139867d70fcSchristos swap_thing (s->cts_offset);
1140867d70fcSchristos swap_thing (s->cts_bits);
1141867d70fcSchristos
1142867d70fcSchristos break;
1143867d70fcSchristos }
1144867d70fcSchristos
1145867d70fcSchristos case CTF_K_STRUCT:
1146867d70fcSchristos case CTF_K_UNION:
1147867d70fcSchristos {
1148867d70fcSchristos /* This has an array of ctf_member or ctf_lmember, depending on
1149867d70fcSchristos size. We could consider it to be a simple array of uint32_t,
1150867d70fcSchristos but for safety's sake in case these structures ever acquire
1151867d70fcSchristos non-uint32_t members, do it member by member. */
1152867d70fcSchristos
1153867d70fcSchristos if (_libctf_unlikely_ (size >= CTF_LSTRUCT_THRESH))
1154867d70fcSchristos {
1155867d70fcSchristos ctf_lmember_t *lm = (ctf_lmember_t *) t;
1156867d70fcSchristos ssize_t i;
1157867d70fcSchristos for (i = vlen; i > 0; i--, lm++)
1158867d70fcSchristos {
1159867d70fcSchristos swap_thing (lm->ctlm_name);
1160867d70fcSchristos swap_thing (lm->ctlm_offsethi);
1161867d70fcSchristos swap_thing (lm->ctlm_type);
1162867d70fcSchristos swap_thing (lm->ctlm_offsetlo);
1163867d70fcSchristos }
1164867d70fcSchristos }
1165867d70fcSchristos else
1166867d70fcSchristos {
1167867d70fcSchristos ctf_member_t *m = (ctf_member_t *) t;
1168867d70fcSchristos ssize_t i;
1169867d70fcSchristos for (i = vlen; i > 0; i--, m++)
1170867d70fcSchristos {
1171867d70fcSchristos swap_thing (m->ctm_name);
1172867d70fcSchristos swap_thing (m->ctm_offset);
1173867d70fcSchristos swap_thing (m->ctm_type);
1174867d70fcSchristos }
1175867d70fcSchristos }
1176867d70fcSchristos break;
1177867d70fcSchristos }
1178867d70fcSchristos
1179867d70fcSchristos case CTF_K_ENUM:
1180867d70fcSchristos {
1181867d70fcSchristos /* This has an array of ctf_enum_t. */
1182867d70fcSchristos
1183867d70fcSchristos ctf_enum_t *item = (ctf_enum_t *) t;
1184867d70fcSchristos ssize_t i;
1185867d70fcSchristos
1186867d70fcSchristos for (i = vlen; i > 0; item++, i--)
1187867d70fcSchristos {
1188867d70fcSchristos swap_thing (item->cte_name);
1189867d70fcSchristos swap_thing (item->cte_value);
1190867d70fcSchristos }
1191867d70fcSchristos break;
1192867d70fcSchristos }
1193867d70fcSchristos default:
1194*c42dbd0eSchristos ctf_err_warn (fp, 0, ECTF_CORRUPT,
1195*c42dbd0eSchristos _("unhandled CTF kind in endianness conversion: %x"),
1196867d70fcSchristos kind);
1197867d70fcSchristos return ECTF_CORRUPT;
1198867d70fcSchristos }
1199867d70fcSchristos
1200867d70fcSchristos t = (ctf_type_t *) ((uintptr_t) t + vbytes);
1201867d70fcSchristos }
1202867d70fcSchristos
1203867d70fcSchristos return 0;
1204867d70fcSchristos }
1205867d70fcSchristos
1206867d70fcSchristos /* Flip the endianness of BUF, given the offsets in the (already endian-
1207*c42dbd0eSchristos converted) CTH. If TO_FOREIGN is set, flip to foreign-endianness; if not,
1208*c42dbd0eSchristos flip away.
1209867d70fcSchristos
1210867d70fcSchristos All of this stuff happens before the header is fully initialized, so the
1211867d70fcSchristos LCTF_*() macros cannot be used yet. Since we do not try to endian-convert v1
1212867d70fcSchristos data, this is no real loss. */
1213867d70fcSchristos
1214*c42dbd0eSchristos int
ctf_flip(ctf_dict_t * fp,ctf_header_t * cth,unsigned char * buf,int to_foreign)1215*c42dbd0eSchristos ctf_flip (ctf_dict_t *fp, ctf_header_t *cth, unsigned char *buf,
1216*c42dbd0eSchristos int to_foreign)
1217867d70fcSchristos {
1218*c42dbd0eSchristos ctf_dprintf("flipping endianness\n");
1219*c42dbd0eSchristos
1220867d70fcSchristos flip_lbls (buf + cth->cth_lbloff, cth->cth_objtoff - cth->cth_lbloff);
1221867d70fcSchristos flip_objts (buf + cth->cth_objtoff, cth->cth_funcoff - cth->cth_objtoff);
1222867d70fcSchristos flip_objts (buf + cth->cth_funcoff, cth->cth_objtidxoff - cth->cth_funcoff);
1223867d70fcSchristos flip_objts (buf + cth->cth_objtidxoff, cth->cth_funcidxoff - cth->cth_objtidxoff);
1224867d70fcSchristos flip_objts (buf + cth->cth_funcidxoff, cth->cth_varoff - cth->cth_funcidxoff);
1225867d70fcSchristos flip_vars (buf + cth->cth_varoff, cth->cth_typeoff - cth->cth_varoff);
1226*c42dbd0eSchristos return flip_types (fp, buf + cth->cth_typeoff,
1227*c42dbd0eSchristos cth->cth_stroff - cth->cth_typeoff, to_foreign);
1228867d70fcSchristos }
1229867d70fcSchristos
1230*c42dbd0eSchristos /* Set up the ctl hashes in a ctf_dict_t. Called by both writable and
1231867d70fcSchristos non-writable dictionary initialization. */
ctf_set_ctl_hashes(ctf_dict_t * fp)1232*c42dbd0eSchristos void ctf_set_ctl_hashes (ctf_dict_t *fp)
1233867d70fcSchristos {
1234867d70fcSchristos /* Initialize the ctf_lookup_by_name top-level dictionary. We keep an
1235867d70fcSchristos array of type name prefixes and the corresponding ctf_hash to use. */
1236867d70fcSchristos fp->ctf_lookups[0].ctl_prefix = "struct";
1237867d70fcSchristos fp->ctf_lookups[0].ctl_len = strlen (fp->ctf_lookups[0].ctl_prefix);
1238867d70fcSchristos fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
1239867d70fcSchristos fp->ctf_lookups[1].ctl_prefix = "union";
1240867d70fcSchristos fp->ctf_lookups[1].ctl_len = strlen (fp->ctf_lookups[1].ctl_prefix);
1241867d70fcSchristos fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
1242867d70fcSchristos fp->ctf_lookups[2].ctl_prefix = "enum";
1243867d70fcSchristos fp->ctf_lookups[2].ctl_len = strlen (fp->ctf_lookups[2].ctl_prefix);
1244867d70fcSchristos fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
1245867d70fcSchristos fp->ctf_lookups[3].ctl_prefix = _CTF_NULLSTR;
1246867d70fcSchristos fp->ctf_lookups[3].ctl_len = strlen (fp->ctf_lookups[3].ctl_prefix);
1247867d70fcSchristos fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
1248867d70fcSchristos fp->ctf_lookups[4].ctl_prefix = NULL;
1249867d70fcSchristos fp->ctf_lookups[4].ctl_len = 0;
1250867d70fcSchristos fp->ctf_lookups[4].ctl_hash = NULL;
1251867d70fcSchristos }
1252867d70fcSchristos
1253867d70fcSchristos /* Open a CTF file, mocking up a suitable ctf_sect. */
1254867d70fcSchristos
ctf_simple_open(const char * ctfsect,size_t ctfsect_size,const char * symsect,size_t symsect_size,size_t symsect_entsize,const char * strsect,size_t strsect_size,int * errp)1255*c42dbd0eSchristos ctf_dict_t *ctf_simple_open (const char *ctfsect, size_t ctfsect_size,
1256867d70fcSchristos const char *symsect, size_t symsect_size,
1257867d70fcSchristos size_t symsect_entsize,
1258867d70fcSchristos const char *strsect, size_t strsect_size,
1259867d70fcSchristos int *errp)
1260867d70fcSchristos {
1261867d70fcSchristos return ctf_simple_open_internal (ctfsect, ctfsect_size, symsect, symsect_size,
1262867d70fcSchristos symsect_entsize, strsect, strsect_size, NULL,
1263867d70fcSchristos 0, errp);
1264867d70fcSchristos }
1265867d70fcSchristos
1266867d70fcSchristos /* Open a CTF file, mocking up a suitable ctf_sect and overriding the external
1267867d70fcSchristos strtab with a synthetic one. */
1268867d70fcSchristos
ctf_simple_open_internal(const char * ctfsect,size_t ctfsect_size,const char * symsect,size_t symsect_size,size_t symsect_entsize,const char * strsect,size_t strsect_size,ctf_dynhash_t * syn_strtab,int writable,int * errp)1269*c42dbd0eSchristos ctf_dict_t *ctf_simple_open_internal (const char *ctfsect, size_t ctfsect_size,
1270867d70fcSchristos const char *symsect, size_t symsect_size,
1271867d70fcSchristos size_t symsect_entsize,
1272867d70fcSchristos const char *strsect, size_t strsect_size,
1273867d70fcSchristos ctf_dynhash_t *syn_strtab, int writable,
1274867d70fcSchristos int *errp)
1275867d70fcSchristos {
1276867d70fcSchristos ctf_sect_t skeleton;
1277867d70fcSchristos
1278867d70fcSchristos ctf_sect_t ctf_sect, sym_sect, str_sect;
1279867d70fcSchristos ctf_sect_t *ctfsectp = NULL;
1280867d70fcSchristos ctf_sect_t *symsectp = NULL;
1281867d70fcSchristos ctf_sect_t *strsectp = NULL;
1282867d70fcSchristos
1283867d70fcSchristos skeleton.cts_name = _CTF_SECTION;
1284867d70fcSchristos skeleton.cts_entsize = 1;
1285867d70fcSchristos
1286867d70fcSchristos if (ctfsect)
1287867d70fcSchristos {
1288867d70fcSchristos memcpy (&ctf_sect, &skeleton, sizeof (struct ctf_sect));
1289867d70fcSchristos ctf_sect.cts_data = ctfsect;
1290867d70fcSchristos ctf_sect.cts_size = ctfsect_size;
1291867d70fcSchristos ctfsectp = &ctf_sect;
1292867d70fcSchristos }
1293867d70fcSchristos
1294867d70fcSchristos if (symsect)
1295867d70fcSchristos {
1296867d70fcSchristos memcpy (&sym_sect, &skeleton, sizeof (struct ctf_sect));
1297867d70fcSchristos sym_sect.cts_data = symsect;
1298867d70fcSchristos sym_sect.cts_size = symsect_size;
1299867d70fcSchristos sym_sect.cts_entsize = symsect_entsize;
1300867d70fcSchristos symsectp = &sym_sect;
1301867d70fcSchristos }
1302867d70fcSchristos
1303867d70fcSchristos if (strsect)
1304867d70fcSchristos {
1305867d70fcSchristos memcpy (&str_sect, &skeleton, sizeof (struct ctf_sect));
1306867d70fcSchristos str_sect.cts_data = strsect;
1307867d70fcSchristos str_sect.cts_size = strsect_size;
1308867d70fcSchristos strsectp = &str_sect;
1309867d70fcSchristos }
1310867d70fcSchristos
1311867d70fcSchristos return ctf_bufopen_internal (ctfsectp, symsectp, strsectp, syn_strtab,
1312867d70fcSchristos writable, errp);
1313867d70fcSchristos }
1314867d70fcSchristos
1315867d70fcSchristos /* Decode the specified CTF buffer and optional symbol table, and create a new
1316*c42dbd0eSchristos CTF dict representing the symbolic debugging information. This code can
1317867d70fcSchristos be used directly by the debugger, or it can be used as the engine for
1318867d70fcSchristos ctf_fdopen() or ctf_open(), below. */
1319867d70fcSchristos
1320*c42dbd0eSchristos ctf_dict_t *
ctf_bufopen(const ctf_sect_t * ctfsect,const ctf_sect_t * symsect,const ctf_sect_t * strsect,int * errp)1321867d70fcSchristos ctf_bufopen (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
1322867d70fcSchristos const ctf_sect_t *strsect, int *errp)
1323867d70fcSchristos {
1324867d70fcSchristos return ctf_bufopen_internal (ctfsect, symsect, strsect, NULL, 0, errp);
1325867d70fcSchristos }
1326867d70fcSchristos
1327867d70fcSchristos /* Like ctf_bufopen, but overriding the external strtab with a synthetic one. */
1328867d70fcSchristos
1329*c42dbd0eSchristos ctf_dict_t *
ctf_bufopen_internal(const ctf_sect_t * ctfsect,const ctf_sect_t * symsect,const ctf_sect_t * strsect,ctf_dynhash_t * syn_strtab,int writable,int * errp)1330867d70fcSchristos ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
1331867d70fcSchristos const ctf_sect_t *strsect, ctf_dynhash_t *syn_strtab,
1332867d70fcSchristos int writable, int *errp)
1333867d70fcSchristos {
1334867d70fcSchristos const ctf_preamble_t *pp;
1335867d70fcSchristos size_t hdrsz = sizeof (ctf_header_t);
1336867d70fcSchristos ctf_header_t *hp;
1337*c42dbd0eSchristos ctf_dict_t *fp;
1338867d70fcSchristos int foreign_endian = 0;
1339867d70fcSchristos int err;
1340867d70fcSchristos
1341867d70fcSchristos libctf_init_debug();
1342867d70fcSchristos
1343867d70fcSchristos if ((ctfsect == NULL) || ((symsect != NULL) &&
1344867d70fcSchristos ((strsect == NULL) && syn_strtab == NULL)))
1345867d70fcSchristos return (ctf_set_open_errno (errp, EINVAL));
1346867d70fcSchristos
1347867d70fcSchristos if (symsect != NULL && symsect->cts_entsize != sizeof (Elf32_Sym) &&
1348867d70fcSchristos symsect->cts_entsize != sizeof (Elf64_Sym))
1349867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_SYMTAB));
1350867d70fcSchristos
1351867d70fcSchristos if (symsect != NULL && symsect->cts_data == NULL)
1352867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_SYMBAD));
1353867d70fcSchristos
1354867d70fcSchristos if (strsect != NULL && strsect->cts_data == NULL)
1355867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_STRBAD));
1356867d70fcSchristos
1357867d70fcSchristos if (ctfsect->cts_size < sizeof (ctf_preamble_t))
1358867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
1359867d70fcSchristos
1360867d70fcSchristos pp = (const ctf_preamble_t *) ctfsect->cts_data;
1361867d70fcSchristos
1362867d70fcSchristos ctf_dprintf ("ctf_bufopen: magic=0x%x version=%u\n",
1363867d70fcSchristos pp->ctp_magic, pp->ctp_version);
1364867d70fcSchristos
1365867d70fcSchristos /* Validate each part of the CTF header.
1366867d70fcSchristos
1367867d70fcSchristos First, we validate the preamble (common to all versions). At that point,
1368867d70fcSchristos we know the endianness and specific header version, and can validate the
1369867d70fcSchristos version-specific parts including section offsets and alignments.
1370867d70fcSchristos
1371867d70fcSchristos We specifically do not support foreign-endian old versions. */
1372867d70fcSchristos
1373867d70fcSchristos if (_libctf_unlikely_ (pp->ctp_magic != CTF_MAGIC))
1374867d70fcSchristos {
1375867d70fcSchristos if (pp->ctp_magic == bswap_16 (CTF_MAGIC))
1376867d70fcSchristos {
1377867d70fcSchristos if (pp->ctp_version != CTF_VERSION_3)
1378867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_CTFVERS));
1379867d70fcSchristos foreign_endian = 1;
1380867d70fcSchristos }
1381867d70fcSchristos else
1382867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
1383867d70fcSchristos }
1384867d70fcSchristos
1385867d70fcSchristos if (_libctf_unlikely_ ((pp->ctp_version < CTF_VERSION_1)
1386867d70fcSchristos || (pp->ctp_version > CTF_VERSION_3)))
1387867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_CTFVERS));
1388867d70fcSchristos
1389867d70fcSchristos if ((symsect != NULL) && (pp->ctp_version < CTF_VERSION_2))
1390867d70fcSchristos {
1391867d70fcSchristos /* The symtab can contain function entries which contain embedded ctf
1392867d70fcSchristos info. We do not support dynamically upgrading such entries (none
1393867d70fcSchristos should exist in any case, since dwarf2ctf does not create them). */
1394867d70fcSchristos
1395*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_NOTSUP, _("ctf_bufopen: CTF version %d "
1396*c42dbd0eSchristos "symsect not supported"),
1397*c42dbd0eSchristos pp->ctp_version);
1398867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_NOTSUP));
1399867d70fcSchristos }
1400867d70fcSchristos
1401867d70fcSchristos if (pp->ctp_version < CTF_VERSION_3)
1402867d70fcSchristos hdrsz = sizeof (ctf_header_v2_t);
1403867d70fcSchristos
1404*c42dbd0eSchristos if (_libctf_unlikely_ (pp->ctp_flags > CTF_F_MAX))
1405*c42dbd0eSchristos {
1406*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_FLAGS, _("ctf_bufopen: invalid header "
1407*c42dbd0eSchristos "flags: %x"),
1408*c42dbd0eSchristos (unsigned int) pp->ctp_flags);
1409*c42dbd0eSchristos return (ctf_set_open_errno (errp, ECTF_FLAGS));
1410*c42dbd0eSchristos }
1411*c42dbd0eSchristos
1412867d70fcSchristos if (ctfsect->cts_size < hdrsz)
1413867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_NOCTFBUF));
1414867d70fcSchristos
1415*c42dbd0eSchristos if ((fp = malloc (sizeof (ctf_dict_t))) == NULL)
1416867d70fcSchristos return (ctf_set_open_errno (errp, ENOMEM));
1417867d70fcSchristos
1418*c42dbd0eSchristos memset (fp, 0, sizeof (ctf_dict_t));
1419867d70fcSchristos
1420867d70fcSchristos if (writable)
1421867d70fcSchristos fp->ctf_flags |= LCTF_RDWR;
1422867d70fcSchristos
1423867d70fcSchristos if ((fp->ctf_header = malloc (sizeof (struct ctf_header))) == NULL)
1424867d70fcSchristos {
1425867d70fcSchristos free (fp);
1426867d70fcSchristos return (ctf_set_open_errno (errp, ENOMEM));
1427867d70fcSchristos }
1428867d70fcSchristos hp = fp->ctf_header;
1429867d70fcSchristos memcpy (hp, ctfsect->cts_data, hdrsz);
1430867d70fcSchristos if (pp->ctp_version < CTF_VERSION_3)
1431867d70fcSchristos upgrade_header (hp);
1432867d70fcSchristos
1433867d70fcSchristos if (foreign_endian)
1434*c42dbd0eSchristos ctf_flip_header (hp);
1435867d70fcSchristos fp->ctf_openflags = hp->cth_flags;
1436867d70fcSchristos fp->ctf_size = hp->cth_stroff + hp->cth_strlen;
1437867d70fcSchristos
1438867d70fcSchristos ctf_dprintf ("ctf_bufopen: uncompressed size=%lu\n",
1439867d70fcSchristos (unsigned long) fp->ctf_size);
1440867d70fcSchristos
1441867d70fcSchristos if (hp->cth_lbloff > fp->ctf_size || hp->cth_objtoff > fp->ctf_size
1442867d70fcSchristos || hp->cth_funcoff > fp->ctf_size || hp->cth_objtidxoff > fp->ctf_size
1443867d70fcSchristos || hp->cth_funcidxoff > fp->ctf_size || hp->cth_typeoff > fp->ctf_size
1444867d70fcSchristos || hp->cth_stroff > fp->ctf_size)
1445*c42dbd0eSchristos {
1446*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT, _("header offset exceeds CTF size"));
1447867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_CORRUPT));
1448*c42dbd0eSchristos }
1449867d70fcSchristos
1450867d70fcSchristos if (hp->cth_lbloff > hp->cth_objtoff
1451867d70fcSchristos || hp->cth_objtoff > hp->cth_funcoff
1452867d70fcSchristos || hp->cth_funcoff > hp->cth_typeoff
1453867d70fcSchristos || hp->cth_funcoff > hp->cth_objtidxoff
1454867d70fcSchristos || hp->cth_objtidxoff > hp->cth_funcidxoff
1455867d70fcSchristos || hp->cth_funcidxoff > hp->cth_varoff
1456867d70fcSchristos || hp->cth_varoff > hp->cth_typeoff || hp->cth_typeoff > hp->cth_stroff)
1457*c42dbd0eSchristos {
1458*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT, _("overlapping CTF sections"));
1459867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_CORRUPT));
1460*c42dbd0eSchristos }
1461867d70fcSchristos
1462867d70fcSchristos if ((hp->cth_lbloff & 3) || (hp->cth_objtoff & 2)
1463867d70fcSchristos || (hp->cth_funcoff & 2) || (hp->cth_objtidxoff & 2)
1464867d70fcSchristos || (hp->cth_funcidxoff & 2) || (hp->cth_varoff & 3)
1465867d70fcSchristos || (hp->cth_typeoff & 3))
1466*c42dbd0eSchristos {
1467*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT,
1468*c42dbd0eSchristos _("CTF sections not properly aligned"));
1469867d70fcSchristos return (ctf_set_open_errno (errp, ECTF_CORRUPT));
1470*c42dbd0eSchristos }
1471*c42dbd0eSchristos
1472*c42dbd0eSchristos /* This invariant will be lifted in v4, but for now it is true. */
1473*c42dbd0eSchristos
1474*c42dbd0eSchristos if ((hp->cth_funcidxoff - hp->cth_objtidxoff != 0) &&
1475*c42dbd0eSchristos (hp->cth_funcidxoff - hp->cth_objtidxoff
1476*c42dbd0eSchristos != hp->cth_funcoff - hp->cth_objtoff))
1477*c42dbd0eSchristos {
1478*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT,
1479*c42dbd0eSchristos _("Object index section is neither empty nor the "
1480*c42dbd0eSchristos "same length as the object section: %u versus %u "
1481*c42dbd0eSchristos "bytes"), hp->cth_funcoff - hp->cth_objtoff,
1482*c42dbd0eSchristos hp->cth_funcidxoff - hp->cth_objtidxoff);
1483*c42dbd0eSchristos return (ctf_set_open_errno (errp, ECTF_CORRUPT));
1484*c42dbd0eSchristos }
1485*c42dbd0eSchristos
1486*c42dbd0eSchristos if ((hp->cth_varoff - hp->cth_funcidxoff != 0) &&
1487*c42dbd0eSchristos (hp->cth_varoff - hp->cth_funcidxoff
1488*c42dbd0eSchristos != hp->cth_objtidxoff - hp->cth_funcoff) &&
1489*c42dbd0eSchristos (hp->cth_flags & CTF_F_NEWFUNCINFO))
1490*c42dbd0eSchristos {
1491*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT,
1492*c42dbd0eSchristos _("Function index section is neither empty nor the "
1493*c42dbd0eSchristos "same length as the function section: %u versus %u "
1494*c42dbd0eSchristos "bytes"), hp->cth_objtidxoff - hp->cth_funcoff,
1495*c42dbd0eSchristos hp->cth_varoff - hp->cth_funcidxoff);
1496*c42dbd0eSchristos return (ctf_set_open_errno (errp, ECTF_CORRUPT));
1497*c42dbd0eSchristos }
1498867d70fcSchristos
1499867d70fcSchristos /* Once everything is determined to be valid, attempt to decompress the CTF
1500867d70fcSchristos data buffer if it is compressed, or copy it into new storage if it is not
1501867d70fcSchristos compressed but needs endian-flipping. Otherwise we just put the data
1502867d70fcSchristos section's buffer pointer into ctf_buf, below. */
1503867d70fcSchristos
1504867d70fcSchristos /* Note: if this is a v1 buffer, it will be reallocated and expanded by
1505867d70fcSchristos init_types(). */
1506867d70fcSchristos
1507867d70fcSchristos if (hp->cth_flags & CTF_F_COMPRESS)
1508867d70fcSchristos {
1509867d70fcSchristos size_t srclen;
1510867d70fcSchristos uLongf dstlen;
1511867d70fcSchristos const void *src;
1512867d70fcSchristos int rc = Z_OK;
1513867d70fcSchristos
1514867d70fcSchristos /* We are allocating this ourselves, so we can drop the ctf header
1515867d70fcSchristos copy in favour of ctf->ctf_header. */
1516867d70fcSchristos
1517867d70fcSchristos if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
1518867d70fcSchristos {
1519867d70fcSchristos err = ECTF_ZALLOC;
1520867d70fcSchristos goto bad;
1521867d70fcSchristos }
1522867d70fcSchristos fp->ctf_dynbase = fp->ctf_base;
1523867d70fcSchristos hp->cth_flags &= ~CTF_F_COMPRESS;
1524867d70fcSchristos
1525867d70fcSchristos src = (unsigned char *) ctfsect->cts_data + hdrsz;
1526867d70fcSchristos srclen = ctfsect->cts_size - hdrsz;
1527867d70fcSchristos dstlen = fp->ctf_size;
1528867d70fcSchristos fp->ctf_buf = fp->ctf_base;
1529867d70fcSchristos
1530867d70fcSchristos if ((rc = uncompress (fp->ctf_base, &dstlen, src, srclen)) != Z_OK)
1531867d70fcSchristos {
1532*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_DECOMPRESS, _("zlib inflate err: %s"),
1533*c42dbd0eSchristos zError (rc));
1534867d70fcSchristos err = ECTF_DECOMPRESS;
1535867d70fcSchristos goto bad;
1536867d70fcSchristos }
1537867d70fcSchristos
1538867d70fcSchristos if ((size_t) dstlen != fp->ctf_size)
1539867d70fcSchristos {
1540*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT,
1541*c42dbd0eSchristos _("zlib inflate short: got %lu of %lu bytes"),
1542*c42dbd0eSchristos (unsigned long) dstlen, (unsigned long) fp->ctf_size);
1543867d70fcSchristos err = ECTF_CORRUPT;
1544867d70fcSchristos goto bad;
1545867d70fcSchristos }
1546867d70fcSchristos }
1547*c42dbd0eSchristos else
1548*c42dbd0eSchristos {
1549*c42dbd0eSchristos if (_libctf_unlikely_ (ctfsect->cts_size < hdrsz + fp->ctf_size))
1550*c42dbd0eSchristos {
1551*c42dbd0eSchristos ctf_err_warn (NULL, 0, ECTF_CORRUPT,
1552*c42dbd0eSchristos _("%lu byte long CTF dictionary overruns %lu byte long CTF section"),
1553*c42dbd0eSchristos (unsigned long) ctfsect->cts_size,
1554*c42dbd0eSchristos (unsigned long) (hdrsz + fp->ctf_size));
1555*c42dbd0eSchristos err = ECTF_CORRUPT;
1556*c42dbd0eSchristos goto bad;
1557*c42dbd0eSchristos }
1558*c42dbd0eSchristos
1559*c42dbd0eSchristos if (foreign_endian)
1560867d70fcSchristos {
1561867d70fcSchristos if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
1562867d70fcSchristos {
1563867d70fcSchristos err = ECTF_ZALLOC;
1564867d70fcSchristos goto bad;
1565867d70fcSchristos }
1566867d70fcSchristos fp->ctf_dynbase = fp->ctf_base;
1567867d70fcSchristos memcpy (fp->ctf_base, ((unsigned char *) ctfsect->cts_data) + hdrsz,
1568867d70fcSchristos fp->ctf_size);
1569867d70fcSchristos fp->ctf_buf = fp->ctf_base;
1570867d70fcSchristos }
1571867d70fcSchristos else
1572867d70fcSchristos {
1573*c42dbd0eSchristos /* We are just using the section passed in -- but its header may
1574*c42dbd0eSchristos be an old version. Point ctf_buf past the old header, and
1575*c42dbd0eSchristos never touch it again. */
1576867d70fcSchristos fp->ctf_base = (unsigned char *) ctfsect->cts_data;
1577867d70fcSchristos fp->ctf_dynbase = NULL;
1578867d70fcSchristos fp->ctf_buf = fp->ctf_base + hdrsz;
1579867d70fcSchristos }
1580*c42dbd0eSchristos }
1581867d70fcSchristos
1582867d70fcSchristos /* Once we have uncompressed and validated the CTF data buffer, we can
1583*c42dbd0eSchristos proceed with initializing the ctf_dict_t we allocated above.
1584867d70fcSchristos
1585867d70fcSchristos Nothing that depends on buf or base should be set directly in this function
1586867d70fcSchristos before the init_types() call, because it may be reallocated during
1587867d70fcSchristos transparent upgrade if this recension of libctf is so configured: see
1588867d70fcSchristos ctf_set_base(). */
1589867d70fcSchristos
1590867d70fcSchristos ctf_set_version (fp, hp, hp->cth_version);
1591*c42dbd0eSchristos if (ctf_str_create_atoms (fp) < 0)
1592*c42dbd0eSchristos {
1593*c42dbd0eSchristos err = ENOMEM;
1594*c42dbd0eSchristos goto bad;
1595*c42dbd0eSchristos }
1596*c42dbd0eSchristos
1597867d70fcSchristos fp->ctf_parmax = CTF_MAX_PTYPE;
1598867d70fcSchristos memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
1599867d70fcSchristos
1600867d70fcSchristos if (symsect != NULL)
1601867d70fcSchristos {
1602867d70fcSchristos memcpy (&fp->ctf_symtab, symsect, sizeof (ctf_sect_t));
1603867d70fcSchristos memcpy (&fp->ctf_strtab, strsect, sizeof (ctf_sect_t));
1604867d70fcSchristos }
1605867d70fcSchristos
1606867d70fcSchristos if (fp->ctf_data.cts_name != NULL)
1607867d70fcSchristos if ((fp->ctf_data.cts_name = strdup (fp->ctf_data.cts_name)) == NULL)
1608867d70fcSchristos {
1609867d70fcSchristos err = ENOMEM;
1610867d70fcSchristos goto bad;
1611867d70fcSchristos }
1612867d70fcSchristos if (fp->ctf_symtab.cts_name != NULL)
1613867d70fcSchristos if ((fp->ctf_symtab.cts_name = strdup (fp->ctf_symtab.cts_name)) == NULL)
1614867d70fcSchristos {
1615867d70fcSchristos err = ENOMEM;
1616867d70fcSchristos goto bad;
1617867d70fcSchristos }
1618867d70fcSchristos if (fp->ctf_strtab.cts_name != NULL)
1619867d70fcSchristos if ((fp->ctf_strtab.cts_name = strdup (fp->ctf_strtab.cts_name)) == NULL)
1620867d70fcSchristos {
1621867d70fcSchristos err = ENOMEM;
1622867d70fcSchristos goto bad;
1623867d70fcSchristos }
1624867d70fcSchristos
1625867d70fcSchristos if (fp->ctf_data.cts_name == NULL)
1626867d70fcSchristos fp->ctf_data.cts_name = _CTF_NULLSTR;
1627867d70fcSchristos if (fp->ctf_symtab.cts_name == NULL)
1628867d70fcSchristos fp->ctf_symtab.cts_name = _CTF_NULLSTR;
1629867d70fcSchristos if (fp->ctf_strtab.cts_name == NULL)
1630867d70fcSchristos fp->ctf_strtab.cts_name = _CTF_NULLSTR;
1631867d70fcSchristos
1632867d70fcSchristos if (strsect != NULL)
1633867d70fcSchristos {
1634867d70fcSchristos fp->ctf_str[CTF_STRTAB_1].cts_strs = strsect->cts_data;
1635867d70fcSchristos fp->ctf_str[CTF_STRTAB_1].cts_len = strsect->cts_size;
1636867d70fcSchristos }
1637867d70fcSchristos fp->ctf_syn_ext_strtab = syn_strtab;
1638867d70fcSchristos
1639867d70fcSchristos if (foreign_endian &&
1640*c42dbd0eSchristos (err = ctf_flip (fp, hp, fp->ctf_buf, 0)) != 0)
1641867d70fcSchristos {
1642*c42dbd0eSchristos /* We can be certain that ctf_flip() will have endian-flipped everything
1643867d70fcSchristos other than the types table when we return. In particular the header
1644867d70fcSchristos is fine, so set it, to allow freeing to use the usual code path. */
1645867d70fcSchristos
1646867d70fcSchristos ctf_set_base (fp, hp, fp->ctf_base);
1647867d70fcSchristos goto bad;
1648867d70fcSchristos }
1649867d70fcSchristos
1650867d70fcSchristos ctf_set_base (fp, hp, fp->ctf_base);
1651867d70fcSchristos
1652*c42dbd0eSchristos /* No need to do anything else for dynamic dicts: they do not support symbol
1653*c42dbd0eSchristos lookups, and the type table is maintained in the dthashes. */
1654867d70fcSchristos if (fp->ctf_flags & LCTF_RDWR)
1655867d70fcSchristos {
1656867d70fcSchristos fp->ctf_refcnt = 1;
1657867d70fcSchristos return fp;
1658867d70fcSchristos }
1659867d70fcSchristos
1660867d70fcSchristos if ((err = init_types (fp, hp)) != 0)
1661867d70fcSchristos goto bad;
1662867d70fcSchristos
1663*c42dbd0eSchristos /* Allocate and initialize the symtab translation table, pointed to by
1664*c42dbd0eSchristos ctf_sxlate, and the corresponding index sections. This table may be too
1665*c42dbd0eSchristos large for the actual size of the object and function info sections: if so,
1666*c42dbd0eSchristos ctf_nsyms will be adjusted and the excess will never be used. It's
1667*c42dbd0eSchristos possible to do indexed symbol lookups even without a symbol table, so check
1668*c42dbd0eSchristos even in that case. Initially, we assume the symtab is native-endian: if it
1669*c42dbd0eSchristos isn't, the caller will inform us later by calling ctf_symsect_endianness. */
1670*c42dbd0eSchristos #ifdef WORDS_BIGENDIAN
1671*c42dbd0eSchristos fp->ctf_symsect_little_endian = 0;
1672*c42dbd0eSchristos #else
1673*c42dbd0eSchristos fp->ctf_symsect_little_endian = 1;
1674*c42dbd0eSchristos #endif
1675867d70fcSchristos
1676867d70fcSchristos if (symsect != NULL)
1677867d70fcSchristos {
1678867d70fcSchristos fp->ctf_nsyms = symsect->cts_size / symsect->cts_entsize;
1679867d70fcSchristos fp->ctf_sxlate = malloc (fp->ctf_nsyms * sizeof (uint32_t));
1680867d70fcSchristos
1681867d70fcSchristos if (fp->ctf_sxlate == NULL)
1682867d70fcSchristos {
1683867d70fcSchristos err = ENOMEM;
1684867d70fcSchristos goto bad;
1685867d70fcSchristos }
1686867d70fcSchristos }
1687867d70fcSchristos
1688*c42dbd0eSchristos if ((err = init_symtab (fp, hp, symsect)) != 0)
1689*c42dbd0eSchristos goto bad;
1690*c42dbd0eSchristos
1691867d70fcSchristos ctf_set_ctl_hashes (fp);
1692867d70fcSchristos
1693867d70fcSchristos if (symsect != NULL)
1694867d70fcSchristos {
1695867d70fcSchristos if (symsect->cts_entsize == sizeof (Elf64_Sym))
1696867d70fcSchristos (void) ctf_setmodel (fp, CTF_MODEL_LP64);
1697867d70fcSchristos else
1698867d70fcSchristos (void) ctf_setmodel (fp, CTF_MODEL_ILP32);
1699867d70fcSchristos }
1700867d70fcSchristos else
1701867d70fcSchristos (void) ctf_setmodel (fp, CTF_MODEL_NATIVE);
1702867d70fcSchristos
1703867d70fcSchristos fp->ctf_refcnt = 1;
1704867d70fcSchristos return fp;
1705867d70fcSchristos
1706867d70fcSchristos bad:
1707867d70fcSchristos ctf_set_open_errno (errp, err);
1708*c42dbd0eSchristos ctf_err_warn_to_open (fp);
1709*c42dbd0eSchristos ctf_dict_close (fp);
1710867d70fcSchristos return NULL;
1711867d70fcSchristos }
1712867d70fcSchristos
1713*c42dbd0eSchristos /* Bump the refcount on the specified CTF dict, to allow export of ctf_dict_t's
1714*c42dbd0eSchristos from iterators that open and close the ctf_dict_t around the loop. (This
1715*c42dbd0eSchristos does not extend their lifetime beyond that of the ctf_archive_t in which they
1716*c42dbd0eSchristos are contained.) */
1717867d70fcSchristos
1718867d70fcSchristos void
ctf_ref(ctf_dict_t * fp)1719*c42dbd0eSchristos ctf_ref (ctf_dict_t *fp)
1720*c42dbd0eSchristos {
1721*c42dbd0eSchristos fp->ctf_refcnt++;
1722*c42dbd0eSchristos }
1723*c42dbd0eSchristos
1724*c42dbd0eSchristos /* Close the specified CTF dict and free associated data structures. Note that
1725*c42dbd0eSchristos ctf_dict_close() is a reference counted operation: if the specified file is
1726*c42dbd0eSchristos the parent of other active dict, its reference count will be greater than one
1727*c42dbd0eSchristos and it will be freed later when no active children exist. */
1728*c42dbd0eSchristos
1729*c42dbd0eSchristos void
ctf_dict_close(ctf_dict_t * fp)1730*c42dbd0eSchristos ctf_dict_close (ctf_dict_t *fp)
1731867d70fcSchristos {
1732867d70fcSchristos ctf_dtdef_t *dtd, *ntd;
1733867d70fcSchristos ctf_dvdef_t *dvd, *nvd;
1734*c42dbd0eSchristos ctf_in_flight_dynsym_t *did, *nid;
1735*c42dbd0eSchristos ctf_err_warning_t *err, *nerr;
1736867d70fcSchristos
1737867d70fcSchristos if (fp == NULL)
1738*c42dbd0eSchristos return; /* Allow ctf_dict_close(NULL) to simplify caller code. */
1739867d70fcSchristos
1740*c42dbd0eSchristos ctf_dprintf ("ctf_dict_close(%p) refcnt=%u\n", (void *) fp, fp->ctf_refcnt);
1741867d70fcSchristos
1742867d70fcSchristos if (fp->ctf_refcnt > 1)
1743867d70fcSchristos {
1744867d70fcSchristos fp->ctf_refcnt--;
1745867d70fcSchristos return;
1746867d70fcSchristos }
1747867d70fcSchristos
1748*c42dbd0eSchristos /* It is possible to recurse back in here, notably if dicts in the
1749*c42dbd0eSchristos ctf_link_inputs or ctf_link_outputs cite this dict as a parent without
1750*c42dbd0eSchristos using ctf_import_unref. Do nothing in that case. */
1751*c42dbd0eSchristos if (fp->ctf_refcnt == 0)
1752*c42dbd0eSchristos return;
1753*c42dbd0eSchristos
1754*c42dbd0eSchristos fp->ctf_refcnt--;
1755867d70fcSchristos free (fp->ctf_dyncuname);
1756867d70fcSchristos free (fp->ctf_dynparname);
1757*c42dbd0eSchristos if (fp->ctf_parent && !fp->ctf_parent_unreffed)
1758*c42dbd0eSchristos ctf_dict_close (fp->ctf_parent);
1759867d70fcSchristos
1760867d70fcSchristos for (dtd = ctf_list_next (&fp->ctf_dtdefs); dtd != NULL; dtd = ntd)
1761867d70fcSchristos {
1762867d70fcSchristos ntd = ctf_list_next (dtd);
1763867d70fcSchristos ctf_dtd_delete (fp, dtd);
1764867d70fcSchristos }
1765867d70fcSchristos ctf_dynhash_destroy (fp->ctf_dthash);
1766867d70fcSchristos if (fp->ctf_flags & LCTF_RDWR)
1767867d70fcSchristos {
1768867d70fcSchristos ctf_dynhash_destroy (fp->ctf_structs.ctn_writable);
1769867d70fcSchristos ctf_dynhash_destroy (fp->ctf_unions.ctn_writable);
1770867d70fcSchristos ctf_dynhash_destroy (fp->ctf_enums.ctn_writable);
1771867d70fcSchristos ctf_dynhash_destroy (fp->ctf_names.ctn_writable);
1772867d70fcSchristos }
1773867d70fcSchristos else
1774867d70fcSchristos {
1775867d70fcSchristos ctf_hash_destroy (fp->ctf_structs.ctn_readonly);
1776867d70fcSchristos ctf_hash_destroy (fp->ctf_unions.ctn_readonly);
1777867d70fcSchristos ctf_hash_destroy (fp->ctf_enums.ctn_readonly);
1778867d70fcSchristos ctf_hash_destroy (fp->ctf_names.ctn_readonly);
1779867d70fcSchristos }
1780867d70fcSchristos
1781867d70fcSchristos for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; dvd = nvd)
1782867d70fcSchristos {
1783867d70fcSchristos nvd = ctf_list_next (dvd);
1784867d70fcSchristos ctf_dvd_delete (fp, dvd);
1785867d70fcSchristos }
1786867d70fcSchristos ctf_dynhash_destroy (fp->ctf_dvhash);
1787*c42dbd0eSchristos
1788*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_symhash);
1789*c42dbd0eSchristos free (fp->ctf_funcidx_sxlate);
1790*c42dbd0eSchristos free (fp->ctf_objtidx_sxlate);
1791*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_objthash);
1792*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_funchash);
1793*c42dbd0eSchristos free (fp->ctf_dynsymidx);
1794*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_dynsyms);
1795*c42dbd0eSchristos for (did = ctf_list_next (&fp->ctf_in_flight_dynsyms); did != NULL; did = nid)
1796*c42dbd0eSchristos {
1797*c42dbd0eSchristos nid = ctf_list_next (did);
1798*c42dbd0eSchristos ctf_list_delete (&fp->ctf_in_flight_dynsyms, did);
1799*c42dbd0eSchristos free (did);
1800*c42dbd0eSchristos }
1801*c42dbd0eSchristos
1802867d70fcSchristos ctf_str_free_atoms (fp);
1803867d70fcSchristos free (fp->ctf_tmp_typeslice);
1804867d70fcSchristos
1805867d70fcSchristos if (fp->ctf_data.cts_name != _CTF_NULLSTR)
1806867d70fcSchristos free ((char *) fp->ctf_data.cts_name);
1807867d70fcSchristos
1808867d70fcSchristos if (fp->ctf_symtab.cts_name != _CTF_NULLSTR)
1809867d70fcSchristos free ((char *) fp->ctf_symtab.cts_name);
1810867d70fcSchristos
1811867d70fcSchristos if (fp->ctf_strtab.cts_name != _CTF_NULLSTR)
1812867d70fcSchristos free ((char *) fp->ctf_strtab.cts_name);
1813867d70fcSchristos else if (fp->ctf_data_mmapped)
1814867d70fcSchristos ctf_munmap (fp->ctf_data_mmapped, fp->ctf_data_mmapped_len);
1815867d70fcSchristos
1816867d70fcSchristos free (fp->ctf_dynbase);
1817867d70fcSchristos
1818867d70fcSchristos ctf_dynhash_destroy (fp->ctf_syn_ext_strtab);
1819867d70fcSchristos ctf_dynhash_destroy (fp->ctf_link_inputs);
1820867d70fcSchristos ctf_dynhash_destroy (fp->ctf_link_outputs);
1821867d70fcSchristos ctf_dynhash_destroy (fp->ctf_link_type_mapping);
1822*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_link_in_cu_mapping);
1823*c42dbd0eSchristos ctf_dynhash_destroy (fp->ctf_link_out_cu_mapping);
1824867d70fcSchristos ctf_dynhash_destroy (fp->ctf_add_processing);
1825*c42dbd0eSchristos ctf_dedup_fini (fp, NULL, 0);
1826*c42dbd0eSchristos ctf_dynset_destroy (fp->ctf_dedup_atoms_alloc);
1827*c42dbd0eSchristos
1828*c42dbd0eSchristos for (err = ctf_list_next (&fp->ctf_errs_warnings); err != NULL; err = nerr)
1829*c42dbd0eSchristos {
1830*c42dbd0eSchristos nerr = ctf_list_next (err);
1831*c42dbd0eSchristos ctf_list_delete (&fp->ctf_errs_warnings, err);
1832*c42dbd0eSchristos free (err->cew_text);
1833*c42dbd0eSchristos free (err);
1834*c42dbd0eSchristos }
1835867d70fcSchristos
1836867d70fcSchristos free (fp->ctf_sxlate);
1837867d70fcSchristos free (fp->ctf_txlate);
1838867d70fcSchristos free (fp->ctf_ptrtab);
1839*c42dbd0eSchristos free (fp->ctf_pptrtab);
1840867d70fcSchristos
1841867d70fcSchristos free (fp->ctf_header);
1842867d70fcSchristos free (fp);
1843867d70fcSchristos }
1844867d70fcSchristos
1845*c42dbd0eSchristos /* Backward compatibility. */
1846*c42dbd0eSchristos void
ctf_file_close(ctf_file_t * fp)1847*c42dbd0eSchristos ctf_file_close (ctf_file_t *fp)
1848*c42dbd0eSchristos {
1849*c42dbd0eSchristos ctf_dict_close (fp);
1850*c42dbd0eSchristos }
1851*c42dbd0eSchristos
1852867d70fcSchristos /* The converse of ctf_open(). ctf_open() disguises whatever it opens as an
1853867d70fcSchristos archive, so closing one is just like closing an archive. */
1854867d70fcSchristos void
ctf_close(ctf_archive_t * arc)1855867d70fcSchristos ctf_close (ctf_archive_t *arc)
1856867d70fcSchristos {
1857867d70fcSchristos ctf_arc_close (arc);
1858867d70fcSchristos }
1859867d70fcSchristos
1860*c42dbd0eSchristos /* Get the CTF archive from which this ctf_dict_t is derived. */
1861867d70fcSchristos ctf_archive_t *
ctf_get_arc(const ctf_dict_t * fp)1862*c42dbd0eSchristos ctf_get_arc (const ctf_dict_t *fp)
1863867d70fcSchristos {
1864867d70fcSchristos return fp->ctf_archive;
1865867d70fcSchristos }
1866867d70fcSchristos
1867867d70fcSchristos /* Return the ctfsect out of the core ctf_impl. Useful for freeing the
1868*c42dbd0eSchristos ctfsect's data * after ctf_dict_close(), which is why we return the actual
1869867d70fcSchristos structure, not a pointer to it, since that is likely to become a pointer to
1870867d70fcSchristos freed data before the return value is used under the expected use case of
1871*c42dbd0eSchristos ctf_getsect()/ ctf_dict_close()/free(). */
1872867d70fcSchristos ctf_sect_t
ctf_getdatasect(const ctf_dict_t * fp)1873*c42dbd0eSchristos ctf_getdatasect (const ctf_dict_t *fp)
1874867d70fcSchristos {
1875867d70fcSchristos return fp->ctf_data;
1876867d70fcSchristos }
1877867d70fcSchristos
1878*c42dbd0eSchristos ctf_sect_t
ctf_getsymsect(const ctf_dict_t * fp)1879*c42dbd0eSchristos ctf_getsymsect (const ctf_dict_t *fp)
1880*c42dbd0eSchristos {
1881*c42dbd0eSchristos return fp->ctf_symtab;
1882*c42dbd0eSchristos }
1883*c42dbd0eSchristos
1884*c42dbd0eSchristos ctf_sect_t
ctf_getstrsect(const ctf_dict_t * fp)1885*c42dbd0eSchristos ctf_getstrsect (const ctf_dict_t *fp)
1886*c42dbd0eSchristos {
1887*c42dbd0eSchristos return fp->ctf_strtab;
1888*c42dbd0eSchristos }
1889*c42dbd0eSchristos
1890*c42dbd0eSchristos /* Set the endianness of the symbol table attached to FP. */
1891*c42dbd0eSchristos void
ctf_symsect_endianness(ctf_dict_t * fp,int little_endian)1892*c42dbd0eSchristos ctf_symsect_endianness (ctf_dict_t *fp, int little_endian)
1893*c42dbd0eSchristos {
1894*c42dbd0eSchristos int old_endianness = fp->ctf_symsect_little_endian;
1895*c42dbd0eSchristos
1896*c42dbd0eSchristos fp->ctf_symsect_little_endian = !!little_endian;
1897*c42dbd0eSchristos
1898*c42dbd0eSchristos /* If we already have a symtab translation table, we need to repopulate it if
1899*c42dbd0eSchristos our idea of the endianness has changed. */
1900*c42dbd0eSchristos
1901*c42dbd0eSchristos if (old_endianness != fp->ctf_symsect_little_endian
1902*c42dbd0eSchristos && fp->ctf_sxlate != NULL && fp->ctf_symtab.cts_data != NULL)
1903*c42dbd0eSchristos assert (init_symtab (fp, fp->ctf_header, &fp->ctf_symtab) == 0);
1904*c42dbd0eSchristos }
1905*c42dbd0eSchristos
1906*c42dbd0eSchristos /* Return the CTF handle for the parent CTF dict, if one exists. Otherwise
1907*c42dbd0eSchristos return NULL to indicate this dict has no imported parent. */
1908*c42dbd0eSchristos ctf_dict_t *
ctf_parent_dict(ctf_dict_t * fp)1909*c42dbd0eSchristos ctf_parent_dict (ctf_dict_t *fp)
1910867d70fcSchristos {
1911867d70fcSchristos return fp->ctf_parent;
1912867d70fcSchristos }
1913867d70fcSchristos
1914*c42dbd0eSchristos /* Backward compatibility. */
1915*c42dbd0eSchristos ctf_dict_t *
ctf_parent_file(ctf_dict_t * fp)1916*c42dbd0eSchristos ctf_parent_file (ctf_dict_t *fp)
1917*c42dbd0eSchristos {
1918*c42dbd0eSchristos return ctf_parent_dict (fp);
1919*c42dbd0eSchristos }
1920*c42dbd0eSchristos
1921*c42dbd0eSchristos /* Return the name of the parent CTF dict, if one exists, or NULL otherwise. */
1922867d70fcSchristos const char *
ctf_parent_name(ctf_dict_t * fp)1923*c42dbd0eSchristos ctf_parent_name (ctf_dict_t *fp)
1924867d70fcSchristos {
1925867d70fcSchristos return fp->ctf_parname;
1926867d70fcSchristos }
1927867d70fcSchristos
1928867d70fcSchristos /* Set the parent name. It is an error to call this routine without calling
1929867d70fcSchristos ctf_import() at some point. */
1930867d70fcSchristos int
ctf_parent_name_set(ctf_dict_t * fp,const char * name)1931*c42dbd0eSchristos ctf_parent_name_set (ctf_dict_t *fp, const char *name)
1932867d70fcSchristos {
1933867d70fcSchristos if (fp->ctf_dynparname != NULL)
1934867d70fcSchristos free (fp->ctf_dynparname);
1935867d70fcSchristos
1936867d70fcSchristos if ((fp->ctf_dynparname = strdup (name)) == NULL)
1937867d70fcSchristos return (ctf_set_errno (fp, ENOMEM));
1938867d70fcSchristos fp->ctf_parname = fp->ctf_dynparname;
1939867d70fcSchristos return 0;
1940867d70fcSchristos }
1941867d70fcSchristos
1942867d70fcSchristos /* Return the name of the compilation unit this CTF file applies to. Usually
1943*c42dbd0eSchristos non-NULL only for non-parent dicts. */
1944867d70fcSchristos const char *
ctf_cuname(ctf_dict_t * fp)1945*c42dbd0eSchristos ctf_cuname (ctf_dict_t *fp)
1946867d70fcSchristos {
1947867d70fcSchristos return fp->ctf_cuname;
1948867d70fcSchristos }
1949867d70fcSchristos
1950867d70fcSchristos /* Set the compilation unit name. */
1951867d70fcSchristos int
ctf_cuname_set(ctf_dict_t * fp,const char * name)1952*c42dbd0eSchristos ctf_cuname_set (ctf_dict_t *fp, const char *name)
1953867d70fcSchristos {
1954867d70fcSchristos if (fp->ctf_dyncuname != NULL)
1955867d70fcSchristos free (fp->ctf_dyncuname);
1956867d70fcSchristos
1957867d70fcSchristos if ((fp->ctf_dyncuname = strdup (name)) == NULL)
1958867d70fcSchristos return (ctf_set_errno (fp, ENOMEM));
1959867d70fcSchristos fp->ctf_cuname = fp->ctf_dyncuname;
1960867d70fcSchristos return 0;
1961867d70fcSchristos }
1962867d70fcSchristos
1963*c42dbd0eSchristos /* Import the types from the specified parent dict by storing a pointer to it in
1964*c42dbd0eSchristos ctf_parent and incrementing its reference count. Only one parent is allowed:
1965*c42dbd0eSchristos if a parent already exists, it is replaced by the new parent. The pptrtab
1966*c42dbd0eSchristos is wiped, and will be refreshed by the next ctf_lookup_by_name call. */
1967867d70fcSchristos int
ctf_import(ctf_dict_t * fp,ctf_dict_t * pfp)1968*c42dbd0eSchristos ctf_import (ctf_dict_t *fp, ctf_dict_t *pfp)
1969867d70fcSchristos {
1970867d70fcSchristos if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0))
1971867d70fcSchristos return (ctf_set_errno (fp, EINVAL));
1972867d70fcSchristos
1973867d70fcSchristos if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel)
1974867d70fcSchristos return (ctf_set_errno (fp, ECTF_DMODEL));
1975867d70fcSchristos
1976*c42dbd0eSchristos if (fp->ctf_parent && !fp->ctf_parent_unreffed)
1977*c42dbd0eSchristos ctf_dict_close (fp->ctf_parent);
1978867d70fcSchristos fp->ctf_parent = NULL;
1979*c42dbd0eSchristos
1980*c42dbd0eSchristos free (fp->ctf_pptrtab);
1981*c42dbd0eSchristos fp->ctf_pptrtab = NULL;
1982*c42dbd0eSchristos fp->ctf_pptrtab_len = 0;
1983*c42dbd0eSchristos fp->ctf_pptrtab_typemax = 0;
1984867d70fcSchristos
1985867d70fcSchristos if (pfp != NULL)
1986867d70fcSchristos {
1987867d70fcSchristos int err;
1988867d70fcSchristos
1989867d70fcSchristos if (fp->ctf_parname == NULL)
1990867d70fcSchristos if ((err = ctf_parent_name_set (fp, "PARENT")) < 0)
1991867d70fcSchristos return err;
1992867d70fcSchristos
1993867d70fcSchristos fp->ctf_flags |= LCTF_CHILD;
1994867d70fcSchristos pfp->ctf_refcnt++;
1995*c42dbd0eSchristos fp->ctf_parent_unreffed = 0;
1996867d70fcSchristos }
1997867d70fcSchristos
1998867d70fcSchristos fp->ctf_parent = pfp;
1999867d70fcSchristos return 0;
2000867d70fcSchristos }
2001867d70fcSchristos
2002*c42dbd0eSchristos /* Like ctf_import, but does not increment the refcount on the imported parent
2003*c42dbd0eSchristos or close it at any point: as a result it can go away at any time and the
2004*c42dbd0eSchristos caller must do all freeing itself. Used internally to avoid refcount
2005*c42dbd0eSchristos loops. */
2006867d70fcSchristos int
ctf_import_unref(ctf_dict_t * fp,ctf_dict_t * pfp)2007*c42dbd0eSchristos ctf_import_unref (ctf_dict_t *fp, ctf_dict_t *pfp)
2008*c42dbd0eSchristos {
2009*c42dbd0eSchristos if (fp == NULL || fp == pfp || (pfp != NULL && pfp->ctf_refcnt == 0))
2010*c42dbd0eSchristos return (ctf_set_errno (fp, EINVAL));
2011*c42dbd0eSchristos
2012*c42dbd0eSchristos if (pfp != NULL && pfp->ctf_dmodel != fp->ctf_dmodel)
2013*c42dbd0eSchristos return (ctf_set_errno (fp, ECTF_DMODEL));
2014*c42dbd0eSchristos
2015*c42dbd0eSchristos if (fp->ctf_parent && !fp->ctf_parent_unreffed)
2016*c42dbd0eSchristos ctf_dict_close (fp->ctf_parent);
2017*c42dbd0eSchristos fp->ctf_parent = NULL;
2018*c42dbd0eSchristos
2019*c42dbd0eSchristos free (fp->ctf_pptrtab);
2020*c42dbd0eSchristos fp->ctf_pptrtab = NULL;
2021*c42dbd0eSchristos fp->ctf_pptrtab_len = 0;
2022*c42dbd0eSchristos fp->ctf_pptrtab_typemax = 0;
2023*c42dbd0eSchristos if (pfp != NULL)
2024*c42dbd0eSchristos {
2025*c42dbd0eSchristos int err;
2026*c42dbd0eSchristos
2027*c42dbd0eSchristos if (fp->ctf_parname == NULL)
2028*c42dbd0eSchristos if ((err = ctf_parent_name_set (fp, "PARENT")) < 0)
2029*c42dbd0eSchristos return err;
2030*c42dbd0eSchristos
2031*c42dbd0eSchristos fp->ctf_flags |= LCTF_CHILD;
2032*c42dbd0eSchristos fp->ctf_parent_unreffed = 1;
2033*c42dbd0eSchristos }
2034*c42dbd0eSchristos
2035*c42dbd0eSchristos fp->ctf_parent = pfp;
2036*c42dbd0eSchristos return 0;
2037*c42dbd0eSchristos }
2038*c42dbd0eSchristos
2039*c42dbd0eSchristos /* Set the data model constant for the CTF dict. */
2040*c42dbd0eSchristos int
ctf_setmodel(ctf_dict_t * fp,int model)2041*c42dbd0eSchristos ctf_setmodel (ctf_dict_t *fp, int model)
2042867d70fcSchristos {
2043867d70fcSchristos const ctf_dmodel_t *dp;
2044867d70fcSchristos
2045867d70fcSchristos for (dp = _libctf_models; dp->ctd_name != NULL; dp++)
2046867d70fcSchristos {
2047867d70fcSchristos if (dp->ctd_code == model)
2048867d70fcSchristos {
2049867d70fcSchristos fp->ctf_dmodel = dp;
2050867d70fcSchristos return 0;
2051867d70fcSchristos }
2052867d70fcSchristos }
2053867d70fcSchristos
2054867d70fcSchristos return (ctf_set_errno (fp, EINVAL));
2055867d70fcSchristos }
2056867d70fcSchristos
2057*c42dbd0eSchristos /* Return the data model constant for the CTF dict. */
2058867d70fcSchristos int
ctf_getmodel(ctf_dict_t * fp)2059*c42dbd0eSchristos ctf_getmodel (ctf_dict_t *fp)
2060867d70fcSchristos {
2061867d70fcSchristos return fp->ctf_dmodel->ctd_code;
2062867d70fcSchristos }
2063867d70fcSchristos
2064*c42dbd0eSchristos /* The caller can hang an arbitrary pointer off each ctf_dict_t using this
2065867d70fcSchristos function. */
2066867d70fcSchristos void
ctf_setspecific(ctf_dict_t * fp,void * data)2067*c42dbd0eSchristos ctf_setspecific (ctf_dict_t *fp, void *data)
2068867d70fcSchristos {
2069867d70fcSchristos fp->ctf_specific = data;
2070867d70fcSchristos }
2071867d70fcSchristos
2072867d70fcSchristos /* Retrieve the arbitrary pointer again. */
2073867d70fcSchristos void *
ctf_getspecific(ctf_dict_t * fp)2074*c42dbd0eSchristos ctf_getspecific (ctf_dict_t *fp)
2075867d70fcSchristos {
2076867d70fcSchristos return fp->ctf_specific;
2077867d70fcSchristos }
2078