Hi.

I'm sending extended version of the patch where I address Honza's note
about backward compatibility. So I add a next section _lto.extension_symtab
where I put new bits. With that, new LTO bytecode can be opened with older
LTO plugin.

Moreover, I've also tested lto.exp tests and binutils master. And I can confirm
that patches work with H.J.'s counterpart:
https://gitlab.com/x86-gcc/gcc/-/tree/users/hjl/plugin/master

$ cat bss.c
int global_zero;
int global_one = 1;

int main() { return 0; }

$ gcc -c -flto bss.c

Old bintuils (with new plugin):

$ ./binutils/nm-new /tmp/bss.o --plugin 
/home/marxin/Programming/gcc2/objdir/gcc/liblto_plugin.so.0.0.0
00000000 T global_one
00000000 T global_zero
00000000 T main

H.J.'s binutils (with new plugin):

$ ./binutils/nm-new /tmp/bss.o --plugin 
/home/marxin/Programming/gcc2/objdir/gcc/liblto_plugin.so.0.0.0
00000000 D global_one
00000000 B global_zero
00000000 T main

System binutils (with old plugin):

$ nm /tmp/bss.o
00000000 T global_one
00000000 T global_zero
00000000 T main

Hope I'm done now.
Thoughts?

Thanks,
Martin
>From 8968bbdf627dc26056f1cb344e253eedae0efca1 Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Fri, 6 Mar 2020 18:09:35 +0100
Subject: [PATCH 2/2] API extension for binutils (type of symbols).

gcc/ChangeLog:

2020-03-12  Martin Liska  <mli...@suse.cz>

	* lto-section-in.c: Add extension_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.

include/ChangeLog:

2020-03-12  Martin Liska  <mli...@suse.cz>

	* lto-symtab.h (enum gcc_plugin_symbol_type): New.
	(enum gcc_plugin_symbol_section_flags): Likewise.

lto-plugin/ChangeLog:

2020-03-12  Martin Liska  <mli...@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.
	(clear_new_symtab_flags): New.
	(write_resolution): Support new get_symbols_v4.
	(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/lto-section-in.c    |   3 +-
 gcc/lto-streamer-out.c  |  64 +++++++++++++++-
 gcc/lto-streamer.h      |   1 +
 include/lto-symtab.h    |  12 +++
 lto-plugin/lto-plugin.c | 165 +++++++++++++++++++++++++++++++++++-----
 5 files changed, 226 insertions(+), 19 deletions(-)

diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index c17dd69dbdd..7bf59c513fc 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -54,7 +54,8 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
   "mode_table",
   "hsa",
   "lto",
-  "ipa_sra"
+  "ipa_sra",
+  "extension_symtab"
 };
 
 /* Hooks so that the ipa passes can call into the lto front end to get
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index cea5e71cffb..2fd20252ba5 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -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,6 +2778,25 @@ 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_flags = 0;
+  if (TREE_CODE (t) == VAR_DECL)
+    {
+      section *s = get_variable_section (t, false);
+      if (s->common.flags & SECTION_BSS)
+	section_flags |= GCCSSS_BSS;
+    }
+  lto_write_data (&section_flags, 1);
+}
+
 /* Write an IL symbol table to OB.
    SET and VSET are cgraph/varpool node sets we are outputting.  */
 
@@ -2818,6 +2838,45 @@ produce_symtab (struct output_block *ob)
   lto_end_section ();
 }
 
+/* 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)
+{
+  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);
+
+  /* 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);
+    }
+  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);
+    }
+
+  lto_end_section ();
+}
+
 
 /* Init the streamer_mode_table for output, where we collect info on what
    machine_mode values have been streamed.  */
@@ -3001,7 +3060,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);
+    {
+      produce_symtab (ob);
+      produce_symtab_extension (ob);
+    }
 
   /* Write command line opts.  */
   lto_write_options ();
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 25bf6c468f7..4f82b439360 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -236,6 +236,7 @@ enum lto_section_type
   LTO_section_ipa_hsa,
   LTO_section_lto,
   LTO_section_ipa_sra,
+  LTO_section_symtab_extension,
   LTO_N_SECTION_TYPES		/* Must be last.  */
 };
 
diff --git a/include/lto-symtab.h b/include/lto-symtab.h
index 0ce0de10121..47f0ff27df8 100644
--- a/include/lto-symtab.h
+++ b/include/lto-symtab.h
@@ -38,4 +38,16 @@ enum gcc_plugin_symbol_visibility
     GCCPV_HIDDEN
   };
 
+enum gcc_plugin_symbol_type
+{
+  GCCST_UNKNOWN,
+  GCCST_FUNCTION,
+  GCCST_VARIABLE,
+};
+
+enum gcc_plugin_symbol_section_flags
+{
+  GCCSSS_BSS = 1
+};
+
 #endif /* GCC_LTO_SYMTAB_H  */
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index c307fc871bf..78c8672f160 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -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_.extension_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
@@ -154,12 +158,12 @@ enum symbol_style
 static char *arguments_file_name;
 static ld_plugin_register_claim_file register_claim_file;
 static ld_plugin_register_all_symbols_read register_all_symbols_read;
-static ld_plugin_get_symbols get_symbols, get_symbols_v2;
+static ld_plugin_get_symbols get_symbols, get_symbols_v2, get_symbols_v4;
 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;
@@ -231,7 +235,7 @@ check_1 (int gate, enum ld_plugin_level level, const char *text)
    Returns the address of the next entry. */
 
 static char *
