binutils: CTF support for objdump and readelf
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 701ab05461788bf9886477aeb3c91948c95ec4e7..5ae58574fb4cfa41479699006585b0140cd9a6b8 100644 (file)
@@ -60,6 +60,7 @@
 #include "bucomm.h"
 #include "elfcomm.h"
 #include "dwarf.h"
+#include "ctf-api.h"
 
 #include "elf/common.h"
 #include "elf/external.h"
 #include "elf/d10v.h"
 #include "elf/d30v.h"
 #include "elf/dlx.h"
+#include "elf/bpf.h"
 #include "elf/epiphany.h"
 #include "elf/fr30.h"
 #include "elf/frv.h"
@@ -182,6 +184,7 @@ typedef struct elf_section_list
 #define DEBUG_DUMP     (1 << 2)        /* The -w command line switch.  */
 #define STRING_DUMP     (1 << 3)       /* The -p command line switch.  */
 #define RELOC_DUMP      (1 << 4)       /* The -R command line switch.  */
+#define CTF_DUMP        (1 << 5)        /* The --ctf command line switch.  */
 
 typedef unsigned char dump_type;
 
@@ -248,12 +251,17 @@ static bfd_boolean do_dump = FALSE;
 static bfd_boolean do_version = FALSE;
 static bfd_boolean do_histogram = FALSE;
 static bfd_boolean do_debugging = FALSE;
+static bfd_boolean do_ctf = FALSE;
 static bfd_boolean do_arch = FALSE;
 static bfd_boolean do_notes = FALSE;
 static bfd_boolean do_archive_index = FALSE;
 static bfd_boolean is_32bit_elf = FALSE;
 static bfd_boolean decompress_dumps = FALSE;
 
+static char *dump_ctf_parent_name;
+static char *dump_ctf_symtab_name;
+static char *dump_ctf_strtab_name;
+
 struct group_list
 {
   struct group_list *  next;
@@ -781,6 +789,7 @@ guess_is_rela (unsigned int e_machine)
     case EM_SCORE:
     case EM_XGATE:
     case EM_NFP:
+    case EM_BPF:
       return FALSE;
 
       /* Targets that use RELA relocations.  */
@@ -1482,6 +1491,10 @@ dump_relocations (Filedata *          filedata,
          rtype = elf_visium_reloc_type (type);
          break;
 
+        case EM_BPF:
+          rtype = elf_bpf_reloc_type (type);
+          break;
+
        case EM_ADAPTEVA_EPIPHANY:
          rtype = elf_epiphany_reloc_type (type);
          break;
@@ -1804,6 +1817,7 @@ get_aarch64_dynamic_type (unsigned long type)
     {
     case DT_AARCH64_BTI_PLT:  return "AARCH64_BTI_PLT";
     case DT_AARCH64_PAC_PLT:  return "AARCH64_PAC_PLT";
+    case DT_AARCH64_VARIANT_PCS:  return "AARCH64_VARIANT_PCS";
     default:
       return NULL;
     }
@@ -4387,6 +4401,10 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type)
 #define OPTION_DWARF_DEPTH     514
 #define OPTION_DWARF_START     515
 #define OPTION_DWARF_CHECK     516
+#define OPTION_CTF_DUMP                517
+#define OPTION_CTF_PARENT      518
+#define OPTION_CTF_SYMBOLS     519
+#define OPTION_CTF_STRINGS     520
 
 static struct option options[] =
 {
@@ -4425,6 +4443,12 @@ static struct option options[] =
   {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
   {"dwarf-check",      no_argument, 0, OPTION_DWARF_CHECK},
 
+  {"ctf",              required_argument, 0, OPTION_CTF_DUMP},
+
+  {"ctf-symbols",      required_argument, 0, OPTION_CTF_SYMBOLS},
+  {"ctf-strings",      required_argument, 0, OPTION_CTF_STRINGS},
+  {"ctf-parent",       required_argument, 0, OPTION_CTF_PARENT},
+
   {"version",         no_argument, 0, 'v'},
   {"wide",            no_argument, 0, 'W'},
   {"help",            no_argument, 0, 'H'},
@@ -4474,6 +4498,15 @@ usage (FILE * stream)
   --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
   --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
                          or deeper\n"));
+  fprintf (stream, _("\
+  --ctf=<number|name>    Display CTF info from section <number|name>\n\
+  --ctf-parent=<number|name>\n\
+                         Use section <number|name> as the CTF parent\n\n\
+  --ctf-symbols=<number|name>\n\
+                         Use section <number|name> as the CTF external symtab\n\n\
+  --ctf-strings=<number|name>\n\
+                         Use section <number|name> as the CTF external strtab\n\n"));
+
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -4701,6 +4734,19 @@ parse_args (Filedata * filedata, int argc, char ** argv)
        case OPTION_DWARF_CHECK:
          dwarf_check = TRUE;
          break;
+       case OPTION_CTF_DUMP:
+         do_ctf = TRUE;
+         request_dump (filedata, CTF_DUMP);
+         break;
+       case OPTION_CTF_SYMBOLS:
+         dump_ctf_symtab_name = strdup (optarg);
+         break;
+       case OPTION_CTF_STRINGS:
+         dump_ctf_strtab_name = strdup (optarg);
+         break;
+       case OPTION_CTF_PARENT:
+         dump_ctf_parent_name = strdup (optarg);
+         break;
        case OPTION_DYN_SYMS:
          do_dyn_syms = TRUE;
          break;
@@ -6868,7 +6914,7 @@ process_section_groups (Filedata * filedata)
                     printable_section_name (filedata, section),
                     (unsigned long) section->sh_entsize,
                     (unsigned long) section->sh_size);
-             break;
+             continue;
            }
 
          start = (unsigned char *) get_data (NULL, filedata, section->sh_offset,
@@ -11095,6 +11141,22 @@ get_solaris_symbol_visibility (unsigned int visibility)
     }
 }
 
