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 (§ion_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 (<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 +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