-parse_table_entry (char *p, struct ld_plugin_symbol *entry, 
+parse_table_entry (char *p, struct ld_plugin_symbol *entry,
 		   struct sym_aux *aux)
 {
   unsigned char t;
@@ -296,6 +300,8 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry,
   entry->visibility = translate_visibility[t];
   p++;
 
+  entry->unused = 0;
+
   memcpy (&entry->size, p, sizeof (uint64_t));
   p += 8;
 
@@ -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 <= 3, LDPL_FATAL, "invalid symbol type found");
+  entry->symbol_type = symbol_types[t];
+  p++;
+  entry->section_flags = *p;
+  p++;
+
+  return p;
+}
+
+
 /* Translate the IL symbol table located between DATA and END. Append the
    slots and symbols to OUT. */
 
@@ -339,6 +371,13 @@ 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)
+{
+  for (unsigned 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 +470,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;
@@ -473,6 +512,19 @@ free_symtab (struct plugin_symtab *symtab)
   symtab->aux = NULL;
 }
 
+/* Clear new flags symbol_type and section_flags
+   from symbol table entries.  */
+
+static void
+clear_new_symtab_flags (struct plugin_symtab *out)
+{
+  for (unsigned i = 0; i < out->nsyms; i++)
+    {
+      out->syms[i].symbol_type = 0;
+      out->syms[i].section_flags = 0;
+    }
+}
+
 /*  Writes the relocations to disk. */
 
 static void
@@ -495,10 +547,16 @@ write_resolution (void)
 
       /* Version 2 of API supports IRONLY_EXP resolution that is
          accepted by GCC-4.7 and newer.  */
-      if (get_symbols_v2)
-        get_symbols_v2 (info->handle, symtab->nsyms, syms);
+      if (get_symbols_v4)
+	get_symbols_v4 (info->handle, symtab->nsyms, syms);
       else
-        get_symbols (info->handle, symtab->nsyms, syms);
+	{
+	  clear_new_symtab_flags (symtab);
+	  if (get_symbols_v2)
+	    get_symbols_v2 (info->handle, symtab->nsyms, syms);
+	  else
+	    get_symbols (info->handle, symtab->nsyms, syms);
+	}
 
       finish_conflict_resolution (symtab, &info->conflicts);
 
@@ -951,9 +1009,9 @@ process_symtab (void *data, const char *name, off_t offset, off_t length)
 {
   struct plugin_objfile *obj = (struct plugin_objfile *)data;
   char *s;
-  char *secdatastart, *secdata;
+  char *secdatastart = NULL, *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 +1053,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 = NULL, *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 +1166,15 @@ 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);
+      if (!errmsg)
+	errmsg = simple_object_find_sections (obj.objfile,
+					      process_symtab_extension,
+					      &obj, &err);
+    }
 
   if (!obj.objfile || errmsg)
     {
@@ -1080,8 +1198,15 @@ 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
+	{
+	  clear_new_symtab_flags (&lto_file.symtab);
+	  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,12 +1367,18 @@ 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;
 	case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
 	  register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
 	  break;
+	case LDPT_GET_SYMBOLS_V4:
+	  get_symbols_v4 = p->tv_u.tv_get_symbols;
+	  break;
 	case LDPT_GET_SYMBOLS_V2:
 	  get_symbols_v2 = p->tv_u.tv_get_symbols;
 	  break;
-- 
2.25.1

>From e9b12e59d1ce3042f528ed4d9cfdbdb22270dfaf Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Thu, 12 Mar 2020 13:15:48 +0100
Subject: [PATCH 1/2] Update include/plugin-api.h.

include/ChangeLog:

2020-03-12  Martin Liska  <mli...@suse.cz>

	* plugin-api.h (struct ld_plugin_symbol): Split
	int def into 4 char fields.
	(enum ld_plugin_symbol_type): New.
	(enum ld_plugin_symbol_section_flags): New.
	(enum ld_plugin_tag): Add LDPT_GET_SYMBOLS_V and
	LDPT_GET_SYMBOLS_V4.
---
 include/plugin-api.h | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/include/plugin-api.h b/include/plugin-api.h
index 09e1202df07..804684449cf 100644
--- a/include/plugin-api.h
+++ b/include/plugin-api.h
@@ -87,7 +87,17 @@ struct ld_plugin_symbol
 {
   char *name;
   char *version;
-  int def;
+#ifdef __BIG_ENDIAN__
+  char unused;
+  char section_flags;
+  char symbol_type;
+  char def;
+#else
+  char def;
+  char symbol_type;
+  char section_flags;
+  char unused;
+#endif
   int visibility;
   uint64_t size;
   char *comdat_key;
@@ -123,6 +133,20 @@ enum ld_plugin_symbol_visibility
   LDPV_HIDDEN
 };
 
+/* The type of the symbol.  */
+
+enum ld_plugin_symbol_type
+{
+  LDST_UNKNOWN,
+  LDST_FUNCTION,
+  LDST_VARIABLE,
+};
+
+enum ld_plugin_symbol_section_flags
+{
+  LDSSS_BSS = 1
+};
+
 /* How a symbol is resolved.  */
 
 enum ld_plugin_symbol_resolution
@@ -431,7 +455,9 @@ enum ld_plugin_tag
   LDPT_GET_INPUT_SECTION_ALIGNMENT = 29,
   LDPT_GET_INPUT_SECTION_SIZE = 30,
   LDPT_REGISTER_NEW_INPUT_HOOK = 31,
-  LDPT_GET_WRAP_SYMBOLS = 32
+  LDPT_GET_WRAP_SYMBOLS = 32,
+  LDPT_ADD_SYMBOLS_V2 = 33,
+  LDPT_GET_SYMBOLS_V4 = 34,
 };
 
 /* The plugin transfer vector.  */
-- 
2.25.1

Reply via email to