Wolfgang Thallergcc16 merge934c3885 months agoHistory
837 lines · 20.5 KB · C
RawDownload
/* Textual dumping of CTF data.   Copyright (C) 2019-2026 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   <http://www.gnu.org/licenses/>.  */ #include <ctf-impl.h>#include <string.h> #define str_append(s, a) ctf_str_append_noerr (s, a) /* One item to be dumped, in string form.  */ typedef struct ctf_dump_item{  ctf_list_t cdi_list;  char *cdi_item;} ctf_dump_item_t; /* Cross-call state for dumping.  Basically just enough to track the section in   use and a list of return strings.  */ struct ctf_dump_state{  ctf_sect_names_t cds_sect;  ctf_dict_t *cds_fp;  ctf_dump_item_t *cds_current;  ctf_list_t cds_items;}; /* Cross-call state for ctf_dump_member. */ typedef struct ctf_dump_membstate{  char **cdm_str;  ctf_dict_t *cdm_fp;  const char *cdm_toplevel_indent;} ctf_dump_membstate_t; static intctf_dump_append (ctf_dump_state_t *state, char *str){  ctf_dump_item_t *cdi;   if ((cdi = malloc (sizeof (struct ctf_dump_item))) == NULL)    return (ctf_set_errno (state->cds_fp, ENOMEM));   cdi->cdi_item = str;  ctf_list_append (&state->cds_items, cdi);  return 0;} static voidctf_dump_free (ctf_dump_state_t *state){  ctf_dump_item_t *cdi, *next_cdi;   if (state == NULL)    return;   for (cdi = ctf_list_next (&state->cds_items); cdi != NULL;       cdi = next_cdi)    {      free (cdi->cdi_item);      next_cdi = ctf_list_next (cdi);      free (cdi);    }} /* Return a dump for a single type, without member info: but do optionally show   the type's references.  */ #define CTF_FT_REFS     0x2 	/* Print referenced types.  */#define CTF_FT_BITFIELD 0x4	/* Print :BITS if a bitfield.  */#define CTF_FT_ID       0x8	/* Print "ID: " in front of type IDs.  */ static char *ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag){  ctf_id_t new_id;  char *str = NULL, *bit = NULL, *buf = NULL;   ctf_set_errno (fp, 0);  new_id = id;  do    {      ctf_encoding_t ep;      ctf_arinfo_t ar;      int kind, unsliced_kind;      ssize_t size, align;      const char *nonroot_leader = "";      const char *nonroot_trailer = "";      const char *idstr = "";       id = new_id;      if (!(flag & CTF_ADD_ROOT))	{	  nonroot_leader = "{";	  nonroot_trailer = "}";	}       buf = ctf_type_aname (fp, id);      if (!buf)	{	  if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)	    {	      ctf_set_errno (fp, ECTF_NONREPRESENTABLE);	      str = str_append (str, " (type not represented in CTF)");	      return str;	    } 	  goto err;	}       if (flag & CTF_FT_ID)	idstr = "ID ";      if (asprintf (&bit, "%s%s0x%lx: (kind %i) ", nonroot_leader, idstr,		    id, ctf_type_kind (fp, id)) < 0)	goto oom;      str = str_append (str, bit);      free (bit);      bit = NULL;       if (buf[0] != '\0')	str = str_append (str, buf);       free (buf);      buf = NULL;       unsliced_kind = ctf_type_kind_unsliced (fp, id);      kind = ctf_type_kind (fp, id);       /* Report encodings of everything with an encoding other than enums:	 base-type enums cannot have a nonzero cte_offset or cte_bits value.	 (Slices of them can, but they are of kind CTF_K_SLICE.)  */      if (unsliced_kind != CTF_K_ENUM && ctf_type_encoding (fp, id, &ep) == 0)	{	  if ((ssize_t) ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT	      && flag & CTF_FT_BITFIELD)	    {	      if (asprintf (&bit, ":%i", ep.cte_bits) < 0)		goto oom;	      str = str_append (str, bit);	      free (bit);	      bit = NULL;	    } 	  if ((ssize_t) ep.cte_bits != ctf_type_size (fp, id) * CHAR_BIT	      || ep.cte_offset != 0)	    {	      const char *slice = ""; 	      if (unsliced_kind == CTF_K_SLICE)		slice = "slice "; 	      if (asprintf (&bit, " [%s0x%x:0x%x]",			    slice, ep.cte_offset, ep.cte_bits) < 0)		goto oom;	      str = str_append (str, bit);	      free (bit);	      bit = NULL;	    } 	  if (asprintf (&bit, " (format 0x%x)", ep.cte_format) < 0)	    goto oom;	  str = str_append (str, bit);	  free (bit);	  bit = NULL;	}       size = ctf_type_size (fp, id);      if (kind != CTF_K_FUNCTION && size >= 0)	{	  if (asprintf (&bit, " (size 0x%lx)", (unsigned long int) size) < 0)	    goto oom; 	  str = str_append (str, bit);	  free (bit);	  bit = NULL;	}       align = ctf_type_align (fp, id);      if (align >= 0)	{	  if (asprintf (&bit, " (aligned at 0x%lx)",			(unsigned long int) align) < 0)	    goto oom; 	  str = str_append (str, bit);	  free (bit);	  bit = NULL;	}       if (nonroot_trailer[0] != 0)	str = str_append (str, nonroot_trailer);       /* Just exit after one iteration if we are not showing the types this type	 references.  */      if (!(flag & CTF_FT_REFS))	return str;       /* Keep going as long as this type references another.  We consider arrays	 to "reference" their element type. */       if (kind == CTF_K_ARRAY)	{	  if (ctf_array_info (fp, id, &ar) < 0)	    goto err;	  new_id = ar.ctr_contents;	}      else	new_id = ctf_type_reference (fp, id);      if (new_id != CTF_ERR)	str = str_append (str, " -> ");    }  while (new_id != CTF_ERR);   if (ctf_errno (fp) != ECTF_NOTREF)    {      free (str);      return NULL;    }   return str;  oom:  ctf_set_errno (fp, errno); err:  ctf_err_warn (fp, 1, ctf_errno (fp), _("cannot format name dumping type 0x%lx"),		id);  free (buf);  free (str);  free (bit);  return NULL;} /* Dump one string field from the file header into the cds_items.  */static intctf_dump_header_strfield (ctf_dict_t *fp, ctf_dump_state_t *state,			  const char *name, uint32_t value){  char *str;  if (value)    {      if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)	goto err;      ctf_dump_append (state, str);    }  return 0;  err:  return (ctf_set_errno (fp, errno));} /* Dump one section-offset field from the file header into the cds_items.  */static intctf_dump_header_sectfield (ctf_dict_t *fp, ctf_dump_state_t *state,			   const char *sect, uint32_t off, uint32_t nextoff){  char *str;  if (nextoff - off)    {      if (asprintf (&str, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect,		    (unsigned long) off, (unsigned long) (nextoff - 1),		    (unsigned long) (nextoff - off)) < 0)	goto err;      ctf_dump_append (state, str);    }  return 0;  err:  return (ctf_set_errno (fp, errno));} /* Dump the file header into the cds_items.  */static intctf_dump_header (ctf_dict_t *fp, ctf_dump_state_t *state){  char *str;  char *flagstr = NULL;  const ctf_header_t *hp = fp->ctf_header;  const char *vertab[] =    {     NULL, "CTF_VERSION_1",     "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "     "boundaries)",     "CTF_VERSION_2",     "CTF_VERSION_3", NULL    };  const char *verstr = NULL;   if (asprintf (&str, "Magic number: 0x%x\n", hp->cth_magic) < 0)      goto err;  ctf_dump_append (state, str);   if (hp->cth_version <= CTF_VERSION)    verstr = vertab[hp->cth_version];   if (verstr == NULL)    verstr = "(not a valid version)";   if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,		verstr) < 0)    goto err;  ctf_dump_append (state, str);   /* Everything else is only printed if present.  */   /* The flags are unusual in that they represent the ctf_dict_t *in memory*:     flags representing compression, etc, are turned off as the file is     decompressed.  So we store a copy of the flags before they are changed, for     the dumper.  */   if (fp->ctf_openflags > 0)    {      if (asprintf (&flagstr, "%s%s%s%s%s%s%s%s%s",		    fp->ctf_openflags & CTF_F_COMPRESS		    ? "CTF_F_COMPRESS": "",		    (fp->ctf_openflags & CTF_F_COMPRESS)		    && (fp->ctf_openflags & ~CTF_F_COMPRESS)		    ? ", " : "",		    fp->ctf_openflags & CTF_F_NEWFUNCINFO		    ? "CTF_F_NEWFUNCINFO" : "",		    (fp->ctf_openflags & (CTF_F_NEWFUNCINFO))		    && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO))		    ? ", " : "",		    fp->ctf_openflags & CTF_F_IDXSORTED		    ? "CTF_F_IDXSORTED" : "",		    fp->ctf_openflags & (CTF_F_IDXSORTED)		    && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO					      | CTF_F_IDXSORTED))		    ? ", " : "",		    fp->ctf_openflags & CTF_F_ARRNELEMS		    ? "CTF_F_ARRNELEMS" : "",		    fp->ctf_openflags & (CTF_F_ARRNELEMS)		    && (fp->ctf_openflags & ~(CTF_F_COMPRESS | CTF_F_NEWFUNCINFO					      | CTF_F_IDXSORTED | CTF_F_ARRNELEMS))		    ? ", " : "",		    fp->ctf_openflags & CTF_F_DYNSTR		    ? "CTF_F_DYNSTR" : "") < 0)	goto err;       if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags, flagstr) < 0)	goto err;      free (flagstr);      ctf_dump_append (state, str);    }   if (ctf_dump_header_strfield (fp, state, "Parent label",				hp->cth_parlabel) < 0)    goto err;   if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)    goto err;   if (ctf_dump_header_strfield (fp, state, "Compilation unit name",				hp->cth_cuname) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,				 hp->cth_objtoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Data object section",				 hp->cth_objtoff, hp->cth_funcoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Function info section",				 hp->cth_funcoff, hp->cth_objtidxoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Object index section",				 hp->cth_objtidxoff, hp->cth_funcidxoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Function index section",				 hp->cth_funcidxoff, hp->cth_varoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Variable section",				 hp->cth_varoff, hp->cth_typeoff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "Type section",				 hp->cth_typeoff, hp->cth_stroff) < 0)    goto err;   if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,				 hp->cth_stroff + hp->cth_strlen + 1) < 0)    goto err;   return 0; err:  free (flagstr);  return (ctf_set_errno (fp, errno));} /* Dump a single label into the cds_items.  */ static intctf_dump_label (const char *name, const ctf_lblinfo_t *info,		void *arg){  char *str;  char *typestr;  ctf_dump_state_t *state = arg;   if (asprintf (&str, "%s -> ", name) < 0)    return (ctf_set_errno (state->cds_fp, errno));   if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,				       CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)    {      free (str);      return 0;				/* Swallow the error.  */    }   str = str_append (str, typestr);  free (typestr);   ctf_dump_append (state, str);  return 0;} /* Dump all the object or function entries into the cds_items.  */ static intctf_dump_objts (ctf_dict_t *fp, ctf_dump_state_t *state, int functions){  const char *name;  ctf_id_t id;  ctf_next_t *i = NULL;  char *str = NULL;   if ((functions && fp->ctf_funcidx_names)      || (!functions && fp->ctf_objtidx_names))    str = str_append (str, _("Section is indexed.\n"));  else if (fp->ctf_ext_symtab.cts_data == NULL)    str = str_append (str, _("No symbol table.\n"));   while ((id = ctf_symbol_next (fp, &i, &name, functions)) != CTF_ERR)    {      char *typestr = NULL;       /* Emit the name, if we know it.  No trailing space: ctf_dump_format_type	 has a leading one.   */      if (name)	{	  if (asprintf (&str, "%s -> ", name) < 0)	    goto oom;	}      else	str = xstrdup ("");       if ((typestr = ctf_dump_format_type (state->cds_fp, id,					   CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)	{	  ctf_dump_append (state, str);	  continue;				/* Swallow the error.  */	}       str = str_append (str, typestr);      free (typestr);      ctf_dump_append (state, str);      continue;     oom:      ctf_set_errno (fp, ENOMEM);      ctf_next_destroy (i);      return -1;    }  return 0;} /* Dump a single variable into the cds_items.  */static intctf_dump_var (const char *name, ctf_id_t type, void *arg){  char *str;  char *typestr;  ctf_dump_state_t *state = arg;   if (asprintf (&str, "%s -> ", name) < 0)    return (ctf_set_errno (state->cds_fp, errno));   if ((typestr = ctf_dump_format_type (state->cds_fp, type,				       CTF_ADD_ROOT | CTF_FT_REFS)) == NULL)

Lines 1–500 of 837.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t