API extension for binutils (type of symbols).
authorMartin Liska <mliska@suse.cz>
Thu, 19 Mar 2020 15:56:27 +0000 (16:56 +0100)
committerMartin Liska <mliska@suse.cz>
Thu, 19 Mar 2020 15:56:27 +0000 (16:56 +0100)
* lto-section-in.c: Add ext_symtab.
* lto-streamer-out.c (write_symbol_extension_info): New.
(produce_symtab_extension): New.
(produce_asm_for_decls): Stream also produce_symtab_extension.
* lto-streamer.h (enum lto_section_type): New section.
* lto-symtab.h (enum gcc_plugin_symbol_type): New.
(enum gcc_plugin_symbol_section_kind): Likewise.
* lto-plugin.c (LTO_SECTION_PREFIX): Rename to ...
(LTO_SYMTAB_PREFIX): ... this.
(LTO_SECTION_PREFIX_LEN): Rename to ...
(LTO_SYMTAB_PREFIX_LEN): ... this.
(LTO_SYMTAB_EXT_PREFIX): New.
(LTO_SYMTAB_EXT_PREFIX_LEN): New.
(LTO_LTO_PREFIX): New.
(LTO_LTO_PREFIX_LEN): New.
(parse_table_entry): Fill up unused to zero.
(parse_table_entry_extension): New.
(parse_symtab_extension): New.
(finish_conflict_resolution): Change type
for resolution.
(process_symtab): Use new macro name.
(process_symtab_extension): New.
(claim_file_handler): Parse also process_symtab_extension.
(onload): Call new add_symbols_v2.

gcc/ChangeLog
gcc/lto-section-in.c
gcc/lto-streamer-out.c
gcc/lto-streamer.h
include/ChangeLog
include/lto-symtab.h
lto-plugin/ChangeLog
lto-plugin/lto-plugin.c

index 259d4aed103915a105664f6b1defe975a7b92dba..6b1b2956e7a04c5cd2cd649b5bd1fb80f41ebc88 100644 (file)
@@ -1,3 +1,11 @@
+2020-03-19  Martin Liska  <mliska@suse.cz>
+
+       * lto-section-in.c: Add ext_symtab.
+       * lto-streamer-out.c (write_symbol_extension_info): New.
+       (produce_symtab_extension): New.
+       (produce_asm_for_decls): Stream also produce_symtab_extension.
+       * lto-streamer.h (enum lto_section_type): New section.
+
 2020-03-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/94211
index c17dd69dbddd7d50757c311350e2d9ac2fc28f5c..0923a8c07468c51694f2f19065805356f37ecfe3 100644 (file)
@@ -38,6 +38,7 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
   "function_body",
   "statics",
   "symtab",
+  "ext_symtab",
   "refs",
   "asm",
   "jmpfuncs",
index cea5e71cffbcfc068af6bb240a5bf2c8d561fa88..a219c1d0dd1a02bfdd6f04fcc0de5bbeea543bd8 100644 (file)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-tree.h"
 #include "tree-dfa.h"
 #include "file-prefix-map.h" /* remap_debug_filename()  */
+#include "output.h"
 
 
 static void lto_write_tree (struct output_block*, tree, bool);
@@ -2777,12 +2778,32 @@ write_symbol (struct streamer_tree_cache_d *cache,
   lto_write_data (&slot_num, 4);
 }
 
+/* Write extension information for symbols (symbol type, section flags).  */
+
+static void
+write_symbol_extension_info (tree t)
+{
+  unsigned char c;
+  c = ((unsigned char) TREE_CODE (t) == VAR_DECL
+       ? GCCST_VARIABLE : GCCST_FUNCTION);
+  lto_write_data (&c, 1);
+  unsigned char section_kind = 0;
+  if (TREE_CODE (t) == VAR_DECL)
+    {
+      section *s = get_variable_section (t, false);
+      if (s->common.flags & SECTION_BSS)
+       section_kind |= GCCSSK_BSS;
+    }
+  lto_write_data (&section_kind, 1);
+}
+
 /* Write an IL symbol table to OB.
    SET and VSET are cgraph/varpool node sets we are outputting.  */
 
-static void
+static unsigned int
 produce_symtab (struct output_block *ob)
 {
+  unsigned int streamed_symbols = 0;
   struct streamer_tree_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, 0, NULL);
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
@@ -2804,6 +2825,7 @@ produce_symtab (struct output_block *ob)
       if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
        continue;
       write_symbol (cache, node->decl, &seen, false);
