From patchwork Mon May 20 17:54:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Indu Bhagat X-Patchwork-Id: 1102288 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-501245-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=oracle.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ieucobKi"; dkim=pass (2048-bit key; unprotected) header.d=oracle.com header.i=@oracle.com header.b="M0a36yKG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45766J5YWhz9s3Z for ; Tue, 21 May 2019 03:56:56 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=ej/WfZh0rSqr8Ff5diCjUfqIVg9++CMUQcznzhBcgzGGiHQ15kF8X BaRXL5/W02iqvOVCRCh/28VzQK9W4e0xUDXXEiRVdls9WC/2oT58cRhtei+qi4IK Q7su87G2DvxRvzUvJXh6yWzCQRFEeJddx46cDQUiUhXXg2BXBG7z7I= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:in-reply-to:references; s=default; bh=bX0T7r9/7E+puO1u//6EBKZ+8As=; b=ieucobKi4dqB97b+0ymKqSVzxv+8 WDCUSALWi+CPiV5G+tHuryIjAbD/7UowM/nYB6HBG6uYW2j8Z3j52N1zuCeq/sa5 tT1k+IcQIxOXgKALw0r0wZyuespJBWj+qwSYxC4he7agnyDkCK9k/1j3bc8oZ6jt bnmoyw7mccY9m+Y= Received: (qmail 3541 invoked by alias); 20 May 2019 17:56:29 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 3459 invoked by uid 89); 20 May 2019 17:56:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_SHORT, SPF_HELO_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 spammy=compressed, transparent, compose, traditionally X-HELO: userp2120.oracle.com Received: from userp2120.oracle.com (HELO userp2120.oracle.com) (156.151.31.85) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 May 2019 17:56:22 +0000 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x4KHiPC2091483 for ; Mon, 20 May 2019 17:56:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : subject : date : message-id : in-reply-to : references; s=corp-2018-07-02; bh=tlVmDS5+HpA2KB5FL6yOaU4Ziaxh9WHnAfiW25owRow=; b=M0a36yKGIN1QPgp/rdrKXaFy5JovX9j1G6HwuHHvCHzyCt+TnHoInGYq2JhpGCfNyX+T E0knKw22C5yovXJzwE0oHQCMZLlBocVbrIxWhw8IL7Xp0IjfieCMSPaO/4Hs965wbk6D 6jmqH4qADpgZlyP+G1/rPeWUo7P54PQ/Ahp3m5se4y+Yv7T/qeiw39UU87GF+7rbf1mM aVaetLEwYDvB7DBy9Un8JB9u0/gXz3nuSIebRU4suR/6/dsd88qVXGJtX7RNyomdGdUJ Hlv0Gwouj31/FCrOCcBV275GgEjlJ617BjhVPZ+lrvhkZrhl7dXFKlS74VCr6m3kujxz qg== Received: from userp3020.oracle.com (userp3020.oracle.com [156.151.31.79]) by userp2120.oracle.com with ESMTP id 2sjapq8gc2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 20 May 2019 17:56:20 +0000 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x4KHrhqJ129628 for ; Mon, 20 May 2019 17:54:20 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userp3020.oracle.com with ESMTP id 2sks1j02fr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 20 May 2019 17:54:20 +0000 Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id x4KHsJtY030795 for ; Mon, 20 May 2019 17:54:19 GMT Received: from ibhagatpc.us.oracle.com (/10.65.131.217) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 20 May 2019 17:54:19 +0000 From: Indu Bhagat To: gcc-patches@gcc.gnu.org Subject: [PATCH,RFC 3/3] Create CTF debug hooks Date: Mon, 20 May 2019 10:54:15 -0700 Message-Id: <1558374855-19140-4-git-send-email-indu.bhagat@oracle.com> In-Reply-To: <1558374855-19140-1-git-send-email-indu.bhagat@oracle.com> References: <1558374855-19140-1-git-send-email-indu.bhagat@oracle.com> Initialize CTF debug hooks when -gtLEVEL is specified. Import the CTF header from binutils. gcc/ChangeLog: * Makefile.in: Add ctfout.* files to GTFILES. * ctfout.c: New file. * ctfout.h: Likewise. * debug.h (ctf_debug_init): New function. * gengtype.c (open_base_files): Add ctfout.h to ifiles. * toplev.c (process_options): Warn and ignore -gtLEVEL if frontend is not C. (toplev::finalize): Finalize CTF containers. gcc/testsuite/ChangeLog: * gcc.dg/debug/ctf/ctf-1.c: New test. * gcc.dg/debug/ctf/ctf-preamble-1.c: Likewise. * gcc.dg/debug/ctf/ctf.exp: Add CTF testsuite. * gcc.dg/debug/dwarf2-ctf-1.c: New test. include/ChangeLog: * ctf.h: Import from binutils. --- gcc/ChangeLog | 11 + gcc/Makefile.in | 3 + gcc/ctfout.c | 171 +++++++++ gcc/ctfout.h | 41 +++ gcc/debug.h | 4 + gcc/gengtype.c | 4 +- gcc/testsuite/ChangeLog | 7 + gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c | 6 + gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c | 11 + gcc/testsuite/gcc.dg/debug/ctf/ctf.exp | 41 +++ gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c | 7 + gcc/toplev.c | 24 ++ include/ChangeLog | 4 + include/ctf.h | 471 ++++++++++++++++++++++++ 14 files changed, 803 insertions(+), 2 deletions(-) create mode 100644 gcc/ctfout.c create mode 100644 gcc/ctfout.h create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c create mode 100644 include/ctf.h diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 6677f77..44d9078 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1254,6 +1254,7 @@ OBJS = \ cfgloopanal.o \ cfgloopmanip.o \ cfgrtl.o \ + ctfout.o \ symtab.o \ cgraph.o \ cgraphbuild.o \ @@ -2532,6 +2533,8 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/dwarf2asm.c \ $(srcdir)/dwarf2cfi.c \ $(srcdir)/dwarf2out.c \ + $(srcdir)/ctfout.h \ + $(srcdir)/ctfout.c \ $(srcdir)/tree-vect-generic.c \ $(srcdir)/dojump.c $(srcdir)/emit-rtl.h \ $(srcdir)/emit-rtl.c $(srcdir)/except.h $(srcdir)/explow.c $(srcdir)/expr.c \ diff --git a/gcc/ctfout.c b/gcc/ctfout.c new file mode 100644 index 0000000..9e9c48f --- /dev/null +++ b/gcc/ctfout.c @@ -0,0 +1,171 @@ +/* Output ctf format from GCC. + Copyright (C) 2019 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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "rtl.h" +#include "tree.h" +#include "memmodel.h" +#include "tm_p.h" +#include "varasm.h" +#include "output.h" +#include "dwarf2asm.h" +#include "debug.h" +#include "ctfout.h" + +/* CTF debug hooks. This is initialized by ctf_debug_init. */ +static struct gcc_debug_hooks ctf_debug_hooks; + +/* The real debug hooks. */ +static const struct gcc_debug_hooks *real_debug_hooks; + +/* A CTF container object - one per translation unit. */ +static GTY(()) ctf_container_ref ctf_container; + +static int ctf_label_num; + +/* Pointers to various ctf sections. */ +static GTY(()) section *ctf_info_section; + +/* Section names used to hold CTF debugging information. */ +#ifndef CTF_INFO_SECTION_NAME +#define CTF_INFO_SECTION_NAME ".ctf" +#endif + +/* Section flags for .ctf section. */ + +/* 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 + +/* Forward declarations for functions defined in this file. */ +static inline ctf_container_ref +new_ctf_container (unsigned char ctp_flags); + +static void output_ctf_preamble (void); +static void output_ctf_header (void); + +/* Allocate a new ctf container with the desired flags. */ +static inline ctf_container_ref +new_ctf_container (unsigned char ctp_flags) +{ + ctf_container = ggc_cleared_alloc (); + + ctf_container->ctf_magic = CTF_MAGIC; + ctf_container->ctf_version = CTF_VERSION; + ctf_container->ctf_flags = ctp_flags; + + return ctf_container; +} + +static inline void +delete_ctf_container (ctf_container_ref ctfc) +{ + ggc_free (ctfc); + ctfc = NULL; +} +/* Initialize a ctf container per translation unit. */ +static void +init_ctf_containers (void) +{ + ctf_container = new_ctf_container (0); +} + +/* Output the ctf preamble. */ +static void +output_ctf_preamble (void) +{ + dw2_asm_output_data (2, ctf_container->ctf_magic, + "CTF preamble magic number"); + dw2_asm_output_data (1, ctf_container->ctf_version, "CTF preamble version"); + dw2_asm_output_data (1, ctf_container->ctf_flags, "CTF preamble flags"); +} + +/* Output the ctf header. */ +static void +output_ctf_header (void) +{ + switch_to_section (ctf_info_section); + ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label); + + output_ctf_preamble (); +} + +/* Initialize the various sections and labels for ctf output. */ +void +init_ctf_sections (void) +{ + /* CTF debug info is generated for C frontend only, at the moment. */ + + 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++); +} + +static void +ctf_define (unsigned int lineno, const char *buffer) +{ + real_debug_hooks->define (lineno, buffer); +} + +static void +ctf_finish (const char *filename) +{ + init_ctf_sections (); + init_ctf_containers (); + + output_ctf_header (); + + real_debug_hooks->finish (filename); +} + +const struct gcc_debug_hooks * +ctf_debug_init (const struct gcc_debug_hooks *hooks) +{ + ctf_debug_hooks = *hooks; + real_debug_hooks = hooks; + + ctf_debug_hooks.finish = ctf_finish; + ctf_debug_hooks.define = ctf_define; + + return &ctf_debug_hooks; +} + +/* Reset all state within ctfout.c sot that we can rerun the compiler + within the same process. For use by toplev::finalize. */ +void ctfout_c_finalize (void) +{ + ctf_info_section = NULL; + + delete_ctf_container (ctf_container); +} + +#include "gt-ctfout.h" diff --git a/gcc/ctfout.h b/gcc/ctfout.h new file mode 100644 index 0000000..c129d6d --- /dev/null +++ b/gcc/ctfout.h @@ -0,0 +1,41 @@ +/* ctfout.h - Various declarations for functions found in ctfout.c + Copyright (C) 2019 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 +. */ + +#ifndef GCC_CTFOUT_H +#define GCC_CTFOUT_H 1 + +#include "ctf.h" + +/* A ctf container for the context passed around when generating ctf debug + * info. There is one container per translation unit. */ +typedef struct GTY(()) ctf_container +{ + /* CTF Preamble. */ + unsigned short ctf_magic; + unsigned char ctf_version; + unsigned char ctf_flags; + /* Global type definitions. */ + // htab_t ctf_types; +} ctf_container_t; + +typedef ctf_container_t * ctf_container_ref; + +void ctfout_c_finalize (void); + +#endif /* GCC_CTFOUT_H */ diff --git a/gcc/debug.h b/gcc/debug.h index 412e7ca..846784e 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -256,6 +256,10 @@ extern bool dwarf2out_default_as_locview_support (void); extern const struct gcc_debug_hooks * dump_go_spec_init (const char *, const struct gcc_debug_hooks *); +/* For CTF debug info generation setup. */ +extern const struct gcc_debug_hooks * +ctf_debug_init (const struct gcc_debug_hooks *); + /* Instance discriminator mapping table. See final.c. */ typedef hash_map decl_to_instance_map_t; extern decl_to_instance_map_t *decl_to_instance_map; diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 5331733..39de737 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1724,8 +1724,8 @@ open_base_files (void) "tree-dfa.h", "tree-ssa.h", "reload.h", "cpplib.h", "tree-chrec.h", "except.h", "output.h", "cfgloop.h", "target.h", "lto-streamer.h", "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h", - "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h", - "omp-offload.h", NULL + "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "ctfout.h", + "omp-general.h", "omp-offload.h", NULL }; const char *const *ifp; outf_p gtype_desc_c; diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c new file mode 100644 index 0000000..1be0dfb --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-gt" } */ + +void func(void) +{ +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c new file mode 100644 index 0000000..fa377ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c @@ -0,0 +1,11 @@ +/* Verify the CTF preamble in the ctf section. */ + +/* { dg-do compile ) */ +/* { dg-options "-O0 -gt -dA" } */ +/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */ +/* { dg-final { scan-assembler "0x4.*CTF preamble version" } } */ +/* { dg-final { scan-assembler "0.*CTF preamble flags" } } */ + +void func (void) +{ +} diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp new file mode 100644 index 0000000..46055f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2002-2019 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +# Disable on ptx (in sync with DWARF testsuite) +if { [istarget nvptx-*-*] } { + return +} + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\] ]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c new file mode 100644 index 0000000..4ffa8ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c @@ -0,0 +1,7 @@ +/* Verify that CTF debug info can co-exist with other debug formats. */ +/* { dg-do compile } */ +/* { dg-options "-gt -dA" } */ +/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */ + +void func (void) +{ } diff --git a/gcc/toplev.c b/gcc/toplev.c index d300ac2..3e0028a 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -72,6 +72,7 @@ along with GCC; see the file COPYING3. If not see #include "pass_manager.h" #include "auto-profile.h" #include "dwarf2out.h" +#include "ctfout.h" #include "ipa-reference.h" #include "symbol-summary.h" #include "tree-vrp.h" @@ -1312,6 +1313,8 @@ parse_alignment_opts (void) static void process_options (void) { + const char *language_string = lang_hooks.name; + /* Just in case lang_hooks.post_options ends up calling a debug_hook. This can happen with incorrect pre-processed input. */ debug_hooks = &do_nothing_debug_hooks; @@ -1484,6 +1487,17 @@ process_options (void) debug_info_level = DINFO_LEVEL_NONE; } + /* CTF is supported for only C at this time. + Compiling with -flto results in frontend language of GNU GIMPLE. */ + if (!lang_GNU_C () && !lang_GNU_GIMPLE () + && ctf_debug_info_level > CTFINFO_LEVEL_NONE) + { + warning_at (UNKNOWN_LOCATION, 0, + "CTF debug info requested, but not supported for %s frontend", + language_string); + ctf_debug_info_level = CTFINFO_LEVEL_NONE; + } + if (flag_dump_final_insns && !flag_syntax_only && !no_backend) { FILE *final_output = fopen (flag_dump_final_insns, "w"); @@ -1556,6 +1570,15 @@ process_options (void) flag_var_tracking_uninit = 0; } + /* The debug hooks are used to generate ctf debug info. The API of debug + * hooks, hence, cannot be used for both -fdump-go-spec and -gt. */ + if (flag_dump_go_spec != NULL && ctf_debug_info_level > CTFINFO_LEVEL_NONE) + sorry ("CTF debug info generation is not supported with " + "-fdump-go-spec"); + + if (ctf_debug_info_level > CTFINFO_LEVEL_NONE) + debug_hooks = ctf_debug_init (debug_hooks); + /* The debug hooks are used to implement -fdump-go-spec because it gives a simple and stable API for all the information we need to dump. */ @@ -2387,6 +2410,7 @@ toplev::finalize (void) cgraph_c_finalize (); cgraphunit_c_finalize (); dwarf2out_c_finalize (); + ctfout_c_finalize (); gcse_c_finalize (); ipa_cp_c_finalize (); ira_costs_c_finalize (); diff --git a/include/ctf.h b/include/ctf.h new file mode 100644 index 0000000..cab92d1 --- /dev/null +++ b/include/ctf.h @@ -0,0 +1,471 @@ +/* CTF format description. + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of libctf. + + libctf is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not see + . */ + +#ifndef _CTF_H +#define _CTF_H + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* CTF - Compact ANSI-C Type Format + + This file format can be used to compactly represent the information needed + by a debugger to interpret the ANSI-C types used by a given program. + Traditionally, this kind of information is generated by the compiler when + invoked with the -g flag and is stored in "stabs" strings or in the more + modern DWARF format. CTF provides a representation of only the information + that is relevant to debugging a complex, optimized C program such as the + operating system kernel in a form that is significantly more compact than + the equivalent stabs or DWARF representation. The format is data-model + independent, so consumers do not need different code depending on whether + they are 32-bit or 64-bit programs; libctf automatically compensates for + endianness variations. CTF assumes that a standard ELF symbol table is + available for use in the debugger, and uses the structure and data of the + symbol table to avoid storing redundant information. The CTF data may be + compressed on disk or in memory, indicated by a bit in the header. CTF may + be interpreted in a raw disk file, or it may be stored in an ELF section, + typically named .ctf. Data structures are aligned so that a raw CTF file or + CTF ELF section may be manipulated using mmap(2). + + The CTF file or section itself has the following structure: + + +--------+--------+---------+----------+----------+-------+--------+ + | file | type | data | function | variable | data | string | + | header | labels | objects | info | info | types | table | + +--------+--------+---------+----------+----------+-------+--------+ + + The file header stores a magic number and version information, encoding + flags, and the byte offset of each of the sections relative to the end of the + header itself. If the CTF data has been uniquified against another set of + CTF data, a reference to that data also appears in the the header. This + reference is the name of the label corresponding to the types uniquified + against. + + Following the header is a list of labels, used to group the types included in + the data types section. Each label is accompanied by a type ID i. A given + label refers to the group of types whose IDs are in the range [0, i]. + + Data object and function records are stored in the same order as they appear + in the corresponding symbol table, except that symbols marked SHN_UNDEF are + not stored and symbols that have no type data are padded out with zeroes. + For each data object, the type ID (a small integer) is recorded. For each + function, the type ID of the return type and argument types is recorded. + + Variable records (as distinct from data objects) provide a modicum of support + for non-ELF systems, mapping a variable name to a CTF type ID. The variable + names are sorted into ASCIIbetical order, permitting binary searching. + + The data types section is a list of variable size records that represent each + type, in order by their ID. The types themselves form a directed graph, + where each node may contain one or more outgoing edges to other type nodes, + denoted by their ID. + + Strings are recorded as a string table ID (0 or 1) and a byte offset into the + string table. String table 0 is the internal CTF string table. String table + 1 is the external string table, which is the string table associated with the + ELF symbol table for this object. CTF does not record any strings that are + already in the symbol table, and the CTF string table does not contain any + duplicated strings. + + If the CTF data has been merged with another parent CTF object, some outgoing + edges may refer to type nodes that exist in another CTF object. The debugger + and libctf library are responsible for connecting the appropriate objects + together so that the full set of types can be explored and manipulated. + + This connection is done purely using the ctf_import() function. There is no + notation anywhere in the child CTF file indicating which parent it is + connected to: it is the debugger's responsibility to track this. */ + +#define CTF_MAX_TYPE 0xfffffffe /* Max type identifier value. */ +#define CTF_MAX_PTYPE 0x7fffffff /* Max parent type identifier value. */ +#define CTF_MAX_NAME 0x7fffffff /* Max offset into a string table. */ +#define CTF_MAX_VLEN 0xffffff /* Max struct, union, enum members or args. */ + +/* See ctf_type_t */ +#define CTF_MAX_SIZE 0xfffffffe /* Max size of a v2 type in bytes. */ +#define CTF_LSIZE_SENT 0xffffffff /* Sentinel for v2 ctt_size. */ + + + /* Start of actual data structure definitions. + + Every field in these structures must have corresponding code in the + endianness-swapping machinery in libctf/ctf-open.c. */ + +typedef struct ctf_preamble +{ + unsigned short ctp_magic; /* Magic number (CTF_MAGIC). */ + unsigned char ctp_version; /* Data format version number (CTF_VERSION). */ + unsigned char ctp_flags; /* Flags (see below). */ +} ctf_preamble_t; + +typedef struct ctf_header +{ + ctf_preamble_t cth_preamble; + uint32_t cth_parlabel; /* Ref to name of parent lbl uniq'd against. */ + uint32_t cth_parname; /* Ref to basename of parent. */ + uint32_t cth_lbloff; /* Offset of label section. */ + uint32_t cth_objtoff; /* Offset of object section. */ + uint32_t cth_funcoff; /* Offset of function section. */ + uint32_t cth_varoff; /* Offset of variable section. */ + uint32_t cth_typeoff; /* Offset of type section. */ + uint32_t cth_stroff; /* Offset of string section. */ + uint32_t cth_strlen; /* Length of string section in bytes. */ +} ctf_header_t; + +#define cth_magic cth_preamble.ctp_magic +#define cth_version cth_preamble.ctp_version +#define cth_flags cth_preamble.ctp_flags + +#define CTF_MAGIC 0xdff2 /* Magic number identifying header. */ + +/* Data format version number. */ + + +#define CTF_VERSION_3 4 +#define CTF_VERSION CTF_VERSION_3 /* Current version. */ + +#define CTF_F_COMPRESS 0x1 /* Data buffer is compressed by libctf. */ + +typedef struct ctf_lblent +{ + uint32_t ctl_label; /* Ref to name of label. */ + uint32_t ctl_type; /* Last type associated with this label. */ +} ctf_lblent_t; + +typedef struct ctf_varent +{ + uint32_t ctv_name; /* Reference to name in string table. */ + uint32_t ctv_type; /* Index of type of this variable. */ +} ctf_varent_t; + +/* In format v2, type sizes, measured in bytes, come in two flavours. Nearly + all of them fit into a (UINT_MAX - 1), and thus can be stored in the ctt_size + member of a ctf_stype_t. The maximum value for these sizes is CTF_MAX_SIZE. + Types larger than this must be stored in the ctf_lsize member of a + ctf_type_t. Use of this member is indicated by the presence of + CTF_LSIZE_SENT in ctt_size. */ + +typedef struct ctf_stype +{ + uint32_t ctt_name; /* Reference to name in string table. */ + uint32_t ctt_info; /* Encoded kind, variant length (see below). */ +#ifndef __GNUC__ + union + { + uint32_t _size; /* Size of entire type in bytes. */ + uint32_t _type; /* Reference to another type. */ + } _u; +#else + __extension__ + union + { + uint32_t ctt_size; /* Size of entire type in bytes. */ + uint32_t ctt_type; /* Reference to another type. */ + }; +#endif +} ctf_stype_t; + +typedef struct ctf_type +{ + uint32_t ctt_name; /* Reference to name in string table. */ + uint32_t ctt_info; /* Encoded kind, variant length (see below). */ +#ifndef __GNUC__ +union + { + uint32_t _size; /* Always CTF_LSIZE_SENT. */ + uint32_t _type; /* Do not use. */ + } _u; +#else + __extension__ + union + { + uint32_t ctt_size; /* Always CTF_LSIZE_SENT. */ + uint32_t ctt_type; /* Do not use. */ + }; +#endif + uint32_t ctt_lsizehi; /* High 32 bits of type size in bytes. */ + uint32_t ctt_lsizelo; /* Low 32 bits of type size in bytes. */ +} ctf_type_t; + +#ifndef __GNUC__ +#define ctt_size _u._size /* For fundamental types that have a size. */ +#define ctt_type _u._type /* For types that reference another type. */ +#endif + +/* The following macros and inline functions compose and decompose values for + ctt_info and ctt_name, as well as other structures that contain name + references. Use outside libdtrace-ctf itself is explicitly for access to CTF + files directly: types returned from the library will always appear to be + CTF_V2. + + v1: (transparently upgraded to v2 at open time: may be compiled out of the + library) + ------------------------ + ctt_info: | kind | isroot | vlen | + ------------------------ + 15 11 10 9 0 + + v2: + ------------------------ + ctt_info: | kind | isroot | vlen | + ------------------------ + 31 26 25 24 0 + + CTF_V1 and V2 _INFO_VLEN have the same interface: + + kind = CTF_*_INFO_KIND(c.ctt_info); <-- CTF_K_* value (see below) + vlen = CTF_*_INFO_VLEN(fp, c.ctt_info); <-- length of variable data list + + stid = CTF_NAME_STID(c.ctt_name); <-- string table id number (0 or 1) + offset = CTF_NAME_OFFSET(c.ctt_name); <-- string table byte offset + + c.ctt_info = CTF_TYPE_INFO(kind, vlen); + c.ctt_name = CTF_TYPE_NAME(stid, offset); */ + + +#define CTF_V2_INFO_KIND(info) (((info) & 0xfc000000) >> 26) +#define CTF_V2_INFO_ISROOT(info) (((info) & 0x2000000) >> 25) +#define CTF_V2_INFO_VLEN(info) (((info) & CTF_MAX_VLEN)) + +#define CTF_NAME_STID(name) ((name) >> 31) +#define CTF_NAME_OFFSET(name) ((name) & CTF_MAX_NAME) + +/* V2 only. */ +#define CTF_TYPE_INFO(kind, isroot, vlen) \ + (((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_MAX_VLEN)) + +#define CTF_TYPE_NAME(stid, offset) \ + (((stid) << 31) | ((offset) & CTF_MAX_NAME)) + +/* The next set of macros are for public consumption only. Not used internally, + since the relevant type boundary is dependent upon the version of the file at + *opening* time, not the version after transparent upgrade. Use + ctf_type_isparent() / ctf_type_ischild() for that. */ + +#define CTF_V2_TYPE_ISPARENT(fp, id) ((id) <= CTF_MAX_PTYPE) +#define CTF_V2_TYPE_ISCHILD(fp, id) ((id) > CTF_MAX_PTYPE) +#define CTF_V2_TYPE_TO_INDEX(id) ((id) & CTF_MAX_PTYPE) +#define CTF_V2_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE+1)) : (id)) + + +/* Valid for both V1 and V2. */ +#define CTF_TYPE_LSIZE(cttp) \ + (((uint64_t)(cttp)->ctt_lsizehi) << 32 | (cttp)->ctt_lsizelo) +#define CTF_SIZE_TO_LSIZE_HI(size) ((uint32_t)((uint64_t)(size) >> 32)) +#define CTF_SIZE_TO_LSIZE_LO(size) ((uint32_t)(size)) + +#define CTF_STRTAB_0 0 /* String table id 0 (in-CTF). */ +#define CTF_STRTAB_1 1 /* String table id 1 (ELF strtab). */ + +/* Values for CTF_TYPE_KIND(). If the kind has an associated data list, + CTF_INFO_VLEN() will extract the number of elements in the list, and + the type of each element is shown in the comments below. */ + +#define CTF_K_UNKNOWN 0 /* Unknown type (used for padding). */ +#define CTF_K_INTEGER 1 /* Variant data is CTF_INT_DATA (see below). */ +#define CTF_K_FLOAT 2 /* Variant data is CTF_FP_DATA (see below). */ +#define CTF_K_POINTER 3 /* ctt_type is referenced type. */ +#define CTF_K_ARRAY 4 /* Variant data is single ctf_array_t. */ +#define CTF_K_FUNCTION 5 /* ctt_type is return type, variant data is + list of argument types (unsigned short's for v1, + uint32_t's for v2). */ +#define CTF_K_STRUCT 6 /* Variant data is list of ctf_member_t's. */ +#define CTF_K_UNION 7 /* Variant data is list of ctf_member_t's. */ +#define CTF_K_ENUM 8 /* Variant data is list of ctf_enum_t's. */ +#define CTF_K_FORWARD 9 /* No additional data; ctt_name is tag. */ +#define CTF_K_TYPEDEF 10 /* ctt_type is referenced type. */ +#define CTF_K_VOLATILE 11 /* ctt_type is base type. */ +#define CTF_K_CONST 12 /* ctt_type is base type. */ +#define CTF_K_RESTRICT 13 /* ctt_type is base type. */ +#define CTF_K_SLICE 14 /* Variant data is a ctf_slice_t. */ + +#define CTF_K_MAX 63 /* Maximum possible (V2) CTF_K_* value. */ + +/* Values for ctt_type when kind is CTF_K_INTEGER. The flags, offset in bits, + and size in bits are encoded as a single word using the following macros. + (However, you can also encode the offset and bitness in a slice.) */ + +#define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24) +#define CTF_INT_OFFSET(data) (((data) & 0x00ff0000) >> 16) +#define CTF_INT_BITS(data) (((data) & 0x0000ffff)) + +#define CTF_INT_DATA(encoding, offset, bits) \ + (((encoding) << 24) | ((offset) << 16) | (bits)) + +#define CTF_INT_SIGNED 0x01 /* Integer is signed (otherwise unsigned). */ +#define CTF_INT_CHAR 0x02 /* Character display format. */ +#define CTF_INT_BOOL 0x04 /* Boolean display format. */ +#define CTF_INT_VARARGS 0x08 /* Varargs display format. */ + +/* Use CTF_CHAR to produce a char that agrees with the system's native + char signedness. */ +#if CHAR_MIN == 0 +# define CTF_CHAR (CTF_INT_CHAR) +#else +# define CTF_CHAR (CTF_INT_CHAR | CTF_INT_SIGNED) +#endif + +/* Values for ctt_type when kind is CTF_K_FLOAT. The encoding, offset in bits, + and size in bits are encoded as a single word using the following macros. + (However, you can also encode the offset and bitness in a slice.) */ + +#define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) +#define CTF_FP_OFFSET(data) (((data) & 0x00ff0000) >> 16) +#define CTF_FP_BITS(data) (((data) & 0x0000ffff)) + +#define CTF_FP_DATA(encoding, offset, bits) \ + (((encoding) << 24) | ((offset) << 16) | (bits)) + +/* Variant data when kind is CTF_K_FLOAT is an encoding in the top eight bits. */ +#define CTF_FP_ENCODING(data) (((data) & 0xff000000) >> 24) + +#define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding. */ +#define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding. */ +#define CTF_FP_CPLX 3 /* Complex encoding. */ +#define CTF_FP_DCPLX 4 /* Double complex encoding. */ +#define CTF_FP_LDCPLX 5 /* Long double complex encoding. */ +#define CTF_FP_LDOUBLE 6 /* Long double encoding. */ +#define CTF_FP_INTRVL 7 /* Interval (2x32-bit) encoding. */ +#define CTF_FP_DINTRVL 8 /* Double interval (2x64-bit) encoding. */ +#define CTF_FP_LDINTRVL 9 /* Long double interval (2x128-bit) encoding. */ +#define CTF_FP_IMAGRY 10 /* Imaginary (32-bit) encoding. */ +#define CTF_FP_DIMAGRY 11 /* Long imaginary (64-bit) encoding. */ +#define CTF_FP_LDIMAGRY 12 /* Long double imaginary (128-bit) encoding. */ + +#define CTF_FP_MAX 12 /* Maximum possible CTF_FP_* value */ + +/* A slice increases the offset and reduces the bitness of the referenced + ctt_type, which must be a type which has an encoding (fp, int, or enum). We + also store the referenced type in here, because it is easier to keep the + ctt_size correct for the slice than to shuffle the size into here and keep + the ctt_type where it is for other types. */ + +typedef struct ctf_slice +{ + uint32_t cts_type; + unsigned char cts_offset; + unsigned char cts_bits; +} ctf_slice_t; + +typedef struct ctf_array_v1 +{ + unsigned short cta_contents; /* Reference to type of array contents. */ + unsigned short cta_index; /* Reference to type of array index. */ + uint32_t cta_nelems; /* Number of elements. */ +} ctf_array_v1_t; + +typedef struct ctf_array +{ + uint32_t cta_contents; /* Reference to type of array contents. */ + uint32_t cta_index; /* Reference to type of array index. */ + uint32_t cta_nelems; /* Number of elements. */ +} ctf_array_t; + +/* Most structure members have bit offsets that can be expressed using a short. + Some don't. ctf_member_t is used for structs which cannot contain any of + these large offsets, whereas ctf_lmember_t is used in the latter case. If + any member of a given struct has an offset that cannot be expressed using a + uint32_t, all members will be stored as type ctf_lmember_t. This is expected + to be very rare (but nonetheless possible). */ + +#define CTF_LSTRUCT_THRESH 536870912 + + +typedef struct ctf_member_v2 +{ + uint32_t ctm_name; /* Reference to name in string table. */ + uint32_t ctm_offset; /* Offset of this member in bits. */ + uint32_t ctm_type; /* Reference to type of member. */ +} ctf_member_t; + +typedef struct ctf_lmember_v2 +{ + uint32_t ctlm_name; /* Reference to name in string table. */ + uint32_t ctlm_offsethi; /* High 32 bits of member offset in bits. */ + uint32_t ctlm_type; /* Reference to type of member. */ + uint32_t ctlm_offsetlo; /* Low 32 bits of member offset in bits. */ +} ctf_lmember_t; + +#define CTF_LMEM_OFFSET(ctlmp) \ + (((uint64_t)(ctlmp)->ctlm_offsethi) << 32 | (ctlmp)->ctlm_offsetlo) +#define CTF_OFFSET_TO_LMEMHI(offset) ((uint32_t)((uint64_t)(offset) >> 32)) +#define CTF_OFFSET_TO_LMEMLO(offset) ((uint32_t)(offset)) + +typedef struct ctf_enum +{ + uint32_t cte_name; /* Reference to name in string table. */ + int cte_value; /* Value associated with this name. */ +} ctf_enum_t; + +/* The ctf_archive is a collection of ctf_file_t's stored together. The format + is suitable for mmap()ing: this control structure merely describes the + mmap()ed archive (and overlaps the first few bytes of it), hence the + greater care taken with integral types. All CTF files in an archive + must have the same data model. (This is not validated.) + + All integers in this structure are stored in little-endian byte order. + + The code relies on the fact that everything in this header is a uint64_t + and thus the header needs no padding (in particular, that no padding is + needed between ctfa_ctfs and the unnamed ctfa_archive_modent array + that follows it). */ + +#define CTFA_MAGIC 0x8b47f2a4d7623eeb /* Random. */ +struct ctf_archive +{ + /* Magic number. (In loaded files, overwritten with the file size + so ctf_arc_close() knows how much to munmap()). */ + uint64_t ctfa_magic; + + /* CTF data model. */ + uint64_t ctfa_model; + + /* Number of CTF files in the archive. */ + uint64_t ctfa_nfiles; + + /* Offset of the name table. */ + uint64_t ctfa_names; + + /* Offset of the CTF table. Each element starts with a size (a uint64_t + in network byte order) then a ctf_file_t of that size. */ + uint64_t ctfa_ctfs; +}; + +/* An array of ctfa_nnamed of this structure lies at + ctf_archive[ctf_archive->ctfa_modents] and gives the ctfa_ctfs or + ctfa_names-relative offsets of each name or ctf_file_t. */ + +typedef struct ctf_archive_modent +{ + uint64_t name_offset; + uint64_t ctf_offset; +} ctf_archive_modent_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _CTF_H */