[gcc(refs/users/marxin/heads/lto-plugin-symbol-type-v6)] API extension for binutils (type of symbols).
Martin Liska
marxin@gcc.gnu.org
Tue Mar 17 08:32:56 GMT 2020
https://gcc.gnu.org/g:51fea5094683959e239b0817f47c9b0fa17ff736
commit 51fea5094683959e239b0817f47c9b0fa17ff736
Author: Martin Liska <mliska@suse.cz>
Date: Fri Mar 6 18:09:35 2020 +0100
API extension for binutils (type of symbols).
gcc/ChangeLog:
2020-03-12 Martin Liska <mliska@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 <mliska@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 <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.
(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.
Diff:
---
gcc/lto-section-in.c | 3 +-
gcc/lto-streamer-out.c | 76 +++++++++++++++++++++-
gcc/lto-streamer.h | 1 +
include/lto-symtab.h | 12 ++++
lto-plugin/lto-plugin.c | 169 +++++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 241 insertions(+), 20 deletions(-)
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index c17dd69dbdd..78b015be696 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",
+ "ext_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..e459ec91856 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,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_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 (§ion_flags, 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,55 @@ 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;
+}
+
+/* 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);
+
+ /* 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 +3070,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 ();
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..a7cdabb01f6 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_.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
@@ -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,15 @@ 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;
+
+ 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 +472,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 +514,21 @@ 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)
+{
+ unsigned i;
+
+ for (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 +551,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 +1013,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 +1057,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 +1170,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 +1202,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 (<o_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 +1371,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;
More information about the Gcc-cvs
mailing list