+      ++streamed_symbols;
     }
   for (lsei = lsei_start (encoder);
        !lsei_end_p (lsei); lsei_next (&lsei))
@@ -2813,8 +2835,61 @@ produce_symtab (struct output_block *ob)
       if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
        continue;
       write_symbol (cache, node->decl, &seen, false);
+      ++streamed_symbols;
+    }
+
+  lto_end_section ();
+
+  return streamed_symbols;
+}
+
+/* Symtab extension version.  */
+#define LTO_SYMTAB_EXTENSION_VERSION 1
+
+/* Write an IL symbol table extension to OB.
+   SET and VSET are cgraph/varpool node sets we are outputting.  */
+
+static void
+produce_symtab_extension (struct output_block *ob,
+                         unsigned int previous_streamed_symbols)
+{
+  unsigned int streamed_symbols = 0;
+  char *section_name = lto_get_section_name (LTO_section_symtab_extension,
+                                            NULL, 0, NULL);
+  lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
+  lto_symtab_encoder_iterator lsei;
+
+  lto_begin_section (section_name, false);
+  free (section_name);
+
+  unsigned char version = LTO_SYMTAB_EXTENSION_VERSION;
+  lto_write_data (&version, 1);
+
+  /* Write the symbol table.
+     First write everything defined and then all declarations.
+     This is necessary to handle cases where we have duplicated symbols.  */
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
+    {
+      symtab_node *node = lsei_node (lsei);
+
+      if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
+       continue;
+      write_symbol_extension_info (node->decl);
+      ++streamed_symbols;
+    }
+  for (lsei = lsei_start (encoder);
+       !lsei_end_p (lsei); lsei_next (&lsei))
+    {
+      symtab_node *node = lsei_node (lsei);
+
+      if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
+       continue;
+      write_symbol_extension_info (node->decl);
+      ++streamed_symbols;
     }
 
+  gcc_assert (previous_streamed_symbols == streamed_symbols);
   lto_end_section ();
 }
 
@@ -3001,7 +3076,10 @@ produce_asm_for_decls (void)
   /* Write the symbol table.  It is used by linker to determine dependencies
      and thus we can skip it for WPA.  */
   if (!flag_wpa)
-    produce_symtab (ob);
+    {
+      unsigned int streamed_symbols = produce_symtab (ob);
+      produce_symtab_extension (ob, streamed_symbols);
+    }
 
   /* Write command line opts.  */
   lto_write_options ();
index 25bf6c468f7f551b3bc6ebe83d3e0cae63ca0fd4..76aa6fe34b893633dd35eef2e9572d182b8280bf 100644 (file)
@@ -219,6 +219,7 @@ enum lto_section_type
   LTO_section_function_body,
   LTO_section_static_initializer,
   LTO_section_symtab,
+  LTO_section_symtab_extension,
   LTO_section_refs,
   LTO_section_asm,
   LTO_section_jump_functions,
index 8c79e73f043e9822f4ba41a382a16f2c27e6c258..c44fb79feebb1d73b35f0ad7407a67eb3cba391e 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-19  Martin Liska  <mliska@suse.cz>
+
+       * lto-symtab.h (enum gcc_plugin_symbol_type): New.
+       (enum gcc_plugin_symbol_section_kind): Likewise.
+
 2020-03-19  Martin Liska  <mliska@suse.cz>
 
        * plugin-api.h (struct ld_plugin_symbol): Split
index 0ce0de10121dbd7d1e86e6cd8bd58a920a1284d3..ef2e35f19c3ecffab000b4322e565bbfa015bc91 100644 (file)
@@ -38,4 +38,17 @@ enum gcc_plugin_symbol_visibility
     GCCPV_HIDDEN
   };
 
+enum gcc_plugin_symbol_type
+{
+  GCCST_UNKNOWN,
+  GCCST_FUNCTION,
+  GCCST_VARIABLE,
+};
+
+enum gcc_plugin_symbol_section_kind
+{
+  GCCSSK_DEFAULT,
+  GCCSSK_BSS
+};
+
 #endif /* GCC_LTO_SYMTAB_H  */
