pahole: Describe expected use of 'default' in the man page
[dwarves.git] / ctf_encoder.c
blobb761287d45348c59f8cd468292d287c65c90d32c
1 /*
2 SPDX-License-Identifier: GPL-2.0-only
4 Copyright (C) 2009 Red Hat Inc.
5 Copyright (C) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
6 */
8 #include "dwarves.h"
9 #include "libctf.h"
10 #include "ctf.h"
11 #include "hash.h"
12 #include "elf_symtab.h"
13 #include <inttypes.h>
15 static int tag__check_id_drift(const struct tag *tag,
16 uint32_t core_id, uint32_t ctf_id)
18 if (ctf_id != core_id) {
19 fprintf(stderr, "%s: %s id drift, core: %u, libctf: %d\n",
20 __func__, dwarf_tag_name(tag->tag), core_id, ctf_id);
21 return -1;
23 return 0;
26 static int dwarf_to_ctf_type(uint16_t tag)
28 switch (tag) {
29 case DW_TAG_const_type: return CTF_TYPE_KIND_CONST;
30 case DW_TAG_pointer_type: return CTF_TYPE_KIND_PTR;
31 case DW_TAG_restrict_type: return CTF_TYPE_KIND_RESTRICT;
32 case DW_TAG_volatile_type: return CTF_TYPE_KIND_VOLATILE;
33 case DW_TAG_class_type:
34 case DW_TAG_structure_type: return CTF_TYPE_KIND_STR;
35 case DW_TAG_union_type: return CTF_TYPE_KIND_UNION;
37 return 0xffff;
40 static int base_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
42 struct base_type *bt = tag__base_type(tag);
43 uint32_t ctf_id = ctf__add_base_type(ctf, bt->name, bt->bit_size);
45 if (tag__check_id_drift(tag, core_id, ctf_id))
46 return -1;
48 return 0;
51 static int pointer_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
53 uint32_t ctf_id = ctf__add_short_type(ctf, dwarf_to_ctf_type(tag->tag), tag->type, 0);
55 if (tag__check_id_drift(tag, core_id, ctf_id))
56 return -1;
58 return 0;
61 static int typedef__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
63 uint32_t ctf_id = ctf__add_short_type(ctf, CTF_TYPE_KIND_TYPDEF, tag->type, tag__namespace(tag)->name);
65 if (tag__check_id_drift(tag, core_id, ctf_id))
66 return -1;
68 return 0;
71 static int fwd_decl__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
73 uint32_t ctf_id = ctf__add_fwd_decl(ctf, tag__namespace(tag)->name);
75 if (tag__check_id_drift(tag, core_id, ctf_id))
76 return -1;
78 return 0;
81 static int structure_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
83 struct type *type = tag__type(tag);
84 int64_t position;
85 uint32_t ctf_id = ctf__add_struct(ctf, dwarf_to_ctf_type(tag->tag),
86 type->namespace.name, type->size,
87 type->nr_members, &position);
89 if (tag__check_id_drift(tag, core_id, ctf_id))
90 return -1;
92 const bool is_short = type->size < CTF_SHORT_MEMBER_LIMIT;
93 struct class_member *pos;
94 type__for_each_data_member(type, pos) {
95 if (is_short)
96 ctf__add_short_member(ctf, pos->name, pos->tag.type,
97 pos->bit_offset, &position);
98 else
99 ctf__add_full_member(ctf, pos->name, pos->tag.type,
100 pos->bit_offset, &position);
103 return 0;
106 static uint32_t array_type__nelems(struct tag *tag)
108 int i;
109 uint32_t nelem = 1;
110 struct array_type *array = tag__array_type(tag);
112 for (i = array->dimensions - 1; i >= 0; --i)
113 nelem *= array->nr_entries[i];
115 return nelem;
118 static int array_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
120 const uint32_t nelems = array_type__nelems(tag);
121 uint32_t ctf_id = ctf__add_array(ctf, tag->type, 0, nelems);
123 if (tag__check_id_drift(tag, core_id, ctf_id))
124 return -1;
126 return 0;
129 static int subroutine_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
131 struct parameter *pos;
132 int64_t position;
133 struct ftype *ftype = tag__ftype(tag);
134 uint32_t ctf_id = ctf__add_function_type(ctf, tag->type, ftype->nr_parms, ftype->unspec_parms, &position);
136 if (tag__check_id_drift(tag, core_id, ctf_id))
137 return -1;
139 ftype__for_each_parameter(ftype, pos)
140 ctf__add_parameter(ctf, pos->tag.type, &position);
142 return 0;
145 static int enumeration_type__encode(struct tag *tag, uint32_t core_id, struct ctf *ctf)
147 struct type *etype = tag__type(tag);
148 int64_t position;
149 uint32_t ctf_id = ctf__add_enumeration_type(ctf, etype->namespace.name,
150 etype->size, etype->nr_members,
151 &position);
153 if (tag__check_id_drift(tag, core_id, ctf_id))
154 return -1;
156 struct enumerator *pos;
157 type__for_each_enumerator(etype, pos)
158 ctf__add_enumerator(ctf, pos->name, pos->value, &position);
160 return 0;
163 static void tag__encode_ctf(struct tag *tag, uint32_t core_id, struct ctf *ctf)
165 switch (tag->tag) {
166 case DW_TAG_base_type:
167 base_type__encode(tag, core_id, ctf);
168 break;
169 case DW_TAG_const_type:
170 case DW_TAG_pointer_type:
171 case DW_TAG_restrict_type:
172 case DW_TAG_volatile_type:
173 pointer_type__encode(tag, core_id, ctf);
174 break;
175 case DW_TAG_typedef:
176 typedef__encode(tag, core_id, ctf);
177 break;
178 case DW_TAG_structure_type:
179 case DW_TAG_union_type:
180 case DW_TAG_class_type:
181 if (tag__type(tag)->declaration)
182 fwd_decl__encode(tag, core_id, ctf);
183 else
184 structure_type__encode(tag, core_id, ctf);
185 break;
186 case DW_TAG_array_type:
187 array_type__encode(tag, core_id, ctf);
188 break;
189 case DW_TAG_subroutine_type:
190 subroutine_type__encode(tag, core_id, ctf);
191 break;
192 case DW_TAG_enumeration_type:
193 enumeration_type__encode(tag, core_id, ctf);
194 break;
198 #define HASHADDR__BITS 8
199 #define HASHADDR__SIZE (1UL << HASHADDR__BITS)
200 #define hashaddr__fn(key) hash_64(key, HASHADDR__BITS)
202 static struct function *hashaddr__find_function(const struct hlist_head hashtable[],
203 const uint64_t addr)
205 struct function *function;
206 struct hlist_node *pos;
207 uint16_t bucket = hashaddr__fn(addr);
208 const struct hlist_head *head = &hashtable[bucket];
210 hlist_for_each_entry(function, pos, head, tool_hnode) {
211 if (function->lexblock.ip.addr == addr)
212 return function;
215 return NULL;
218 static struct variable *hashaddr__find_variable(const struct hlist_head hashtable[],
219 const uint64_t addr)
221 struct variable *variable;
222 struct hlist_node *pos;
223 uint16_t bucket = hashaddr__fn(addr);
224 const struct hlist_head *head = &hashtable[bucket];
226 hlist_for_each_entry(variable, pos, head, tool_hnode) {
227 if (variable->ip.addr == addr)
228 return variable;
231 return NULL;
235 * FIXME: Its in the DWARF loader, we have to find a better handoff
236 * mechanizm...
238 extern struct strings *strings;
240 int cu__encode_ctf(struct cu *cu, int verbose)
242 int err = -1;
243 struct ctf *ctf = ctf__new(cu->filename, cu->elf);
245 if (ctf == NULL)
246 goto out;
248 if (cu__cache_symtab(cu) < 0)
249 goto out_delete;
251 ctf__set_strings(ctf, strings);
253 uint32_t id;
254 struct tag *pos;
255 cu__for_each_type(cu, id, pos)
256 tag__encode_ctf(pos, id, ctf);
258 struct hlist_head hash_addr[HASHADDR__SIZE];
260 for (id = 0; id < HASHADDR__SIZE; ++id)
261 INIT_HLIST_HEAD(&hash_addr[id]);
263 struct function *function;
264 cu__for_each_function(cu, id, function) {
265 uint64_t addr = function->lexblock.ip.addr;
266 struct hlist_head *head = &hash_addr[hashaddr__fn(addr)];
267 hlist_add_head(&function->tool_hnode, head);
270 uint64_t addr;
271 GElf_Sym sym;
272 const char *sym_name;
273 cu__for_each_cached_symtab_entry(cu, id, sym, sym_name) {
274 if (ctf__ignore_symtab_function(&sym, sym_name))
275 continue;
277 addr = elf_sym__value(&sym);
278 int64_t position;
279 function = hashaddr__find_function(hash_addr, addr);
280 if (function == NULL) {
281 if (verbose)
282 fprintf(stderr,
283 "function %4d: %-20s %#" PRIx64 " %5u NOT FOUND!\n",
284 id, sym_name, addr,
285 elf_sym__size(&sym));
286 err = ctf__add_function(ctf, 0, 0, 0, &position);
287 if (err != 0)
288 goto out_err_ctf;
289 continue;
292 const struct ftype *ftype = &function->proto;
293 err = ctf__add_function(ctf, function->proto.tag.type,
294 ftype->nr_parms,
295 ftype->unspec_parms, &position);
297 if (err != 0)
298 goto out_err_ctf;
300 struct parameter *pos;
301 ftype__for_each_parameter(ftype, pos)
302 ctf__add_function_parameter(ctf, pos->tag.type, &position);
305 for (id = 0; id < HASHADDR__SIZE; ++id)
306 INIT_HLIST_HEAD(&hash_addr[id]);
308 struct variable *var;
309 cu__for_each_variable(cu, id, pos) {
310 var = tag__variable(pos);
311 if (variable__scope(var) != VSCOPE_GLOBAL)
312 continue;
313 struct hlist_head *head = &hash_addr[hashaddr__fn(var->ip.addr)];
314 hlist_add_head(&var->tool_hnode, head);
317 cu__for_each_cached_symtab_entry(cu, id, sym, sym_name) {
318 if (ctf__ignore_symtab_object(&sym, sym_name))
319 continue;
320 addr = elf_sym__value(&sym);
322 var = hashaddr__find_variable(hash_addr, addr);
323 if (var == NULL) {
324 if (verbose)
325 fprintf(stderr,
326 "variable %4d: %-20s %#" PRIx64 " %5u NOT FOUND!\n",
327 id, sym_name, addr,
328 elf_sym__size(&sym));
329 err = ctf__add_object(ctf, 0);
330 if (err != 0)
331 goto out_err_ctf;
332 continue;
335 err = ctf__add_object(ctf, var->ip.tag.type);
336 if (err != 0)
337 goto out_err_ctf;
340 ctf__encode(ctf, CTF_FLAGS_COMPR);
342 err = 0;
343 out_delete:
344 ctf__delete(ctf);
345 out:
346 return err;
347 out_err_ctf:
348 fprintf(stderr,
349 "%4d: %-20s %#llx %5u failed encoding, "
350 "ABORTING!\n", id, sym_name,
351 (unsigned long long)addr, elf_sym__size(&sym));
352 goto out_delete;