+static const char *
+get_aarch64_symbol_other (unsigned int other)
+{
+  static char buf[32];
+
+  if (other & STO_AARCH64_VARIANT_PCS)
+    {
+      other &= ~STO_AARCH64_VARIANT_PCS;
+      if (other == 0)
+       return "VARIANT_PCS";
+      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);
+      return buf;
+    }
+  return NULL;
+}
+
 static const char *
 get_mips_symbol_other (unsigned int other)
 {
@@ -11206,6 +11268,9 @@ get_symbol_other (Filedata * filedata, unsigned int other)
 
   switch (filedata->file_header.e_machine)
     {
+    case EM_AARCH64:
+      result = get_aarch64_symbol_other (other);
+      break;
     case EM_MIPS:
       result = get_mips_symbol_other (other);
       break;
@@ -12410,6 +12475,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type)
     case EM_AARCH64:
       return (reloc_type == 258
              || reloc_type == 1); /* R_AARCH64_ABS32 || R_AARCH64_P32_ABS32 */
+    case EM_BPF:
+      return reloc_type == 11; /* R_BPF_DATA_32 */
     case EM_ADAPTEVA_EPIPHANY:
       return reloc_type == 3;
     case EM_ALPHA:
@@ -13741,6 +13808,163 @@ dump_section_as_bytes (Elf_Internal_Shdr *  section,
   return TRUE;
 }
 
+static ctf_sect_t *
+shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata)
+{
+  buf->cts_name = SECTION_NAME(shdr);
+  buf->cts_type = shdr->sh_type;
+  buf->cts_flags = shdr->sh_flags;
+  buf->cts_size = shdr->sh_size;
+  buf->cts_entsize = shdr->sh_entsize;
+  buf->cts_offset = (off64_t) shdr->sh_offset;
+
+  return buf;
+}
+
+/* Formatting callback function passed to ctf_dump.  Returns either the pointer
+   it is passed, or a pointer to newly-allocated storage, in which case
+   dump_ctf() will free it when it no longer needs it.  */
+
+static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED,
+                                   char *s, void *arg)
+{
+  char *spaces = arg;
+  char *new_s;
+
+  if (asprintf (&new_s, "%s%s", spaces, s) < 0)
+    return s;
+  return new_s;
+}
+
+static bfd_boolean
+dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
+{
+  Elf_Internal_Shdr *  parent_sec = NULL;
+  Elf_Internal_Shdr *  symtab_sec = NULL;
+  Elf_Internal_Shdr *  strtab_sec = NULL;
+  void *              data = NULL;
+  void *              symdata = NULL;
+  void *              strdata = NULL;
+  void *              parentdata = NULL;
+  ctf_sect_t           ctfsect, symsect, strsect, parentsect;
+  ctf_sect_t *         symsectp = NULL;
+  ctf_sect_t *         strsectp = NULL;
+  ctf_file_t *         ctf = NULL;
+  ctf_file_t *         parent = NULL;
+
+  const char *things[] = {"Labels", "Data objects", "Function objects",
+                         "Variables", "Types", "Strings", ""};
+  const char **thing;
+  int err;
+  bfd_boolean ret = FALSE;
+  size_t i;
+
+  shdr_to_ctf_sect (&ctfsect, section, filedata);
+  data = get_section_contents (section, filedata);
+  ctfsect.cts_data = data;
+
+  if (dump_ctf_symtab_name)
+    {
+      if ((symtab_sec = find_section (filedata, dump_ctf_symtab_name)) == NULL)
+       {
+         error (_("No symbol section named %s\n"), dump_ctf_symtab_name);
+         goto fail;
+       }
+      if ((symdata = (void *) get_data (NULL, filedata,
+                                       symtab_sec->sh_offset, 1,
+                                       symtab_sec->sh_size,
+                                       _("symbols"))) == NULL)
+       goto fail;
+      symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata);
+      symsect.cts_data = symdata;
+    }
+  if (dump_ctf_strtab_name)
+    {
+      if ((strtab_sec = find_section (filedata, dump_ctf_strtab_name)) == NULL)
+       {
+         error (_("No string table section named %s\n"),
+                dump_ctf_strtab_name);
+         goto fail;
+       }
+      if ((strdata = (void *) get_data (NULL, filedata,
+                                       strtab_sec->sh_offset, 1,
+                                       strtab_sec->sh_size,
+                                       _("strings"))) == NULL)
+       goto fail;
+      strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata);
+      strsect.cts_data = strdata;
+    }
+  if (dump_ctf_parent_name)
+    {
+      if ((parent_sec = find_section (filedata, dump_ctf_parent_name)) == NULL)
+       {
+         error (_("No CTF parent section named %s\n"), dump_ctf_parent_name);
+         goto fail;
+       }
+      if ((parentdata = (void *) get_data (NULL, filedata,
+                                          parent_sec->sh_offset, 1,
+                                          parent_sec->sh_size,
+                                          _("CTF parent"))) == NULL)
+       goto fail;
+      shdr_to_ctf_sect (&parentsect, parent_sec, filedata);
+      parentsect.cts_data = parentdata;
+    }
+
+  /* Load the CTF file and dump it.  */
+
+  if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL)
+    {
+      error (_("CTF open failure: %s\n"), ctf_errmsg (err));
+      goto fail;
+    }
+
+  if (parentdata)
+    {
+      if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL)
+       {
+         error (_("CTF open failure: %s\n"), ctf_errmsg (err));
+         goto fail;
+       }
+
+      ctf_import (ctf, parent);
+    }
+
+  ret = TRUE;
+
+  printf (_("\nDump of CTF section '%s':\n"),
+         printable_section_name (filedata, section));
+
+  for (i = 1, thing = things; *thing[0]; thing++, i++)
+    {
+      ctf_dump_state_t *s = NULL;
+      char *item;
+
+      printf ("\n  %s:\n", *thing);
+      while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines,
+                              (void *) "    ")) != NULL)
+       {
+         printf ("%s\n", item);
+         free (item);
+       }
+
+      if (ctf_errno (ctf))
+       {
+         error (_("Iteration failed: %s, %s\n"), *thing,
+                  ctf_errmsg (ctf_errno (ctf)));
+         ret = FALSE;
+       }
+    }
+
+ fail:
+  ctf_file_close (ctf);
+  ctf_file_close (parent);
+  free (parentdata);
+  free (data);
+  free (symdata);
+  free (strdata);
+  return ret;
+}
+
 static bfd_boolean
 load_specific_debug_section (enum dwarf_section_display_enum  debug,
                             const Elf_Internal_Shdr *        sec,
@@ -14078,6 +14302,12 @@ process_section_contents (Filedata * filedata)
          if (! display_debug_section (i, section, filedata))
            res = FALSE;
        }