index 9b3f8fbe5a6a3e84c6b9b39770dc35cab8845d03..205652cdda49bc7d27e7899d7f1cecb9e86ce40f 100644 (file)
@@ -1,3 +1,23 @@
+2020-03-19  Martin Liska  <mliska@suse.cz>
+
+       * lto-plugin.c (LTO_SECTION_PREFIX): Rename to ...
+       (LTO_SYMTAB_PREFIX): ... this.
+       (LTO_SECTION_PREFIX_LEN): Rename to ...
+       (LTO_SYMTAB_PREFIX_LEN): ... this.
+       (LTO_SYMTAB_EXT_PREFIX): New.
+       (LTO_SYMTAB_EXT_PREFIX_LEN): New.
+       (LTO_LTO_PREFIX): New.
+       (LTO_LTO_PREFIX_LEN): New.
+       (parse_table_entry): Fill up unused to zero.
+       (parse_table_entry_extension): New.
+       (parse_symtab_extension): New.
+       (finish_conflict_resolution): Change type
+       for resolution.
+       (process_symtab): Use new macro name.
+       (process_symtab_extension): New.
+       (claim_file_handler): Parse also process_symtab_extension.
+       (onload): Call new add_symbols_v2.
+
 2020-01-01  Jakub Jelinek  <jakub@redhat.com>
 
        Update copyright years.
index c307fc871bf8e57fb61eecb7bf6f727fef0318ab..ca6c84a1ffd60771e85335045c3c14ce4f6ea4d2 100644 (file)
@@ -88,10 +88,14 @@ along with this program; see the file COPYING3.  If not see
 
 /* LTO magic section name.  */
 
-#define LTO_SECTION_PREFIX     ".gnu.lto_.symtab"
-#define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
-#define OFFLOAD_SECTION                ".gnu.offload_lto_.opts"
-#define OFFLOAD_SECTION_LEN    (sizeof (OFFLOAD_SECTION) - 1)
+#define LTO_SYMTAB_PREFIX          ".gnu.lto_.symtab"
+#define LTO_SYMTAB_PREFIX_LEN      (sizeof (LTO_SYMTAB_PREFIX) - 1)
+#define LTO_SYMTAB_EXT_PREFIX      ".gnu.lto_.ext_symtab"
+#define LTO_SYMTAB_EXT_PREFIX_LEN   (sizeof (LTO_SYMTAB_EXT_PREFIX) - 1)
+#define LTO_LTO_PREFIX             ".gnu.lto_.lto"
+#define LTO_LTO_PREFIX_LEN         (sizeof (LTO_LTO_PREFIX) - 1)
+#define OFFLOAD_SECTION                    ".gnu.offload_lto_.opts"
+#define OFFLOAD_SECTION_LEN        (sizeof (OFFLOAD_SECTION) - 1)
 
 /* The part of the symbol table the plugin has to keep track of. Note that we
    must keep SYMS until all_symbols_read is called to give the linker time to
@@ -159,7 +163,7 @@ static ld_plugin_register_cleanup register_cleanup;
 static ld_plugin_add_input_file add_input_file;
 static ld_plugin_add_input_library add_input_library;
 static ld_plugin_message message;
-static ld_plugin_add_symbols add_symbols;
+static ld_plugin_add_symbols add_symbols, add_symbols_v2;
 
 static struct plugin_file_info *claimed_files = NULL;
 static unsigned int num_claimed_files = 0;
@@ -286,6 +290,8 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry,
   else
     entry->comdat_key = xstrdup (entry->comdat_key);
 
+  entry->unused = entry->section_kind = entry->symbol_type = 0;
+
   t = *p;
   check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
   entry->def = translate_kind[t];
@@ -309,6 +315,32 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry,
   return p;
 }
 
+/* Parse an entry of the IL symbol table. The data to be parsed is pointed
+   by P and the result is written in ENTRY. The slot number is stored in SLOT.
+   Returns the address of the next entry. */
+
+static char *
+parse_table_entry_extension (char *p, struct ld_plugin_symbol *entry)
+{
+  unsigned char t;
+  enum ld_plugin_symbol_type symbol_types[] =
+    {
+      LDST_UNKNOWN,
+      LDST_FUNCTION,
+      LDST_VARIABLE,
+    };
+
+  t = *p;
+  check (t <= 2, LDPL_FATAL, "invalid symbol type found");
+  entry->symbol_type = symbol_types[t];
+  p++;
+  entry->section_kind = *p;
+  p++;
+
+  return p;
+}
+
+
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */
 
@@ -339,6 +371,24 @@ translate (char *data, char *end, struct plugin_symtab *out)
   out->aux = aux;
 }
 
