1 | /* Output CTF format from GCC. |
2 | Copyright (C) 2019-2024 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | #include "config.h" |
21 | #include "system.h" |
22 | #include "coretypes.h" |
23 | #include "target.h" |
24 | #include "memmodel.h" |
25 | #include "tm_p.h" |
26 | #include "output.h" |
27 | #include "dwarf2asm.h" |
28 | #include "debug.h" |
29 | #include "ctfc.h" |
30 | #include "diagnostic-core.h" |
31 | |
32 | static int ctf_label_num; |
33 | |
34 | /* Pointers to various CTF sections. */ |
35 | |
36 | static GTY (()) section * ctf_info_section; |
37 | |
38 | /* Section names used to hold CTF debugging information. */ |
39 | |
40 | /* CTF debug info section. */ |
41 | |
42 | #ifndef CTF_INFO_SECTION_NAME |
43 | #define CTF_INFO_SECTION_NAME ".ctf" |
44 | #endif |
45 | |
46 | /* Section flags for the CTF debug info section. */ |
47 | |
48 | #define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG) |
49 | |
50 | /* Maximum size (in bytes) of an artificially generated CTF label. */ |
51 | |
52 | #define MAX_CTF_LABEL_BYTES 40 |
53 | |
54 | static char ctf_info_section_label[MAX_CTF_LABEL_BYTES]; |
55 | |
56 | #ifndef CTF_INFO_SECTION_LABEL |
57 | #define CTF_INFO_SECTION_LABEL "Lctf" |
58 | #endif |
59 | |
60 | /* CTF preprocess callback arguments. */ |
61 | |
62 | typedef struct ctf_dtd_preprocess_arg |
63 | { |
64 | uint64_t dtd_global_func_idx; |
65 | ctf_container_ref dtd_arg_ctfc; |
66 | } ctf_dtd_preprocess_arg_t; |
67 | |
68 | typedef struct ctf_dvd_preprocess_arg |
69 | { |
70 | uint64_t dvd_global_obj_idx; |
71 | ctf_container_ref dvd_arg_ctfc; |
72 | } ctf_dvd_preprocess_arg_t; |
73 | |
74 | /* Compare two CTF variable definition entries. Currently used for sorting |
75 | by name. */ |
76 | |
77 | static int |
78 | ctf_varent_compare (const void * entry1, const void * entry2) |
79 | { |
80 | int result; |
81 | const ctf_dvdef_t * e1 = *(const ctf_dvdef_t * const*) entry1; |
82 | const ctf_dvdef_t * e2 = *(const ctf_dvdef_t * const*) entry2; |
83 | |
84 | result = strcmp (s1: e1->dvd_name, s2: e2->dvd_name); |
85 | |
86 | return result; |
87 | } |
88 | |
89 | /* A CTF type record may be followed by variable-length of bytes to encode the |
90 | CTF type completely. This routine calculates the number of bytes, in the |
91 | final binary CTF format, which are used to encode information about the type |
92 | completely. |
93 | |
94 | This function must always be in sync with the CTF header. */ |
95 | |
96 | static uint64_t |
97 | ctf_calc_num_vbytes (ctf_dtdef_ref ctftype) |
98 | { |
99 | uint32_t size; |
100 | uint64_t vlen_bytes = 0; |
101 | |
102 | uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); |
103 | uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); |
104 | |
105 | ctf_dmdef_t * dmd; |
106 | ctf_func_arg_t * farg; |
107 | uint32_t size_per_member = 0; |
108 | unsigned int num_members = 0; |
109 | unsigned int num_fargs = 0; |
110 | |
111 | switch (kind) |
112 | { |
113 | case CTF_K_FORWARD: |
114 | case CTF_K_UNKNOWN: |
115 | case CTF_K_POINTER: |
116 | case CTF_K_TYPEDEF: |
117 | case CTF_K_VOLATILE: |
118 | case CTF_K_CONST: |
119 | case CTF_K_RESTRICT: |
120 | /* These types have no vlen data. */ |
121 | break; |
122 | |
123 | case CTF_K_INTEGER: |
124 | case CTF_K_FLOAT: |
125 | /* 4 bytes to represent encoding CTF_INT_DATA, CTF_FP_DATA. */ |
126 | vlen_bytes += sizeof (uint32_t); |
127 | break; |
128 | case CTF_K_FUNCTION: |
129 | /* Sanity check - number of function args must be the same as |
130 | vlen. */ |
131 | for (farg = ctftype->dtd_u.dtu_argv; |
132 | farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg)) |
133 | num_fargs++; |
134 | gcc_assert (vlen == num_fargs); |
135 | |
136 | /* FIXME - CTF_PADDING_FOR_ALIGNMENT. */ |
137 | vlen_bytes += (vlen + (vlen & 1)) * sizeof (uint32_t); |
138 | break; |
139 | case CTF_K_ARRAY: |
140 | /* This has a single ctf_array_t. */ |
141 | vlen_bytes += sizeof (ctf_array_t); |
142 | break; |
143 | case CTF_K_SLICE: |
144 | vlen_bytes += sizeof (ctf_slice_t); |
145 | break; |
146 | case CTF_K_STRUCT: |
147 | case CTF_K_UNION: |
148 | /* Count the number and type of members. */ |
149 | size = ctftype->dtd_data.ctti_size; |
150 | size_per_member = size >= CTF_LSTRUCT_THRESH |
151 | ? sizeof (ctf_lmember_t) : sizeof (ctf_member_t); |
152 | |
153 | /* Sanity check - number of members of struct must be the same as |
154 | vlen. */ |
155 | for (dmd = ctftype->dtd_u.dtu_members; |
156 | dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) |
157 | num_members++; |
158 | gcc_assert (vlen == num_members); |
159 | |
160 | vlen_bytes += (num_members * size_per_member); |
161 | break; |
162 | case CTF_K_ENUM: |
163 | vlen_bytes += vlen * sizeof (ctf_enum_t); |
164 | break; |
165 | default : |
166 | break; |
167 | } |
168 | return vlen_bytes; |
169 | } |
170 | |
171 | /* Add a CTF variable to the end of the list. */ |
172 | |
173 | static void |
174 | ctf_list_add_ctf_vars (ctf_container_ref ctfc, ctf_dvdef_ref var) |
175 | { |
176 | ctfc->ctfc_vars_list[ctfc->ctfc_vars_list_count++] = var; |
177 | } |
178 | |
179 | /* Initialize the various sections and labels for CTF output. */ |
180 | |
181 | void |
182 | init_ctf_sections (void) |
183 | { |
184 | /* Note : Even in case of LTO, the compiler continues to generate a single |
185 | CTF section for each compilation unit "early". Unlike other debug |
186 | sections, CTF sections are non-LTO sections, and do not take the |
187 | .gnu.debuglto_ prefix. The linker will de-duplicate the types in the CTF |
188 | sections, in case of LTO or otherwise. */ |
189 | ctf_info_section = get_section (CTF_INFO_SECTION_NAME, CTF_INFO_SECTION_FLAGS, |
190 | NULL); |
191 | |
192 | ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label, |
193 | CTF_INFO_SECTION_LABEL, ctf_label_num++); |
194 | } |
195 | |
196 | /* Routines for CTF pre-processing. */ |
197 | |
198 | static void |
199 | ctf_preprocess_var (ctf_container_ref ctfc, ctf_dvdef_ref var) |
200 | { |
201 | /* Add it to the list of types. This array of types will be sorted before |
202 | assembling into output. */ |
203 | ctf_list_add_ctf_vars (ctfc, var); |
204 | } |
205 | |
206 | /* CTF preprocess callback routine for CTF variables. */ |
207 | |
208 | int |
209 | ctf_dvd_preprocess_cb (ctf_dvdef_ref * slot, void * arg) |
210 | { |
211 | ctf_dvd_preprocess_arg_t * dvd_arg = (ctf_dvd_preprocess_arg_t *)arg; |
212 | ctf_dvdef_ref var = (ctf_dvdef_ref) *slot; |
213 | ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc; |
214 | |
215 | /* If the CTF variable corresponds to an extern variable declaration with |
216 | a defining declaration later on, skip it. Only CTF variable |
217 | corresponding to the defining declaration for the extern variable is |
218 | desirable. */ |
219 | if (ctf_dvd_ignore_lookup (ctfc: arg_ctfc, die: var->dvd_key)) |
220 | return 1; |
221 | |
222 | ctf_preprocess_var (ctfc: arg_ctfc, var); |
223 | |
224 | /* Keep track of global objts. */ |
225 | arg_ctfc->ctfc_gobjts_list[dvd_arg->dvd_global_obj_idx] = var; |
226 | dvd_arg->dvd_global_obj_idx++; |
227 | |
228 | return 1; |
229 | } |
230 | |
231 | /* CTF preprocess callback routine for CTF types. */ |
232 | |
233 | int |
234 | ctf_dtd_preprocess_cb (ctf_dtdef_ref * slot, void * arg) |
235 | { |
236 | uint32_t kind; |
237 | |
238 | ctf_dtdef_ref ctftype = (ctf_dtdef_ref) *slot; |
239 | ctf_dtd_preprocess_arg_t * dtd_arg = (ctf_dtd_preprocess_arg_t *)arg; |
240 | ctf_container_ref arg_ctfc = dtd_arg->dtd_arg_ctfc; |
241 | |
242 | size_t index = ctftype->dtd_type; |
243 | gcc_assert (index <= arg_ctfc->ctfc_types->elements ()); |
244 | |
245 | /* CTF types need to be output in the order of their type IDs. In other |
246 | words, if type A is used to define type B, type ID of type A must |
247 | appear before type ID of type B. */ |
248 | arg_ctfc->ctfc_types_list[index] = ctftype; |
249 | |
250 | /* Keep track of the CTF type if it's a function type and the type |
251 | was generated from a function object. */ |
252 | kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); |
253 | if (kind == CTF_K_FUNCTION && ctftype->from_global_func) |
254 | { |
255 | arg_ctfc->ctfc_gfuncs_list[dtd_arg->dtd_global_func_idx] = ctftype; |
256 | dtd_arg->dtd_global_func_idx++; |
257 | } |
258 | |
259 | /* Calculate the vlen bytes. */ |
260 | arg_ctfc->ctfc_num_vlen_bytes += ctf_calc_num_vbytes (ctftype); |
261 | |
262 | return 1; |
263 | } |
264 | |
265 | /* CTF preprocessing. |
266 | After the CTF types for the compilation unit have been generated fully, the |
267 | compiler writes out the asm for the CTF types. |
268 | |
269 | CTF writeout in the compiler requires two passes over the CTF types. In the |
270 | first pass, the CTF preprocess pass: |
271 | 1. CTF types are sorted in the order of their type IDs. |
272 | 2. The variable number of bytes after each CTF type record are calculated. |
273 | This is used to calculate the offsets in the ctf_header_t. |
274 | 3. If the CTF type is of CTF_K_FUNCTION, the number of bytes in the |
275 | funcinfo sub-section are calculated. This is used to calculate the |
276 | offsets in the ctf_header_t. |
277 | 4. Keep the list of CTF variables in ASCIIbetical order of their names. |
278 | |
279 | In the second pass, the CTF writeout pass, asm tags are written out using |
280 | the compiler's afore-generated internal pre-processed CTF types. */ |
281 | |
282 | static void |
283 | ctf_preprocess (ctf_container_ref ctfc) |
284 | { |
285 | size_t num_ctf_types = ctfc->ctfc_types->elements (); |
286 | size_t num_ctf_vars = ctfc_get_num_ctf_vars (ctfc); |
287 | |
288 | /* Initialize an array to keep track of the CTF variables at global |
289 | scope. At this time, size it conservatively. */ |
290 | size_t num_global_objts = num_ctf_vars; |
291 | if (num_global_objts) |
292 | { |
293 | ctfc->ctfc_gobjts_list = ggc_vec_alloc<ctf_dvdef_t*>(c: num_global_objts); |
294 | } |
295 | |
296 | if (num_ctf_vars) |
297 | { |
298 | ctf_dvd_preprocess_arg_t dvd_arg; |
299 | dvd_arg.dvd_global_obj_idx = 0; |
300 | dvd_arg.dvd_arg_ctfc = ctfc; |
301 | |
302 | /* Allocate CTF var list. */ |
303 | ctfc->ctfc_vars_list = ggc_vec_alloc<ctf_dvdef_ref>(c: num_ctf_vars); |
304 | /* Variables appear in the sort ASCIIbetical order of their names. This |
305 | permits binary searching in the CTF reader. Add the variables to a |
306 | list for sorting. */ |
307 | ctfc->ctfc_vars->traverse<void *, ctf_dvd_preprocess_cb> (argument: &dvd_arg); |
308 | /* Sort the list. */ |
309 | qsort (ctfc->ctfc_vars_list, ctfc->ctfc_vars_list_count, |
310 | sizeof (ctf_dvdef_ref), ctf_varent_compare); |
311 | /* Update the actual number of the generated CTF variables at global |
312 | scope. */ |
313 | ctfc->ctfc_num_global_objts = dvd_arg.dvd_global_obj_idx; |
314 | } |
315 | |
316 | /* Initialize an array to keep track of the CTF functions types for global |
317 | functions in the CTF data section. */ |
318 | size_t num_global_funcs = ctfc->ctfc_num_global_funcs; |
319 | if (num_global_funcs) |
320 | { |
321 | ctfc->ctfc_gfuncs_list = ggc_vec_alloc<ctf_dtdef_t*>(c: num_global_funcs); |
322 | gcc_assert (num_ctf_types); |
323 | } |
324 | |
325 | if (num_ctf_types) |
326 | { |
327 | ctf_dtd_preprocess_arg_t dtd_arg; |
328 | dtd_arg.dtd_global_func_idx = 0; |
329 | dtd_arg.dtd_arg_ctfc = ctfc; |
330 | /* Allocate the CTF types list. Add 1 because type ID 0 is never a valid |
331 | CTF type ID. No CTF type record should appear at that offset, this |
332 | eases debugging and readability. */ |
333 | ctfc->ctfc_types_list = ggc_vec_alloc<ctf_dtdef_ref>(c: num_ctf_types + 1); |
334 | /* Pre-process CTF types. */ |
335 | ctfc->ctfc_types->traverse<void *, ctf_dtd_preprocess_cb> (argument: &dtd_arg); |
336 | |
337 | gcc_assert (dtd_arg.dtd_global_func_idx == num_global_funcs); |
338 | } |
339 | } |
340 | |
341 | /* CTF asm helper routines. */ |
342 | |
343 | /* Asm'out the CTF preamble. */ |
344 | |
345 | static void |
346 | ctf_asm_preamble (ctf_container_ref ctfc) |
347 | { |
348 | dw2_asm_output_data (2, ctfc->ctfc_magic, |
349 | "CTF preamble magic number" ); |
350 | dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version" ); |
351 | dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags" ); |
352 | } |
353 | |
354 | /* Asm'out a CTF type which is represented by ctf_stype_t. */ |
355 | |
356 | static void |
357 | ctf_asm_stype (ctf_dtdef_ref type) |
358 | { |
359 | dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name" ); |
360 | dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info" ); |
361 | /* union. */ |
362 | dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size or ctt_type" ); |
363 | } |
364 | |
365 | /* Asm'out a CTF type which is represented by ctf_type_t. */ |
366 | |
367 | static void |
368 | ctf_asm_type (ctf_dtdef_ref type) |
369 | { |
370 | dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name" ); |
371 | dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info" ); |
372 | /* union. */ |
373 | dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size" ); |
374 | dw2_asm_output_data (4, type->dtd_data.ctti_lsizehi, "ctt_lsizehi" ); |
375 | dw2_asm_output_data (4, type->dtd_data.ctti_lsizelo, "ctt_lsizelo" ); |
376 | } |
377 | |
378 | /* Asm'out a CTF type of kind CTF_K_SLICE. */ |
379 | |
380 | static void |
381 | ctf_asm_slice (ctf_dtdef_ref type) |
382 | { |
383 | dw2_asm_output_data (4, type->dtd_u.dtu_slice.cts_type, "cts_type" ); |
384 | dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_offset, "cts_offset" ); |
385 | dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_bits, "cts_bits" ); |
386 | } |
387 | |
388 | /* Asm'out a CTF type of kind CTF_K_ARRAY. */ |
389 | |
390 | static void |
391 | ctf_asm_array (ctf_dtdef_ref dtd) |
392 | { |
393 | dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_contents, "cta_contents" ); |
394 | dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_index, "cta_index" ); |
395 | dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_nelems, "cta_nelems" ); |
396 | } |
397 | |
398 | /* Asm'out a CTF variable. */ |
399 | |
400 | static void |
401 | ctf_asm_varent (ctf_dvdef_ref var) |
402 | { |
403 | /* Output the reference to the name in the string table. */ |
404 | dw2_asm_output_data (4, var->dvd_name_offset, "ctv_name" ); |
405 | /* Output the type index. */ |
406 | dw2_asm_output_data (4, var->dvd_type, "ctv_typeidx" ); |
407 | } |
408 | |
409 | /* Asm'out a member of CTF struct or union, represented by ctf_lmember_t. */ |
410 | |
411 | static void |
412 | ctf_asm_sou_lmember (ctf_dmdef_t * dmd) |
413 | { |
414 | dw2_asm_output_data (4, dmd->dmd_name_offset, "ctlm_name" ); |
415 | dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset), |
416 | "ctlm_offsethi" ); |
417 | dw2_asm_output_data (4, dmd->dmd_type, "ctlm_type" ); |
418 | dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset), |
419 | "ctlm_offsetlo" ); |
420 | } |
421 | |
422 | /* Asm'out a member of a CTF sruct or union, represented by ctf_member_t. */ |
423 | |
424 | static void |
425 | ctf_asm_sou_member (ctf_dmdef_t * dmd) |
426 | { |
427 | dw2_asm_output_data (4, dmd->dmd_name_offset, "ctm_name" ); |
428 | dw2_asm_output_data (4, dmd->dmd_offset, "ctm_offset" ); |
429 | dw2_asm_output_data (4, dmd->dmd_type, "ctm_type" ); |
430 | } |
431 | |
432 | /* Asm'out an enumerator constant. */ |
433 | |
434 | static void |
435 | ctf_asm_enum_const (ctf_dmdef_t * dmd) |
436 | { |
437 | dw2_asm_output_data (4, dmd->dmd_name_offset, "cte_name" ); |
438 | dw2_asm_output_data (4, dmd->dmd_value, "cte_value" ); |
439 | } |
440 | |
441 | /* Asm'out a function argument. */ |
442 | |
443 | static void |
444 | ctf_asm_func_arg (ctf_func_arg_t * farg) |
445 | { |
446 | dw2_asm_output_data (4, farg->farg_type, "dtu_argv" ); |
447 | } |
448 | |
449 | /* CTF writeout to asm file. */ |
450 | |
451 | static void |
452 | (ctf_container_ref ctfc) |
453 | { |
454 | switch_to_section (ctf_info_section); |
455 | ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label); |
456 | |
457 | ctf_asm_preamble (ctfc); |
458 | |
459 | /* For a single compilation unit, the parent container's name and label are |
460 | NULL. */ |
461 | dw2_asm_output_data (4, 0, "cth_parlabel" ); |
462 | dw2_asm_output_data (4, 0, "cth_parname" ); |
463 | dw2_asm_output_data (4, ctfc->ctfc_cuname_offset, "cth_cuname" ); |
464 | |
465 | int typeslen = 0; |
466 | /* Initialize the offsets. The offsets are from after the CTF header. */ |
467 | uint32_t lbloff = 0; |
468 | uint32_t objtoff = 0; |
469 | uint32_t funcoff = 0; |
470 | uint32_t objtidxoff = 0; |
471 | uint32_t funcidxoff = 0; |
472 | uint32_t varoff = 0; |
473 | uint32_t typeoff = 0; |
474 | uint32_t stroff = 0; |
475 | |
476 | if (!ctfc_is_empty_container (ctfc)) |
477 | { |
478 | gcc_assert (ctfc_get_num_ctf_types (ctfc) |
479 | == (ctfc->ctfc_num_types + ctfc->ctfc_num_stypes)); |
480 | |
481 | funcoff = objtoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t); |
482 | /* Object index appears after function info. */ |
483 | objtidxoff = funcoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t); |
484 | /* Funxtion index goes next. */ |
485 | funcidxoff = objtidxoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t); |
486 | /* Vars appear after function index. */ |
487 | varoff = funcidxoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t); |
488 | /* CTF types appear after vars. */ |
489 | typeoff = varoff + (ctfc->ctfc_vars_list_count) * sizeof (ctf_varent_t); |
490 | /* The total number of bytes for CTF types is the sum of the number of |
491 | times struct ctf_type_t, struct ctf_stype_t are written, plus the |
492 | amount of variable length data after each one of these. */ |
493 | typeslen = ctfc->ctfc_num_types * sizeof (ctf_type_t) |
494 | + ctfc->ctfc_num_stypes * (sizeof (ctf_stype_t)) |
495 | + ctfc_get_num_vlen_bytes (ctfc); |
496 | |
497 | /* Strings appear after types. */ |
498 | stroff = typeoff + typeslen; |
499 | } |
500 | |
501 | /* Offset of label section. */ |
502 | dw2_asm_output_data (4, lbloff, "cth_lbloff" ); |
503 | /* Offset of object section. */ |
504 | dw2_asm_output_data (4, objtoff, "cth_objtoff" ); |
505 | /* Offset of function section. */ |
506 | dw2_asm_output_data (4, funcoff, "cth_funcoff" ); |
507 | /* Offset of object index section. */ |
508 | dw2_asm_output_data (4, objtidxoff, "cth_objtidxoff" ); |
509 | /* Offset of function index section. */ |
510 | dw2_asm_output_data (4, funcidxoff, "cth_funcidxoff" ); |
511 | |
512 | /* Offset of variable section. */ |
513 | dw2_asm_output_data (4, varoff, "cth_varoff" ); |
514 | /* Offset of type section. */ |
515 | dw2_asm_output_data (4, typeoff, "cth_typeoff" ); |
516 | /* Offset of string section. */ |
517 | dw2_asm_output_data (4, stroff, "cth_stroff" ); |
518 | /* Length of string section in bytes. */ |
519 | dw2_asm_output_data (4, ctfc->ctfc_strlen, "cth_strlen" ); |
520 | } |
521 | |
522 | /* Output the CTF object info section. */ |
523 | |
524 | static void |
525 | output_ctf_obj_info (ctf_container_ref ctfc) |
526 | { |
527 | uint64_t i; |
528 | ctf_dvdef_ref var; |
529 | |
530 | if (!ctfc->ctfc_num_global_objts) return; |
531 | |
532 | /* Compiler spits out the objts (at global scope) in the CTF obj info section. |
533 | In no specific order. In an object file, the CTF object index section is |
534 | used to associate the objts to their corresponding names. */ |
535 | for (i = 0; i < ctfc->ctfc_num_global_objts; i++) |
536 | { |
537 | var = ctfc->ctfc_gobjts_list[i]; |
538 | |
539 | /* CTF type ID corresponding to the type of the variable. */ |
540 | dw2_asm_output_data (4, var->dvd_type, "objtinfo_var_type" ); |
541 | } |
542 | |
543 | } |
544 | |
545 | /* Output the CTF function info section. */ |
546 | |
547 | static void |
548 | output_ctf_func_info (ctf_container_ref ctfc) |
549 | { |
550 | uint64_t i; |
551 | ctf_dtdef_ref ctftype; |
552 | |
553 | if (!ctfc->ctfc_num_global_funcs) return; |
554 | |
555 | /* The CTF funcinfo section is simply an array of CTF_K_FUNCTION type IDs in |
556 | the type section. In an object file, the CTF function index section is |
557 | used to associate functions to their corresponding names. */ |
558 | for (i = 0; i < ctfc->ctfc_num_global_funcs; i++) |
559 | { |
560 | ctftype = ctfc->ctfc_gfuncs_list[i]; |
561 | dw2_asm_output_data (4, ctftype->dtd_type, "funcinfo_func_type" ); |
562 | } |
563 | } |
564 | |
565 | /* Output the CTF object index section. */ |
566 | |
567 | static void |
568 | output_ctf_objtidx (ctf_container_ref ctfc) |
569 | { |
570 | uint64_t i; |
571 | ctf_dvdef_ref var; |
572 | |
573 | if (!ctfc->ctfc_num_global_objts) return; |
574 | |
575 | for (i = 0; i < ctfc->ctfc_num_global_objts; i++) |
576 | { |
577 | var = ctfc->ctfc_gobjts_list[i]; |
578 | /* Offset to the name in CTF string table. */ |
579 | dw2_asm_output_data (4, var->dvd_name_offset, "objtinfo_name" ); |
580 | } |
581 | } |
582 | |
583 | /* Output the CTF function index section. */ |
584 | |
585 | static void |
586 | output_ctf_funcidx (ctf_container_ref ctfc) |
587 | { |
588 | uint64_t i; |
589 | ctf_dtdef_ref ctftype; |
590 | |
591 | if (!ctfc->ctfc_num_global_funcs) return; |
592 | |
593 | for (i = 0; i < ctfc->ctfc_num_global_funcs; i++) |
594 | { |
595 | ctftype = ctfc->ctfc_gfuncs_list[i]; |
596 | /* Offset to the name in CTF string table. */ |
597 | dw2_asm_output_data (4, ctftype->dtd_data.ctti_name, "funcinfo_name" ); |
598 | } |
599 | } |
600 | |
601 | /* Output the CTF variables. Variables appear in the sorted ASCIIbetical |
602 | order of their names. This permits binary searching in the CTF reader. */ |
603 | |
604 | static void |
605 | output_ctf_vars (ctf_container_ref ctfc) |
606 | { |
607 | size_t i; |
608 | unsigned int num_ctf_vars = ctfc->ctfc_vars_list_count; |
609 | if (num_ctf_vars) |
610 | { |
611 | /* Iterate over the list of sorted vars and output the asm. */ |
612 | for (i = 0; i < num_ctf_vars; i++) |
613 | { |
614 | ctf_asm_varent (var: ctfc->ctfc_vars_list[i]); |
615 | /* The type of variable must be a valid one. */ |
616 | gcc_assert (ctfc->ctfc_vars_list[i]->dvd_type != CTF_NULL_TYPEID); |
617 | } |
618 | } |
619 | } |
620 | |
621 | /* Output the CTF string records. */ |
622 | |
623 | static void |
624 | output_ctf_strs (ctf_container_ref ctfc) |
625 | { |
626 | ctf_string_t * ctf_string = ctfc->ctfc_strtable.ctstab_head; |
627 | |
628 | while (ctf_string) |
629 | { |
630 | dw2_asm_output_nstring (ctf_string->cts_str, -1, "ctf_string" ); |
631 | ctf_string = ctf_string->cts_next; |
632 | } |
633 | } |
634 | |
635 | /* Output the members of the CTF struct or union. */ |
636 | |
637 | static void |
638 | output_asm_ctf_sou_fields (ctf_container_ref ARG_UNUSED (ctfc), |
639 | ctf_dtdef_ref dtd) |
640 | { |
641 | ctf_dmdef_t * dmd; |
642 | |
643 | /* Function pointer to dump struct/union members. */ |
644 | void (*ctf_asm_sou_field_func) (ctf_dmdef_t *); |
645 | |
646 | uint32_t size = dtd->dtd_data.ctti_size; |
647 | |
648 | /* The variable length data struct/union CTF types is an array of |
649 | ctf_member or ctf_lmember, depending on size of the member. */ |
650 | if (size >= CTF_LSTRUCT_THRESH) |
651 | ctf_asm_sou_field_func = ctf_asm_sou_lmember; |
652 | else |
653 | ctf_asm_sou_field_func = ctf_asm_sou_member; |
654 | |
655 | for (dmd = dtd->dtd_u.dtu_members; |
656 | dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) |
657 | { |
658 | ctf_asm_sou_field_func (dmd); |
659 | /* Sanity Check - Unrepresented types appear as explicit types. */ |
660 | gcc_assert (dmd->dmd_type != CTF_NULL_TYPEID); |
661 | } |
662 | } |
663 | |
664 | /* Output the list of enumerator constants of the CTF enum type. */ |
665 | |
666 | static void |
667 | output_asm_ctf_enum_list (ctf_container_ref ARG_UNUSED (ctfc), |
668 | ctf_dtdef_ref dtd) |
669 | { |
670 | ctf_dmdef_t * dmd; |
671 | |
672 | for (dmd = dtd->dtd_u.dtu_members; |
673 | dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) |
674 | ctf_asm_enum_const (dmd); |
675 | } |
676 | |
677 | /* Output the list of function arguments of the CTF function type. */ |
678 | |
679 | static void |
680 | output_asm_func_args_list (ctf_container_ref ARG_UNUSED (ctfc), |
681 | ctf_dtdef_ref dtd) |
682 | { |
683 | ctf_func_arg_t * farg; |
684 | |
685 | for (farg = dtd->dtd_u.dtu_argv; |
686 | farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg)) |
687 | ctf_asm_func_arg (farg); |
688 | } |
689 | |
690 | /* Output the variable length portion of the CTF type record. */ |
691 | |
692 | static void |
693 | output_asm_ctf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref ctftype) |
694 | { |
695 | uint32_t encoding; |
696 | uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info); |
697 | uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info); |
698 | |
699 | switch (kind) |
700 | { |
701 | case CTF_K_INTEGER: |
702 | case CTF_K_FLOAT: |
703 | if (kind == CTF_K_INTEGER) |
704 | { |
705 | encoding = CTF_INT_DATA (ctftype->dtd_u.dtu_enc.cte_format, |
706 | ctftype->dtd_u.dtu_enc.cte_offset, |
707 | ctftype->dtd_u.dtu_enc.cte_bits); |
708 | } |
709 | else |
710 | { |
711 | encoding = CTF_FP_DATA (ctftype->dtd_u.dtu_enc.cte_format, |
712 | ctftype->dtd_u.dtu_enc.cte_offset, |
713 | ctftype->dtd_u.dtu_enc.cte_bits); |
714 | } |
715 | dw2_asm_output_data (4, encoding, "ctf_encoding_data" ); |
716 | break; |
717 | case CTF_K_FUNCTION: |
718 | { |
719 | output_asm_func_args_list (ctfc, dtd: ctftype); |
720 | /* FIXME - CTF_PADDING_FOR_ALIGNMENT. |
721 | libctf expects this padding for alignment reasons. Expected to |
722 | be redundant in CTF_VERSION_4. */ |
723 | if (vlen & 1) |
724 | dw2_asm_output_data (4, 0, "dtu_argv_padding" ); |
725 | |
726 | break; |
727 | } |
728 | case CTF_K_ARRAY: |
729 | ctf_asm_array (dtd: ctftype); |
730 | break; |
731 | case CTF_K_SLICE: |
732 | { |
733 | ctf_asm_slice (type: ctftype); |
734 | /* Type of the slice must be a valid CTF type. */ |
735 | gcc_assert (ctftype->dtd_u.dtu_slice.cts_type != CTF_NULL_TYPEID); |
736 | break; |
737 | } |
738 | case CTF_K_STRUCT: |
739 | case CTF_K_UNION: |
740 | output_asm_ctf_sou_fields (ctfc, dtd: ctftype); |
741 | break; |
742 | case CTF_K_ENUM: |
743 | output_asm_ctf_enum_list (ctfc, dtd: ctftype); |
744 | break; |
745 | |
746 | default: |
747 | /* CTF types of kind CTF_K_VOLATILE, CTF_K_CONST, CTF_K_RESTRICT, |
748 | etc have no vlen data to write. */ |
749 | break; |
750 | } |
751 | } |
752 | |
753 | /* Output a CTF Type. */ |
754 | |
755 | static void |
756 | output_asm_ctf_type (ctf_container_ref ctfc, ctf_dtdef_ref type) |
757 | { |
758 | if (type->dtd_data.ctti_size <= CTF_MAX_SIZE) |
759 | ctf_asm_stype (type); |
760 | else |
761 | ctf_asm_type (type); |
762 | /* Now comes the variable-length portion for defining types completely. |
763 | E.g., encoding follows CTF_INT_DATA, CTF_FP_DATA types, |
764 | struct ctf_array_t follows CTF_K_ARRAY types, or a bunch of |
765 | struct ctf_member / ctf_lmember ctf_enum sit in there for CTF_K_STRUCT or |
766 | CTF_K_UNION. */ |
767 | output_asm_ctf_vlen_bytes (ctfc, ctftype: type); |
768 | |
769 | uint32_t kind = CTF_V2_INFO_KIND (type->dtd_data.ctti_info); |
770 | /* The underlying type must be a valid CTF type. */ |
771 | if (kind == CTF_K_POINTER || kind == CTF_K_TYPEDEF |
772 | || kind == CTF_K_VOLATILE || kind == CTF_K_CONST |
773 | || kind == CTF_K_RESTRICT) |
774 | gcc_assert (type->dtd_data.ctti_type != CTF_NULL_TYPEID); |
775 | } |
776 | |
777 | /* Output all CTF type records. */ |
778 | |
779 | static void |
780 | output_ctf_types (ctf_container_ref ctfc) |
781 | { |
782 | size_t i; |
783 | size_t num_ctf_types = ctfc->ctfc_types->elements (); |
784 | if (num_ctf_types) |
785 | { |
786 | /* Type ID = 0 is used as sentinel value; not a valid type. */ |
787 | for (i = 1; i <= num_ctf_types; i++) |
788 | output_asm_ctf_type (ctfc, type: ctfc->ctfc_types_list[i]); |
789 | } |
790 | } |
791 | |
792 | /* CTF routines interfacing to the compiler. */ |
793 | |
794 | /* Prepare and output the CTF section. */ |
795 | |
796 | void |
797 | ctf_output (const char * filename) |
798 | { |
799 | if (ctf_debug_info_level == CTFINFO_LEVEL_NONE) |
800 | return; |
801 | |
802 | /* Get the CTF container for the current translation unit. */ |
803 | ctf_container_ref tu_ctfc = ctf_get_tu_ctfc (); |
804 | |
805 | init_ctf_sections (); |
806 | |
807 | ctf_add_cuname (tu_ctfc, filename); |
808 | |
809 | /* Pre-process CTF before generating assembly. */ |
810 | ctf_preprocess (ctfc: tu_ctfc); |
811 | output_ctf_header (ctfc: tu_ctfc); |
812 | output_ctf_obj_info (ctfc: tu_ctfc); |
813 | output_ctf_func_info (ctfc: tu_ctfc); |
814 | output_ctf_objtidx (ctfc: tu_ctfc); |
815 | output_ctf_funcidx (ctfc: tu_ctfc); |
816 | output_ctf_vars (ctfc: tu_ctfc); |
817 | output_ctf_types (ctfc: tu_ctfc); |
818 | output_ctf_strs (ctfc: tu_ctfc); |
819 | |
820 | /* The total number of string bytes must be equal to those processed out to |
821 | the str subsection. */ |
822 | gcc_assert (tu_ctfc->ctfc_strlen |
823 | == ctfc_get_strtab_len (tu_ctfc, CTF_STRTAB)); |
824 | |
825 | } |
826 | |
827 | /* Reset all state for CTF generation so that we can rerun the compiler within |
828 | the same process. */ |
829 | |
830 | void |
831 | ctf_finalize (void) |
832 | { |
833 | ctf_info_section = NULL; |
834 | |
835 | ctf_container_ref tu_ctfc = ctf_get_tu_ctfc (); |
836 | ctfc_delete_container (tu_ctfc); |
837 | tu_ctfc = NULL; |
838 | } |
839 | |
840 | #include "gt-ctfout.h" |
841 | |