+
+      if (dump & CTF_DUMP)
+       {
+         if (! dump_section_as_ctf (section, filedata))
+           res = FALSE;
+       }
     }
 
   /* Check to see if the user requested a
@@ -14370,7 +14600,7 @@ typedef struct
 static const char * arm_attr_tag_CPU_arch[] =
   {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
    "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "v8-R", "v8-M.baseline",
-   "v8-M.mainline"};
+   "v8-M.mainline", "", "", "", "v8.1-M.mainline"};
 static const char * arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char * arm_attr_tag_THUMB_ISA_use[] =
   {"No", "Thumb-1", "Thumb-2", "Yes"};
@@ -14434,6 +14664,9 @@ static const char * arm_attr_tag_Virtualization_use[] =
 static const char * arm_attr_tag_MPextension_use_legacy[] =
   {"Not Allowed", "Allowed"};
 
+static const char * arm_attr_tag_MVE_arch[] =
+  {"No MVE", "MVE Integer only", "MVE Integer and FP"};
+
 #define LOOKUP(id, name) \
   {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
 static arm_attr_public_tag arm_attr_public_tags[] =
@@ -14473,6 +14706,7 @@ static arm_attr_public_tag arm_attr_public_tags[] =
   LOOKUP(42, MPextension_use),
   LOOKUP(44, DIV_use),
   LOOKUP(46, DSP_extension),
+  LOOKUP(48, MVE_arch),
   {64, "nodefaults", 0, NULL},
   {65, "also_compatible_with", 0, NULL},
   LOOKUP(66, T2EE_use),
@@ -19953,5 +20187,9 @@ main (int argc, char ** argv)
   if (cmdline.dump_sects != NULL)
     free (cmdline.dump_sects);
 
+  free (dump_ctf_symtab_name);
+  free (dump_ctf_strtab_name);
+  free (dump_ctf_parent_name);
+
   return err ? EXIT_FAILURE : EXIT_SUCCESS;
 }
This page took 0.031023 seconds and 4 git commands to generate.