+static void
+parse_symtab_extension (char *data, char *end, struct plugin_symtab *out)
+{
+  unsigned i;
+
+  unsigned char version = *data;
+  data++;
+
+  /* Version 1 contains the following data per entry:
+     - symbol_type
+     - section_kind
+     .  */
+
+  if (version == 1)
+    for (i = 0; i < out->nsyms; i++)
+      data = parse_table_entry_extension (data, &out->syms[i]);
+}
+
 /* Free all memory that is no longer needed after writing the symbol
    resolution. */
 
@@ -431,7 +481,7 @@ finish_conflict_resolution (struct plugin_symtab *symtab,
 
   for (i = 0; i < symtab->nsyms; i++)
     { 
-      int resolution = LDPR_UNKNOWN;
+      char resolution = LDPR_UNKNOWN;
 
       if (symtab->aux[i].next_conflict == -1)
        continue;
@@ -953,7 +1003,7 @@ process_symtab (void *data, const char *name, off_t offset, off_t length)
   char *s;
   char *secdatastart, *secdata;
 
-  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
+  if (strncmp (name, LTO_SYMTAB_PREFIX, LTO_SYMTAB_PREFIX_LEN) != 0)
     return 1;
 
   s = strrchr (name, '.');
@@ -995,6 +1045,59 @@ err:
   return 0;
 }
 
+/* Process one section of an object file.  */
+
+static int
+process_symtab_extension (void *data, const char *name, off_t offset,
+                         off_t length)
+{
+  struct plugin_objfile *obj = (struct plugin_objfile *)data;
+  char *s;
+  char *secdatastart, *secdata;
+
+  if (strncmp (name, LTO_SYMTAB_EXT_PREFIX, LTO_SYMTAB_EXT_PREFIX_LEN) != 0)
+    return 1;
+
+  s = strrchr (name, '.');
+  if (s)
+    sscanf (s, ".%" PRI_LL "x", &obj->out->id);
+  secdata = secdatastart = xmalloc (length);
+  offset += obj->file->offset;
+  if (offset != lseek (obj->file->fd, offset, SEEK_SET))
+    goto err;
+
+  do
+    {
+      ssize_t got = read (obj->file->fd, secdata, length);
+      if (got == 0)
+       break;
+      else if (got > 0)
+       {
+         secdata += got;
+         length -= got;
+       }
+      else if (errno != EINTR)
+       goto err;
+    }
+  while (length > 0);
+  if (length > 0)
+    goto err;
+
+  parse_symtab_extension (secdatastart, secdata, obj->out);
+  obj->found++;
+  free (secdatastart);
+  return 1;
+
+err:
+  if (message)
+    message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
+  /* Force claim_file_handler to abandon this file.  */
+  obj->found = 0;
+  free (secdatastart);
+  return 0;
+}
+
+
 /* Find an offload section of an object file.  */
 
 static int
@@ -1055,8 +1158,17 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
   if (!obj.objfile && !err)
     goto err;
 
-  if (obj.objfile)
-    errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
+   if (obj.objfile)
+    {
+      errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj,
+                                           &err);
+      /*  Parsing symtab extension should be done only for add_symbols_v2 and
+         later versions.  */
+      if (!errmsg && add_symbols_v2 != NULL)
+       errmsg = simple_object_find_sections (obj.objfile,
+                                             process_symtab_extension,
+                                             &obj, &err);
+    }
 
   if (!obj.objfile || errmsg)
     {
@@ -1080,8 +1192,12 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
 
   if (obj.found > 0)
     {
-      status = add_symbols (file->handle, lto_file.symtab.nsyms,
-                           lto_file.symtab.syms);
+      if (add_symbols_v2)
+       status = add_symbols_v2 (file->handle, lto_file.symtab.nsyms,
+                                lto_file.symtab.syms);
+      else
+       status = add_symbols (file->handle, lto_file.symtab.nsyms,
+                             lto_file.symtab.syms);
       check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
 
       num_claimed_files++;
@@ -1242,6 +1358,9 @@ onload (struct ld_plugin_tv *tv)
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
          register_claim_file = p->tv_u.tv_register_claim_file;
          break;
+       case LDPT_ADD_SYMBOLS_V2:
+         add_symbols_v2 = p->tv_u.tv_add_symbols;
+         break;
        case LDPT_ADD_SYMBOLS:
          add_symbols = p->tv_u.tv_add_symbols;
          break;