aboutsummaryrefslogtreecommitdiff
path: root/gcc/ctfout.c
diff options
context:
space:
mode:
authorIndu Bhagat <indu.bhagat@oracle.com>2021-05-20 11:15:52 -0700
committerJose E. Marchesi <jose.marchesi@oracle.com>2021-06-28 18:47:20 +0200
commitb7e215a8ee81d44281d9e0a2a25eceb47b6911dd (patch)
tree121afbbec2428c85a68b6119ac8c0f25f6cd9fab /gcc/ctfout.c
parent532617d6367c29803d5909f2432b1ebfb9ee1886 (diff)
downloadgcc-b7e215a8ee81d44281d9e0a2a25eceb47b6911dd.zip
gcc-b7e215a8ee81d44281d9e0a2a25eceb47b6911dd.tar.gz
gcc-b7e215a8ee81d44281d9e0a2a25eceb47b6911dd.tar.bz2
CTF/BTF debug formats
This commit introduces support for generating CTF debugging information and BTF debugging information from GCC. 2021-06-28 Indu Bhagat <indu.bhagat@oracle.com> David Faust <david.faust@oracle.com> Jose E. Marchesi <jose.marchesi@oracle.com> Weimin Pan <weimin.pan@oracle.com> gcc/ * Makefile.in: Add ctfc.*, ctfout.c and btfout.c files to GTFILES. Add new object files. * common.opt: Add CTF and BTF debug info options. * btfout.c: New file. * ctfc.c: Likewise. * ctfc.h: Likewise. * ctfout.c: Likewise. * dwarf2ctf.c: Likewise. * dwarf2ctf.h: Likewise. * dwarf2cfi.c (dwarf2out_do_frame): Acknowledge CTF_DEBUG and BTF_DEBUG. * dwarf2out.c (dwarf2out_source_line): Likewise. (dwarf2out_finish): Skip emitting DWARF if CTF or BTF are to be generated. (debug_format_do_cu): New function. (dwarf2out_early_finish): Traverse DIEs and emit CTF/BTF for them if requested. Include dwarf2ctf.c. * final.c (dwarf2_debug_info_emitted_p): Acknowledge DWARF-based debug formats. * flag-types.h (enum debug_info_type): Add CTF_DEBUG and BTF_DEBUG. (CTF_DEBUG): New bitmask. (BTF_DEBUG): Likewise. (enum ctf_debug_info_levels): New enum. * gengtype.c (open_base_files): Handle ctfc.h. (main): Handle uint32_t type. * flags.h (btf_debuginfo_p): New definition. (dwarf_based_debuginfo_p): Likewise. * opts.c (debug_type_names): Add entries for CTF and BTF. (btf_debuginfo_p): New function. (dwarf_based_debuginfo_p): Likewise. (common_handle_option): Handle -gctfN and -gbtf options. (set_debug_level): Set CTF_DEBUG, BTF_DEBUG whenever appropriate. * toplev.c (process_options): Inform the user and ignore -gctfLEVEL if frontend is not C. include/ * ctf.h: New file. * btf.h: Likewise. libiberty/ * simple-object.c (handle_lto_debug_sections): Copy over .ctf sections.
Diffstat (limited to 'gcc/ctfout.c')
-rw-r--r--gcc/ctfout.c830
1 files changed, 830 insertions, 0 deletions
diff --git a/gcc/ctfout.c b/gcc/ctfout.c
new file mode 100644
index 0000000..c264fd6
--- /dev/null
+++ b/gcc/ctfout.c
@@ -0,0 +1,830 @@
+/* Output CTF format from GCC.
+ Copyright (C) 2019,2021 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "output.h"
+#include "dwarf2asm.h"
+#include "debug.h"
+#include "ctfc.h"
+#include "diagnostic-core.h"
+
+static int ctf_label_num;
+
+/* Pointers to various CTF sections. */
+
+static GTY (()) section * ctf_info_section;
+
+/* Section names used to hold CTF debugging information. */
+
+/* CTF debug info section. */
+
+#ifndef CTF_INFO_SECTION_NAME
+#define CTF_INFO_SECTION_NAME ".ctf"
+#endif
+
+/* Section flags for the CTF debug info section. */
+
+#define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG)
+
+/* Maximum size (in bytes) of an artificially generated CTF label. */
+
+#define MAX_CTF_LABEL_BYTES 40
+
+static char ctf_info_section_label[MAX_CTF_LABEL_BYTES];
+
+#ifndef CTF_INFO_SECTION_LABEL
+#define CTF_INFO_SECTION_LABEL "Lctf"
+#endif
+
+/* CTF preprocess callback arguments. */
+
+typedef struct ctf_dtd_preprocess_arg
+{
+ uint64_t dtd_global_func_idx;
+ ctf_container_ref dtd_arg_ctfc;
+} ctf_dtd_preprocess_arg_t;
+
+typedef struct ctf_dvd_preprocess_arg
+{
+ uint64_t dvd_global_obj_idx;
+ ctf_container_ref dvd_arg_ctfc;
+} ctf_dvd_preprocess_arg_t;
+
+/* Compare two CTF variable definition entries. Currently used for sorting
+ by name. */
+
+static int
+ctf_varent_compare (const void * entry1, const void * entry2)
+{
+ int result;
+ const ctf_dvdef_t * e1 = *(const ctf_dvdef_t * const*) entry1;
+ const ctf_dvdef_t * e2 = *(const ctf_dvdef_t * const*) entry2;
+
+ result = strcmp (e1->dvd_name, e2->dvd_name);
+
+ return result;
+}
+
+/* A CTF type record may be followed by variable-length of bytes to encode the
+ CTF type completely. This routine calculates the number of bytes, in the
+ final binary CTF format, which are used to encode information about the type
+ completely.
+
+ This function must always be in sync with the CTF header. */
+
+static uint64_t
+ctf_calc_num_vbytes (ctf_dtdef_ref ctftype)
+{
+ uint32_t size;
+ uint64_t vlen_bytes = 0;
+
+ uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+ uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+
+ ctf_dmdef_t * dmd;
+ ctf_func_arg_t * farg;
+ uint32_t size_per_member = 0;
+ unsigned int num_members = 0;
+ unsigned int num_fargs = 0;
+
+ switch (kind)
+ {
+ case CTF_K_FORWARD:
+ case CTF_K_UNKNOWN:
+ case CTF_K_POINTER:
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ /* These types have no vlen data. */
+ break;
+
+ case CTF_K_INTEGER:
+ case CTF_K_FLOAT:
+ /* 4 bytes to represent encoding CTF_INT_DATA, CTF_FP_DATA. */
+ vlen_bytes += sizeof (uint32_t);
+ break;
+ case CTF_K_FUNCTION:
+ /* Sanity check - number of function args must be the same as
+ vlen. */
+ for (farg = ctftype->dtd_u.dtu_argv;
+ farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg))
+ num_fargs++;
+ gcc_assert (vlen == num_fargs);
+
+ /* FIXME - CTF_PADDING_FOR_ALIGNMENT. */
+ vlen_bytes += (vlen + (vlen & 1)) * sizeof (uint32_t);
+ break;
+ case CTF_K_ARRAY:
+ /* This has a single ctf_array_t. */
+ vlen_bytes += sizeof (ctf_array_t);
+ break;
+ case CTF_K_SLICE:
+ vlen_bytes += sizeof (ctf_slice_t);
+ break;
+ case CTF_K_STRUCT:
+ case CTF_K_UNION:
+ /* Count the number and type of members. */
+ size = ctftype->dtd_data.ctti_size;
+ size_per_member = size >= CTF_LSTRUCT_THRESH
+ ? sizeof (ctf_lmember_t) : sizeof (ctf_member_t);
+
+ /* Sanity check - number of members of struct must be the same as
+ vlen. */
+ for (dmd = ctftype->dtd_u.dtu_members;
+ dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+ num_members++;
+ gcc_assert (vlen == num_members);
+
+ vlen_bytes += (num_members * size_per_member);
+ break;
+ case CTF_K_ENUM:
+ vlen_bytes += vlen * sizeof (ctf_enum_t);
+ break;
+ default :
+ break;
+ }
+ return vlen_bytes;
+}
+
+/* Add a CTF variable to the end of the list. */
+
+static void
+ctf_list_add_ctf_vars (ctf_container_ref ctfc, ctf_dvdef_ref var)
+{
+ /* FIXME - static may not fly with multiple CUs. */
+ static int num_vars_added = 0;
+ ctfc->ctfc_vars_list[num_vars_added++] = var;
+}
+
+/* Initialize the various sections and labels for CTF output. */
+
+void
+init_ctf_sections (void)
+{
+ /* Note : Even in case of LTO, the compiler continues to generate a single
+ CTF section for each compilation unit "early". Unlike other debug
+ sections, CTF sections are non-LTO sections, and do not take the
+ .gnu.debuglto_ prefix. The linker will de-duplicate the types in the CTF
+ sections, in case of LTO or otherwise. */
+ ctf_info_section = get_section (CTF_INFO_SECTION_NAME, CTF_INFO_SECTION_FLAGS,
+ NULL);
+
+ ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label,
+ CTF_INFO_SECTION_LABEL, ctf_label_num++);
+}
+
+/* Routines for CTF pre-processing. */
+
+static void
+ctf_preprocess_var (ctf_container_ref ctfc, ctf_dvdef_ref var)
+{
+ /* Add it to the list of types. This array of types will be sorted before
+ assembling into output. */
+ ctf_list_add_ctf_vars (ctfc, var);
+}
+
+/* CTF preprocess callback routine for CTF variables. */
+
+int
+ctf_dvd_preprocess_cb (ctf_dvdef_ref * slot, void * arg)
+{
+ ctf_dvd_preprocess_arg_t * dvd_arg = (ctf_dvd_preprocess_arg_t *)arg;
+ ctf_dvdef_ref var = (ctf_dvdef_ref) *slot;
+ ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc;
+
+ ctf_preprocess_var (arg_ctfc, var);
+
+ /* Keep track of global objts. */
+ arg_ctfc->ctfc_gobjts_list[dvd_arg->dvd_global_obj_idx] = var;
+ dvd_arg->dvd_global_obj_idx++;
+
+ return 1;
+}
+
+/* CTF preprocess callback routine for CTF types. */
+
+int
+ctf_dtd_preprocess_cb (ctf_dtdef_ref * slot, void * arg)
+{
+ uint32_t kind;
+
+ ctf_dtdef_ref ctftype = (ctf_dtdef_ref) *slot;
+ ctf_dtd_preprocess_arg_t * dtd_arg = (ctf_dtd_preprocess_arg_t *)arg;
+ ctf_container_ref arg_ctfc = dtd_arg->dtd_arg_ctfc;
+
+ size_t index = ctftype->dtd_type;
+ gcc_assert (index <= arg_ctfc->ctfc_types->elements ());
+
+ /* CTF types need to be output in the order of their type IDs. In other
+ words, if type A is used to define type B, type ID of type A must
+ appear before type ID of type B. */
+ arg_ctfc->ctfc_types_list[index] = ctftype;
+
+ /* Keep track of the CTF type if it's a function type and the type
+ was generated from a function object. */
+ kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+ if (kind == CTF_K_FUNCTION && ctftype->from_global_func)
+ {
+ arg_ctfc->ctfc_gfuncs_list[dtd_arg->dtd_global_func_idx] = ctftype;
+ dtd_arg->dtd_global_func_idx++;
+ }
+
+ /* Calculate the vlen bytes. */
+ arg_ctfc->ctfc_num_vlen_bytes += ctf_calc_num_vbytes (ctftype);
+
+ return 1;
+}
+
+/* CTF preprocessing.
+ After the CTF types for the compilation unit have been generated fully, the
+ compiler writes out the asm for the CTF types.
+
+ CTF writeout in the compiler requires two passes over the CTF types. In the
+ first pass, the CTF preprocess pass:
+ 1. CTF types are sorted in the order of their type IDs.
+ 2. The variable number of bytes after each CTF type record are calculated.
+ This is used to calculate the offsets in the ctf_header_t.
+ 3. If the CTF type is of CTF_K_FUNCTION, the number of bytes in the
+ funcinfo sub-section are calculated. This is used to calculate the
+ offsets in the ctf_header_t.
+ 4. Keep the list of CTF variables in ASCIIbetical order of their names.
+
+ In the second pass, the CTF writeout pass, asm tags are written out using
+ the compiler's afore-generated internal pre-processed CTF types. */
+
+static void
+ctf_preprocess (ctf_container_ref ctfc)
+{
+ size_t num_ctf_types = ctfc->ctfc_types->elements ();
+
+ /* Initialize an array to keep track of the CTF variables at global
+ scope. */
+ size_t num_global_objts = ctfc->ctfc_num_global_objts;
+ if (num_global_objts)
+ {
+ ctfc->ctfc_gobjts_list = ggc_vec_alloc<ctf_dvdef_t*>(num_global_objts);
+ }
+
+ size_t num_ctf_vars = ctfc->ctfc_vars->elements ();
+ if (num_ctf_vars)
+ {
+ ctf_dvd_preprocess_arg_t dvd_arg;
+ dvd_arg.dvd_global_obj_idx = 0;
+ dvd_arg.dvd_arg_ctfc = ctfc;
+
+ /* Allocate CTF var list. */
+ ctfc->ctfc_vars_list = ggc_vec_alloc<ctf_dvdef_ref>(num_ctf_vars);
+ /* Variables appear in the sort ASCIIbetical order of their names. This
+ permits binary searching in the CTF reader. Add the variables to a
+ list for sorting. */
+ ctfc->ctfc_vars->traverse<void *, ctf_dvd_preprocess_cb> (&dvd_arg);
+ /* Sort the list. */
+ qsort (ctfc->ctfc_vars_list, num_ctf_vars, sizeof (ctf_dvdef_ref),
+ ctf_varent_compare);
+ }
+
+ /* Initialize an array to keep track of the CTF functions types for global
+ functions in the CTF data section. */
+ size_t num_global_funcs = ctfc->ctfc_num_global_funcs;
+ if (num_global_funcs)
+ {
+ ctfc->ctfc_gfuncs_list = ggc_vec_alloc<ctf_dtdef_t*>(num_global_funcs);
+ gcc_assert (num_ctf_types);
+ }
+
+ if (num_ctf_types)
+ {
+ ctf_dtd_preprocess_arg_t dtd_arg;
+ dtd_arg.dtd_global_func_idx = 0;
+ dtd_arg.dtd_arg_ctfc = ctfc;
+ /* Allocate the CTF types list. Add 1 because type ID 0 is never a valid
+ CTF type ID. No CTF type record should appear at that offset, this
+ eases debugging and readability. */
+ ctfc->ctfc_types_list = ggc_vec_alloc<ctf_dtdef_ref>(num_ctf_types + 1);
+ /* Pre-process CTF types. */
+ ctfc->ctfc_types->traverse<void *, ctf_dtd_preprocess_cb> (&dtd_arg);
+
+ gcc_assert (dtd_arg.dtd_global_func_idx == num_global_funcs);
+ }
+}
+
+/* CTF asm helper routines. */
+
+/* Asm'out the CTF preamble. */
+
+static void
+ctf_asm_preamble (ctf_container_ref ctfc)
+{
+ dw2_asm_output_data (2, ctfc->ctfc_magic,
+ "CTF preamble magic number");
+ dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version");
+ dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags");
+}
+
+/* Asm'out a CTF type which is represented by ctf_stype_t. */
+
+static void
+ctf_asm_stype (ctf_dtdef_ref type)
+{
+ dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name");
+ dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info");
+ /* union. */
+ dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size or ctt_type");
+}
+
+/* Asm'out a CTF type which is represented by ctf_type_t. */
+
+static void
+ctf_asm_type (ctf_dtdef_ref type)
+{
+ dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name");
+ dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info");
+ /* union. */
+ dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size");
+ dw2_asm_output_data (4, type->dtd_data.ctti_lsizehi, "ctt_lsizehi");
+ dw2_asm_output_data (4, type->dtd_data.ctti_lsizelo, "ctt_lsizelo");
+}
+
+/* Asm'out a CTF type of kind CTF_K_SLICE. */
+
+static void
+ctf_asm_slice (ctf_dtdef_ref type)
+{
+ dw2_asm_output_data (4, type->dtd_u.dtu_slice.cts_type, "cts_type");
+ dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_offset, "cts_offset");
+ dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_bits, "cts_bits");
+}
+
+/* Asm'out a CTF type of kind CTF_K_ARRAY. */
+
+static void
+ctf_asm_array (ctf_dtdef_ref dtd)
+{
+ dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_contents, "cta_contents");
+ dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_index, "cta_index");
+ dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_nelems, "cta_nelems");
+}
+
+/* Asm'out a CTF variable. */
+
+static void
+ctf_asm_varent (ctf_dvdef_ref var)
+{
+ /* Output the reference to the name in the string table. */
+ dw2_asm_output_data (4, var->dvd_name_offset, "ctv_name");
+ /* Output the type index. */
+ dw2_asm_output_data (4, var->dvd_type, "ctv_typeidx");
+}
+
+/* Asm'out a member of CTF struct or union, represented by ctf_lmember_t. */
+
+static void
+ctf_asm_sou_lmember (ctf_dmdef_t * dmd)
+{
+ dw2_asm_output_data (4, dmd->dmd_name_offset, "ctlm_name");
+ dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset),
+ "ctlm_offsethi");
+ dw2_asm_output_data (4, dmd->dmd_type, "ctlm_type");
+ dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset),
+ "ctlm_offsetlo");
+}
+
+/* Asm'out a member of a CTF sruct or union, represented by ctf_member_t. */
+
+static void
+ctf_asm_sou_member (ctf_dmdef_t * dmd)
+{
+ dw2_asm_output_data (4, dmd->dmd_name_offset, "ctm_name");
+ dw2_asm_output_data (4, dmd->dmd_offset, "ctm_offset");
+ dw2_asm_output_data (4, dmd->dmd_type, "ctm_type");
+}
+
+/* Asm'out an enumerator constant. */
+
+static void
+ctf_asm_enum_const (ctf_dmdef_t * dmd)
+{
+ dw2_asm_output_data (4, dmd->dmd_name_offset, "cte_name");
+ dw2_asm_output_data (4, dmd->dmd_value, "cte_value");
+}
+
+/* Asm'out a function argument. */
+
+static void
+ctf_asm_func_arg (ctf_func_arg_t * farg)
+{
+ dw2_asm_output_data (4, farg->farg_type, "dtu_argv");
+}
+
+/* CTF writeout to asm file. */
+
+static void
+output_ctf_header (ctf_container_ref ctfc)
+{
+ switch_to_section (ctf_info_section);
+ ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label);
+
+ ctf_asm_preamble (ctfc);
+
+ /* For a single compilation unit, the parent container's name and label are
+ NULL. */
+ dw2_asm_output_data (4, 0, "cth_parlabel");
+ dw2_asm_output_data (4, 0, "cth_parname");
+ dw2_asm_output_data (4, ctfc->ctfc_cuname_offset, "cth_cuname");
+
+ int typeslen = 0;
+ /* Initialize the offsets. The offsets are from after the CTF header. */
+ uint32_t lbloff = 0;
+ uint32_t objtoff = 0;
+ uint32_t funcoff = 0;
+ uint32_t objtidxoff = 0;
+ uint32_t funcidxoff = 0;
+ uint32_t varoff = 0;
+ uint32_t typeoff = 0;
+ uint32_t stroff = 0;
+
+ if (!ctfc_is_empty_container (ctfc))
+ {
+ gcc_assert (ctfc_get_num_ctf_types (ctfc)
+ == (ctfc->ctfc_num_types + ctfc->ctfc_num_stypes));
+
+ funcoff = objtoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t);
+ /* Object index appears after function info. */
+ objtidxoff = funcoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t);
+ /* Funxtion index goes next. */
+ funcidxoff = objtidxoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t);
+ /* Vars appear after function index. */
+ varoff = funcidxoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t);
+ /* CTF types appear after vars. */
+ typeoff = varoff + ctfc_get_num_ctf_vars (ctfc) * sizeof (ctf_varent_t);
+ /* The total number of bytes for CTF types is the sum of the number of
+ times struct ctf_type_t, struct ctf_stype_t are written, plus the
+ amount of variable length data after each one of these. */
+ typeslen = ctfc->ctfc_num_types * sizeof (ctf_type_t)
+ + ctfc->ctfc_num_stypes * (sizeof (ctf_stype_t))
+ + ctfc_get_num_vlen_bytes (ctfc);
+
+ /* Strings appear after types. */
+ stroff = typeoff + typeslen;
+ }
+
+ /* Offset of label section. */
+ dw2_asm_output_data (4, lbloff, "cth_lbloff");
+ /* Offset of object section. */
+ dw2_asm_output_data (4, objtoff, "cth_objtoff");
+ /* Offset of function section. */
+ dw2_asm_output_data (4, funcoff, "cth_funcoff");
+ /* Offset of object index section. */
+ dw2_asm_output_data (4, objtidxoff, "cth_objtidxoff");
+ /* Offset of function index section. */
+ dw2_asm_output_data (4, funcidxoff, "cth_funcidxoff");
+
+ /* Offset of variable section. */
+ dw2_asm_output_data (4, varoff, "cth_varoff");
+ /* Offset of type section. */
+ dw2_asm_output_data (4, typeoff, "cth_typeoff");
+ /* Offset of string section. */
+ dw2_asm_output_data (4, stroff, "cth_stroff");
+ /* Length of string section in bytes. */
+ dw2_asm_output_data (4, ctfc->ctfc_strlen, "cth_strlen");
+}
+
+/* Output the CTF object info section. */
+
+static void
+output_ctf_obj_info (ctf_container_ref ctfc)
+{
+ uint64_t i;
+ ctf_dvdef_ref var;
+
+ if (!ctfc->ctfc_num_global_objts) return;
+
+ /* Compiler spits out the objts (at global scope) in the CTF obj info section.
+ In no specific order. In an object file, the CTF object index section is
+ used to associate the objts to their corresponding names. */
+ for (i = 0; i < ctfc->ctfc_num_global_objts; i++)
+ {
+ var = ctfc->ctfc_gobjts_list[i];
+
+ /* CTF type ID corresponding to the type of the variable. */
+ dw2_asm_output_data (4, var->dvd_type, "objtinfo_var_type");
+ }
+
+}
+
+/* Output the CTF function info section. */
+
+static void
+output_ctf_func_info (ctf_container_ref ctfc)
+{
+ uint64_t i;
+ ctf_dtdef_ref ctftype;
+
+ if (!ctfc->ctfc_num_global_funcs) return;
+
+ /* The CTF funcinfo section is simply an array of CTF_K_FUNCTION type IDs in
+ the type section. In an object file, the CTF function index section is
+ used to associate functions to their corresponding names. */
+ for (i = 0; i < ctfc->ctfc_num_global_funcs; i++)
+ {
+ ctftype = ctfc->ctfc_gfuncs_list[i];
+ dw2_asm_output_data (4, ctftype->dtd_type, "funcinfo_func_type");
+ }
+}
+
+/* Output the CTF object index section. */
+
+static void
+output_ctf_objtidx (ctf_container_ref ctfc)
+{
+ uint64_t i;
+ ctf_dvdef_ref var;
+
+ if (!ctfc->ctfc_num_global_objts) return;
+
+ for (i = 0; i < ctfc->ctfc_num_global_objts; i++)
+ {
+ var = ctfc->ctfc_gobjts_list[i];
+ /* Offset to the name in CTF string table. */
+ dw2_asm_output_data (4, var->dvd_name_offset, "objtinfo_name");
+ }
+}
+
+/* Output the CTF function index section. */
+
+static void
+output_ctf_funcidx (ctf_container_ref ctfc)
+{
+ uint64_t i;
+ ctf_dtdef_ref ctftype;
+
+ if (!ctfc->ctfc_num_global_funcs) return;
+
+ for (i = 0; i < ctfc->ctfc_num_global_funcs; i++)
+ {
+ ctftype = ctfc->ctfc_gfuncs_list[i];
+ /* Offset to the name in CTF string table. */
+ dw2_asm_output_data (4, ctftype->dtd_data.ctti_name, "funcinfo_name");
+ }
+}
+
+/* Output the CTF variables. Variables appear in the sorted ASCIIbetical
+ order of their names. This permits binary searching in the CTF reader. */
+
+static void
+output_ctf_vars (ctf_container_ref ctfc)
+{
+ size_t i;
+ size_t num_ctf_vars = ctfc->ctfc_vars->elements ();
+ if (num_ctf_vars)
+ {
+ /* Iterate over the list of sorted vars and output the asm. */
+ for (i = 0; i < num_ctf_vars; i++)
+ {
+ ctf_asm_varent (ctfc->ctfc_vars_list[i]);
+ /* The type of variable must be a valid one. */
+ gcc_assert (ctfc->ctfc_vars_list[i]->dvd_type != CTF_NULL_TYPEID);
+ }
+ }
+}
+
+/* Output the CTF string records. */
+
+static void
+output_ctf_strs (ctf_container_ref ctfc)
+{
+ ctf_string_t * ctf_string = ctfc->ctfc_strtable.ctstab_head;
+
+ while (ctf_string)
+ {
+ dw2_asm_output_nstring (ctf_string->cts_str, -1, "ctf_string");
+ ctf_string = ctf_string->cts_next;
+ }
+}
+
+/* Output the members of the CTF struct or union. */
+
+static void
+output_asm_ctf_sou_fields (ctf_container_ref ARG_UNUSED (ctfc),
+ ctf_dtdef_ref dtd)
+{
+ ctf_dmdef_t * dmd;
+
+ /* Function pointer to dump struct/union members. */
+ void (*ctf_asm_sou_field_func) (ctf_dmdef_t *);
+
+ uint32_t size = dtd->dtd_data.ctti_size;
+
+ /* The variable length data struct/union CTF types is an array of
+ ctf_member or ctf_lmember, depending on size of the member. */
+ if (size >= CTF_LSTRUCT_THRESH)
+ ctf_asm_sou_field_func = ctf_asm_sou_lmember;
+ else
+ ctf_asm_sou_field_func = ctf_asm_sou_member;
+
+ for (dmd = dtd->dtd_u.dtu_members;
+ dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+ {
+ ctf_asm_sou_field_func (dmd);
+ /* Sanity Check - Unrepresented types appear as explicit types. */
+ gcc_assert (dmd->dmd_type != CTF_NULL_TYPEID);
+ }
+}
+
+/* Output the list of enumerator constants of the CTF enum type. */
+
+static void
+output_asm_ctf_enum_list (ctf_container_ref ARG_UNUSED (ctfc),
+ ctf_dtdef_ref dtd)
+{
+ ctf_dmdef_t * dmd;
+
+ for (dmd = dtd->dtd_u.dtu_members;
+ dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+ ctf_asm_enum_const (dmd);
+}
+
+/* Output the list of function arguments of the CTF function type. */
+
+static void
+output_asm_func_args_list (ctf_container_ref ARG_UNUSED (ctfc),
+ ctf_dtdef_ref dtd)
+{
+ ctf_func_arg_t * farg;
+
+ for (farg = dtd->dtd_u.dtu_argv;
+ farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg))
+ ctf_asm_func_arg (farg);
+}
+
+/* Output the variable length portion of the CTF type record. */
+
+static void
+output_asm_ctf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref ctftype)
+{
+ uint32_t encoding;
+ uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+ uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+
+ switch (kind)
+ {
+ case CTF_K_INTEGER:
+ case CTF_K_FLOAT:
+ if (kind == CTF_K_INTEGER)
+ {
+ encoding = CTF_INT_DATA (ctftype->dtd_u.dtu_enc.cte_format,
+ ctftype->dtd_u.dtu_enc.cte_offset,
+ ctftype->dtd_u.dtu_enc.cte_bits);
+ }
+ else
+ {
+ encoding = CTF_FP_DATA (ctftype->dtd_u.dtu_enc.cte_format,
+ ctftype->dtd_u.dtu_enc.cte_offset,
+ ctftype->dtd_u.dtu_enc.cte_bits);
+ }
+ dw2_asm_output_data (4, encoding, "ctf_encoding_data");
+ break;
+ case CTF_K_FUNCTION:
+ {
+ output_asm_func_args_list (ctfc, ctftype);
+ /* FIXME - CTF_PADDING_FOR_ALIGNMENT.
+ libctf expects this padding for alignment reasons. Expected to
+ be redundant in CTF_VERSION_4. */
+ if (vlen & 1)
+ dw2_asm_output_data (4, 0, "dtu_argv_padding");
+
+ break;
+ }
+ case CTF_K_ARRAY:
+ ctf_asm_array (ctftype);
+ break;
+ case CTF_K_SLICE:
+ {
+ ctf_asm_slice (ctftype);
+ /* Type of the slice must be a valid CTF type. */
+ gcc_assert (ctftype->dtd_u.dtu_slice.cts_type != CTF_NULL_TYPEID);
+ break;
+ }
+ case CTF_K_STRUCT:
+ case CTF_K_UNION:
+ output_asm_ctf_sou_fields (ctfc, ctftype);
+ break;
+ case CTF_K_ENUM:
+ output_asm_ctf_enum_list (ctfc, ctftype);
+ break;
+
+ default:
+ /* CTF types of kind CTF_K_VOLATILE, CTF_K_CONST, CTF_K_RESTRICT,
+ etc have no vlen data to write. */
+ break;
+ }
+}
+
+/* Output a CTF Type. */
+
+static void
+output_asm_ctf_type (ctf_container_ref ctfc, ctf_dtdef_ref type)
+{
+ if (type->dtd_data.ctti_size <= CTF_MAX_SIZE)
+ ctf_asm_stype (type);
+ else
+ ctf_asm_type (type);
+ /* Now comes the variable-length portion for defining types completely.
+ E.g., encoding follows CTF_INT_DATA, CTF_FP_DATA types,
+ struct ctf_array_t follows CTF_K_ARRAY types, or a bunch of
+ struct ctf_member / ctf_lmember ctf_enum sit in there for CTF_K_STRUCT or
+ CTF_K_UNION. */
+ output_asm_ctf_vlen_bytes (ctfc, type);
+
+ uint32_t kind = CTF_V2_INFO_KIND (type->dtd_data.ctti_info);
+ /* The underlying type must be a valid CTF type. */
+ if (kind == CTF_K_POINTER || kind == CTF_K_TYPEDEF
+ || kind == CTF_K_VOLATILE || kind == CTF_K_CONST
+ || kind == CTF_K_RESTRICT)
+ gcc_assert (type->dtd_data.ctti_type != CTF_NULL_TYPEID);
+}
+
+/* Output all CTF type records. */
+
+static void
+output_ctf_types (ctf_container_ref ctfc)
+{
+ size_t i;
+ size_t num_ctf_types = ctfc->ctfc_types->elements ();
+ if (num_ctf_types)
+ {
+ /* Type ID = 0 is used as sentinel value; not a valid type. */
+ for (i = 1; i <= num_ctf_types; i++)
+ output_asm_ctf_type (ctfc, ctfc->ctfc_types_list[i]);
+ }
+}
+
+/* CTF routines interfacing to the compiler. */
+
+/* Prepare and output the CTF section. */
+
+void
+ctf_output (const char * filename)
+{
+ if (ctf_debug_info_level == CTFINFO_LEVEL_NONE)
+ return;
+
+ /* Get the CTF container for the current translation unit. */
+ ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
+
+ init_ctf_sections ();
+
+ ctf_add_cuname (tu_ctfc, filename);
+
+ /* Pre-process CTF before generating assembly. */
+ ctf_preprocess (tu_ctfc);
+ output_ctf_header (tu_ctfc);
+ output_ctf_obj_info (tu_ctfc);
+ output_ctf_func_info (tu_ctfc);
+ output_ctf_objtidx (tu_ctfc);
+ output_ctf_funcidx (tu_ctfc);
+ output_ctf_vars (tu_ctfc);
+ output_ctf_types (tu_ctfc);
+ output_ctf_strs (tu_ctfc);
+
+ /* The total number of string bytes must be equal to those processed out to
+ the str subsection. */
+ gcc_assert (tu_ctfc->ctfc_strlen
+ == ctfc_get_strtab_len (tu_ctfc, CTF_STRTAB));
+
+}
+
+/* Reset all state for CTF generation so that we can rerun the compiler within
+ the same process. */
+
+void
+ctf_finalize (void)
+{
+ ctf_info_section = NULL;
+
+ ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
+ ctfc_delete_container (tu_ctfc);
+ tu_ctfc = NULL;
+}
+
+#include "gt-ctfout.h"