diff options
author | ak <ak@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-23 05:33:51 +0000 |
---|---|---|
committer | ak <ak@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-23 05:33:51 +0000 |
commit | f18bad3324ef4d6e39219a4ec94b0a59cbcbb010 (patch) | |
tree | 50e055bbea281c232261eb1e07af42e60ab3a165 | |
parent | aa5c56571d44e75a4ac0d2824131e011cd38a7c2 (diff) | |
download | gcc-f18bad3324ef4d6e39219a4ec94b0a59cbcbb010.tar.gz |
gcc:
2010-07-10 Andi Kleen <ak@linux.intel.com>
PR lto/44992
* lto-opts.c (lto_write_options): Add NULL file_data argument to
lto_get_section_name.
* lto-section-out.c (lto_destroy_simple_output_block): Likewise.
* lto-streamer-out.c (produce_asm): Likewise.
(copy_function): Likewise.
(produce_symtab): Likewise.
(produce_asm_for_decls): Likewise.
* lto-streamer.c (lto_get_section_name): Add file_data argument.
Rewrite to add random postfix to LTO sections.
* lto-streamer.h (lto_file_decl_data): Add next, id, resolutions.
(lto_get_section_name): Add file_data argument to prototype.
lto:
2010-07-10 Andi Kleen <ak@linux.intel.com>
PR lto/44992
* lto.c: Include splay-tree.h
(lto_resolution_read): Change to walk file_ids tree and parse
extra file_id in resolution file.
(lto_section_with_id): Add.
(create_subid_section_table): Add.
(lwstate): Add.
(lto_create_files_from_ids): Add.
(lto_file_read): Change to handle sub file ids and create list
of file_datas. Add output argument for count.
(get_section_data): Pass file_data to lto_get_section_name.
(lto_flatten_file): Add.
(read_cgraph_and_symbols): Handle linked lists of file_datas.
lto-plugin:
2010-07-10 Andi Kleen <ak@linux.intel.com>
PR lto/44992
* lto-plugin.c (sym_aux): Add.
(plugin_symtab): Remove slots. Add aux and id.
(parse_table_entry): Change to use aux instead of slots.
(LTO_SECTION_PREFIX): Add.
(translate): Improve buffer allocation. Change to append
symbols to existing out buffer.
(get_section): Remove.
(process_symtab): Add.
(free_2): Free symtab->aux.
(write_resolution): Handle aux instead of slots.
Print sub id to resolution file.
(claim_file_handler): Clear lto_file. Replace get_symtab/translate
calls with call to process_symtab.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162443 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/lto-opts.c | 2 | ||||
-rw-r--r-- | gcc/lto-section-out.c | 2 | ||||
-rw-r--r-- | gcc/lto-streamer-out.c | 10 | ||||
-rw-r--r-- | gcc/lto-streamer.c | 70 | ||||
-rw-r--r-- | gcc/lto-streamer.h | 11 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/lto/lto.c | 217 | ||||
-rw-r--r-- | lto-plugin/ChangeLog | 17 | ||||
-rw-r--r-- | lto-plugin/lto-plugin.c | 128 |
10 files changed, 341 insertions, 147 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b7514debf7..99635b600ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 2010-07-10 Andi Kleen <ak@linux.intel.com> + PR lto/44992 + * lto-opts.c (lto_write_options): Add NULL file_data argument to + lto_get_section_name. + * lto-section-out.c (lto_destroy_simple_output_block): Likewise. + * lto-streamer-out.c (produce_asm): Likewise. + (copy_function): Likewise. + (produce_symtab): Likewise. + (produce_asm_for_decls): Likewise. + * lto-streamer.c (lto_get_section_name): Add file_data argument. + Rewrite to add random postfix to LTO sections. + * lto-streamer.h (lto_file_decl_data): Add next, id, resolutions. + (lto_get_section_name): Add file_data argument to prototype. + +2010-07-10 Andi Kleen <ak@linux.intel.com> + * lto-opts.c (lto_read_file_options): Check for missing section. 2010-07-22 Bernd Schmidt <bernds@codesourcery.com> diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c index 21a5a20a0a6..fa52f953608 100644 --- a/gcc/lto-opts.c +++ b/gcc/lto-opts.c @@ -294,7 +294,7 @@ output_options (struct lto_output_stream *stream) void lto_write_options (void) { - char *const section_name = lto_get_section_name (LTO_section_opts, NULL); + char *const section_name = lto_get_section_name (LTO_section_opts, NULL, NULL); struct lto_output_stream stream; struct lto_simple_header header; struct lto_output_stream *header_stream; diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c index b5353f34af2..e9b7b0a70fa 100644 --- a/gcc/lto-section-out.c +++ b/gcc/lto-section-out.c @@ -486,7 +486,7 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob) struct lto_simple_header header; struct lto_output_stream *header_stream; - section_name = lto_get_section_name (ob->section_type, NULL); + section_name = lto_get_section_name (ob->section_type, NULL, NULL); lto_begin_section (section_name, !flag_wpa); free (section_name); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 7b78ce52148..c96c13aeefe 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1810,10 +1810,10 @@ produce_asm (struct output_block *ob, tree fn) if (section_type == LTO_section_function_body) { const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn)); - section_name = lto_get_section_name (section_type, name); + section_name = lto_get_section_name (section_type, name, NULL); } else - section_name = lto_get_section_name (section_type, NULL); + section_name = lto_get_section_name (section_type, NULL, NULL); lto_begin_section (section_name, !flag_wpa); free (section_name); @@ -2041,7 +2041,7 @@ copy_function (struct cgraph_node *node) size_t len; const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)); char *section_name = - lto_get_section_name (LTO_section_function_body, name); + lto_get_section_name (LTO_section_function_body, name, NULL); size_t i, j; struct lto_in_decl_state *in_state; struct lto_out_decl_state *out_state = lto_get_out_decl_state (); @@ -2398,7 +2398,7 @@ produce_symtab (struct output_block *ob, cgraph_node_set set, varpool_node_set vset) { struct lto_streamer_cache_d *cache = ob->writer_cache; - char *section_name = lto_get_section_name (LTO_section_symtab, NULL); + char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); bitmap seen; struct cgraph_node *node, *alias; struct varpool_node *vnode, *valias; @@ -2477,7 +2477,7 @@ produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset) memset (&header, 0, sizeof (struct lto_decl_header)); - section_name = lto_get_section_name (LTO_section_decls, NULL); + section_name = lto_get_section_name (LTO_section_decls, NULL, NULL); lto_begin_section (section_name, !flag_wpa); free (section_name); diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c index 406096015f4..0536bb97b25 100644 --- a/gcc/lto-streamer.c +++ b/gcc/lto-streamer.c @@ -133,57 +133,45 @@ lto_bitmap_free (bitmap b) /* Get a section name for a particular type or name. The NAME field - is only used if SECTION_TYPE is LTO_section_function_body or - LTO_static_initializer. For all others it is ignored. The callee - of this function is responcible to free the returned name. */ + is only used if SECTION_TYPE is LTO_section_function_body. For all + others it is ignored. The callee of this function is responsible + to free the returned name. */ char * -lto_get_section_name (int section_type, const char *name) +lto_get_section_name (int section_type, const char *name, struct lto_file_decl_data *f) { - switch (section_type) + const char *add; + char post[32]; + const char *sep; + + if (section_type == LTO_section_function_body) { - case LTO_section_function_body: gcc_assert (name != NULL); if (name[0] == '*') name++; - return concat (LTO_SECTION_NAME_PREFIX, name, NULL); - - case LTO_section_static_initializer: - return concat (LTO_SECTION_NAME_PREFIX, ".statics", NULL); - - case LTO_section_symtab: - return concat (LTO_SECTION_NAME_PREFIX, ".symtab", NULL); - - case LTO_section_decls: - return concat (LTO_SECTION_NAME_PREFIX, ".decls", NULL); - - case LTO_section_cgraph: - return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL); - - case LTO_section_varpool: - return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL); - - case LTO_section_refs: - return concat (LTO_SECTION_NAME_PREFIX, ".refs", NULL); - - case LTO_section_jump_functions: - return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL); - - case LTO_section_ipa_pure_const: - return concat (LTO_SECTION_NAME_PREFIX, ".pureconst", NULL); - - case LTO_section_ipa_reference: - return concat (LTO_SECTION_NAME_PREFIX, ".reference", NULL); + add = name; + sep = ""; + } + else if (section_type < LTO_N_SECTION_TYPES) + { + add = lto_section_name[section_type]; + sep = "."; + } + else + internal_error ("bytecode stream: unexpected LTO section %s", name); - case LTO_section_opts: - return concat (LTO_SECTION_NAME_PREFIX, ".opts", NULL); + /* Make the section name unique so that ld -r combining sections + doesn't confuse the reader with merged sections. - case LTO_section_cgraph_opt_sum: - return concat (LTO_SECTION_NAME_PREFIX, ".cgraphopt", NULL); + For options don't add a ID, the option reader cannot deal with them + and merging should be ok here. - default: - internal_error ("bytecode stream: unexpected LTO section %s", name); - } + XXX: use crc64 to minimize collisions? */ + if (section_type == LTO_section_opts) + strcpy (post, ""); + else + sprintf (post, ".%x", f ? f->id : crc32_string(0, get_random_seed (false))); + return concat (LTO_SECTION_NAME_PREFIX, sep, add, post, NULL); } diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index cc38b22d179..3304132b1d0 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -600,6 +600,15 @@ struct GTY(()) lto_file_decl_data /* Hash new name of renamed global declaration to its original name. */ htab_t GTY((skip)) renaming_hash_table; + + /* Linked list used temporarily in reader */ + struct lto_file_decl_data *next; + + /* Sub ID for merged objects. */ + unsigned id; + + /* Symbol resolutions for this file */ + VEC(ld_plugin_symbol_resolution_t,heap) *resolutions; }; typedef struct lto_file_decl_data *lto_file_decl_data_ptr; @@ -815,7 +824,7 @@ extern void lto_record_function_out_decl_state (tree, extern const char *lto_tag_name (enum LTO_tags); extern bitmap lto_bitmap_alloc (void); extern void lto_bitmap_free (bitmap); -extern char *lto_get_section_name (int, const char *); +extern char *lto_get_section_name (int, const char *, struct lto_file_decl_data *); extern void print_lto_report (void); extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree, int *, unsigned *); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index b1b3c48ca50..97853b34a37 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,19 @@ +2010-07-10 Andi Kleen <ak@linux.intel.com> + + PR lto/44992 + * lto.c: Include splay-tree.h + (lto_resolution_read): Change to walk file_ids tree and parse + extra file_id in resolution file. + (lto_section_with_id): Add. + (create_subid_section_table): Add. + (lwstate): Add. + (lto_create_files_from_ids): Add. + (lto_file_read): Change to handle sub file ids and create list + of file_datas. Add output argument for count. + (get_section_data): Pass file_data to lto_get_section_name. + (lto_flatten_file): Add. + (read_cgraph_and_symbols): Handle linked lists of file_datas. + 2010-07-08 Manuel López-Ibáñez <manu@gcc.gnu.org> * lto-coff.c: Include diagnostic-core.h in every file that diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 2a0049494ca..e4ee214f622 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "lto.h" #include "lto-tree.h" #include "lto-streamer.h" +#include "splay-tree.h" /* This needs to be included after config.h. Otherwise, _GNU_SOURCE will not be defined in time to set __USE_GNU in the system headers, and strsignal @@ -309,11 +310,10 @@ lto_parse_hex (const char *p) { } /* Read resolution for file named FILE_NAME. The resolution is read from - RESOLUTION. An array with the symbol resolution is returned. The array - size is written to SIZE. */ + RESOLUTION. */ -static VEC(ld_plugin_symbol_resolution_t,heap) * -lto_resolution_read (FILE *resolution, lto_file *file) +static void +lto_resolution_read (splay_tree file_ids, FILE *resolution, lto_file *file) { /* We require that objects in the resolution file are in the same order as the lto1 command line. */ @@ -321,11 +321,12 @@ lto_resolution_read (FILE *resolution, lto_file *file) char *obj_name; unsigned int num_symbols; unsigned int i; - VEC(ld_plugin_symbol_resolution_t,heap) *ret = NULL; + struct lto_file_decl_data *file_data; unsigned max_index = 0; + splay_tree_node nd = NULL; if (!resolution) - return NULL; + return; name_len = strlen (file->filename); obj_name = XNEWVEC (char, name_len + 1); @@ -356,15 +357,15 @@ lto_resolution_read (FILE *resolution, lto_file *file) for (i = 0; i < num_symbols; i++) { int t; - unsigned index; + unsigned index, id; char r_str[27]; enum ld_plugin_symbol_resolution r = (enum ld_plugin_symbol_resolution) 0; unsigned int j; unsigned int lto_resolution_str_len = sizeof (lto_resolution_str) / sizeof (char *); - t = fscanf (resolution, "%u %26s %*[^\n]\n", &index, r_str); - if (t != 2) + t = fscanf (resolution, "%u %x %26s %*[^\n]\n", &index, &id, r_str); + if (t != 3) internal_error ("Invalid line in the resolution file."); if (index > max_index) max_index = index; @@ -380,12 +381,120 @@ lto_resolution_read (FILE *resolution, lto_file *file) if (j == lto_resolution_str_len) internal_error ("Invalid resolution in the resolution file."); - VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, ret, + if (!(nd && nd->key == id)) + { + nd = splay_tree_lookup (file_ids, id); + if (nd == NULL) + internal_error ("Resolution sub id %x not in object file", id); + } + + file_data = (struct lto_file_decl_data *)nd->value; + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "Adding resolution %u %u to id %x\n", + index, r, file_data->id); + VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, + file_data->resolutions, max_index + 1); - VEC_replace (ld_plugin_symbol_resolution_t, ret, index, r); + VEC_replace (ld_plugin_symbol_resolution_t, + file_data->resolutions, index, r); } +} - return ret; +/* Is the name for a id'ed LTO section? */ + +static int +lto_section_with_id (const char *name, unsigned *id) +{ + char *s; + + if (strncmp (name, LTO_SECTION_NAME_PREFIX, strlen (LTO_SECTION_NAME_PREFIX))) + return 0; + s = strrchr (name, '.'); + return s && sscanf (s, ".%x", id) == 1; +} + +/* Create file_data of each sub file id */ + +static int +create_subid_section_table (void **slot, void *data) +{ + struct lto_section_slot s_slot, *new_slot; + struct lto_section_slot *ls = *(struct lto_section_slot **)slot; + splay_tree file_ids = (splay_tree)data; + unsigned id; + splay_tree_node nd; + void **hash_slot; + char *new_name; + struct lto_file_decl_data *file_data; + + if (!lto_section_with_id (ls->name, &id)) + return 1; + + /* Find hash table of sub module id */ + nd = splay_tree_lookup (file_ids, id); + if (nd != NULL) + { + file_data = (struct lto_file_decl_data *)nd->value; + } + else + { + file_data = ggc_alloc_lto_file_decl_data (); + memset(file_data, 0, sizeof (struct lto_file_decl_data)); + file_data->id = id; + file_data->section_hash_table = lto_obj_create_section_hash_table ();; + splay_tree_insert (file_ids, id, (splay_tree_value)file_data); + } + + /* Copy section into sub module hash table */ + new_name = XDUPVEC (char, ls->name, strlen (ls->name) + 1); + s_slot.name = new_name; + hash_slot = htab_find_slot (file_data->section_hash_table, &s_slot, INSERT); + gcc_assert (*hash_slot == NULL); + + new_slot = XDUP (struct lto_section_slot, ls); + new_slot->name = new_name; + *hash_slot = new_slot; + return 1; +} + +/* Read declarations and other initializations for a FILE_DATA. */ + +static void +lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file) +{ + const char *data; + size_t len; + + file_data->renaming_hash_table = lto_create_renaming_table (); + file_data->file_name = file->filename; + data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len); + gcc_assert (data != NULL); + lto_read_decls (file_data, data, file_data->resolutions); + lto_free_section_data (file_data, LTO_section_decls, NULL, data, len); +} + +struct lwstate +{ + lto_file *file; + struct lto_file_decl_data **file_data; + int *count; +}; + +/* Traverse ids and create a list of file_datas out of it. */ + +static int lto_create_files_from_ids (splay_tree_node node, void *data) +{ + struct lwstate *lw = (struct lwstate *)data; + struct lto_file_decl_data *file_data = (struct lto_file_decl_data *)node->value; + + lto_file_finalize (file_data, lw->file); + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "Creating file %s with sub id %x\n", + file_data->file_name, file_data->id); + file_data->next = *lw->file_data; + *lw->file_data = file_data; + (*lw->count)++; + return 0; } /* Generate a TREE representation for all types and external decls @@ -396,23 +505,32 @@ lto_resolution_read (FILE *resolution, lto_file *file) the .o file to load the functions and ipa information. */ static struct lto_file_decl_data * -lto_file_read (lto_file *file, FILE *resolution_file) +lto_file_read (lto_file *file, FILE *resolution_file, int *count) { - struct lto_file_decl_data *file_data; - const char *data; - size_t len; - VEC(ld_plugin_symbol_resolution_t,heap) *resolutions; + struct lto_file_decl_data *file_data = NULL; + splay_tree file_ids; + htab_t section_hash_table; + struct lwstate state; - resolutions = lto_resolution_read (resolution_file, file); + section_hash_table = lto_obj_build_section_table (file); - file_data = ggc_alloc_lto_file_decl_data (); - file_data->file_name = file->filename; - file_data->section_hash_table = lto_obj_build_section_table (file); - file_data->renaming_hash_table = lto_create_renaming_table (); - - data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len); - lto_read_decls (file_data, data, resolutions); - lto_free_section_data (file_data, LTO_section_decls, NULL, data, len); + /* Find all sub modules in the object and put their sections into new hash + tables in a splay tree. */ + file_ids = splay_tree_new (splay_tree_compare_ints, NULL, NULL); + htab_traverse (section_hash_table, create_subid_section_table, file_ids); + + /* Add resolutions to file ids */ + lto_resolution_read (file_ids, resolution_file, file); + + /* Finalize each lto file for each submodule in the merged object + and create list for returning. */ + state.file = file; + state.file_data = &file_data; + state.count = count; + splay_tree_foreach (file_ids, lto_create_files_from_ids, &state); + + splay_tree_delete (file_ids); + htab_delete (section_hash_table); return file_data; } @@ -507,7 +625,7 @@ get_section_data (struct lto_file_decl_data *file_data, htab_t section_hash_table = file_data->section_hash_table; struct lto_section_slot *f_slot; struct lto_section_slot s_slot; - const char *section_name = lto_get_section_name (section_type, name); + const char *section_name = lto_get_section_name (section_type, name, file_data); char *data = NULL; *len = 0; @@ -1538,6 +1656,33 @@ lto_read_all_file_options (void) static GTY((length ("lto_stats.num_input_files + 1"))) struct lto_file_decl_data **all_file_decl_data; +/* Turn file datas for sub files into a single array, so that they look + like separate files for further passes. */ + +static void +lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix) +{ + struct lto_file_decl_data *n, *next; + int i, k; + + lto_stats.num_input_files = count; + all_file_decl_data + = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1); + /* Set the hooks so that all of the ipa passes can read in their data. */ + lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); + for (i = 0, k = 0; i < last_file_ix; i++) + { + for (n = orig[i]; n != NULL; n = next) + { + all_file_decl_data[k++] = n; + next = n->next; + n->next = NULL; + } + } + all_file_decl_data[k] = NULL; + gcc_assert (k == count); +} + /* Read all the symbols from the input files FNAMES. NFILES is the number of files requested in the command line. Instantiate a global call graph by aggregating all the sub-graphs found in each @@ -1549,16 +1694,14 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) unsigned int i, last_file_ix; FILE *resolution; struct cgraph_node *node; + int count = 0; + struct lto_file_decl_data **decl_data; - lto_stats.num_input_files = nfiles; init_cgraph (); timevar_push (TV_IPA_LTO_DECL_IN); - /* Set the hooks so that all of the ipa passes can read in their data. */ - all_file_decl_data - = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1); - lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); + decl_data = (struct lto_file_decl_data **)xmalloc (sizeof(*decl_data) * (nfiles+1)); /* Read the resolution file. */ resolution = NULL; @@ -1595,11 +1738,11 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) if (!current_lto_file) break; - file_data = lto_file_read (current_lto_file, resolution); + file_data = lto_file_read (current_lto_file, resolution, &count); if (!file_data) break; - all_file_decl_data[last_file_ix++] = file_data; + decl_data[last_file_ix++] = file_data; lto_obj_file_close (current_lto_file); current_lto_file = NULL; @@ -1607,11 +1750,13 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) code in gimple.c uses hashtables that are not ggc aware. */ } + lto_flatten_files (decl_data, count, last_file_ix); + lto_stats.num_input_files = count; + free(decl_data); + if (resolution_file_name) fclose (resolution); - all_file_decl_data[last_file_ix] = NULL; - /* Set the hooks so that all of the ipa passes can read in their data. */ lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); diff --git a/lto-plugin/ChangeLog b/lto-plugin/ChangeLog index 04a091b1021..a8f7461298c 100644 --- a/lto-plugin/ChangeLog +++ b/lto-plugin/ChangeLog @@ -1,3 +1,20 @@ +2010-07-10 Andi Kleen <ak@linux.intel.com> + + PR lto/44992 + * lto-plugin.c (sym_aux): Add. + (plugin_symtab): Remove slots. Add aux and id. + (parse_table_entry): Change to use aux instead of slots. + (LTO_SECTION_PREFIX): Add. + (translate): Improve buffer allocation. Change to append + symbols to existing out buffer. + (get_section): Remove. + (process_symtab): Add. + (free_2): Free symtab->aux. + (write_resolution): Handle aux instead of slots. + Print sub id to resolution file. + (claim_file_handler): Clear lto_file. Replace get_symtab/translate + calls with call to process_symtab. + 2010-07-22 Richard Guenther <rguenther@suse.de> * Makefile.am: New copy_lto_plugin rule to install the plugin diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c index c82f50d97f9..314759bc462 100644 --- a/lto-plugin/lto-plugin.c +++ b/lto-plugin/lto-plugin.c @@ -55,11 +55,18 @@ along with this program; see the file COPYING3. If not see must keep SYMS until all_symbols_read is called to give the linker time to copy the symbol information. */ +struct sym_aux +{ + uint32_t slot; + unsigned id; +}; + struct plugin_symtab { int nsyms; - uint32_t *slots; + struct sym_aux *aux; struct ld_plugin_symbol *syms; + unsigned id; }; /* All that we have to remember about a file. */ @@ -120,7 +127,8 @@ check (bool 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, uint32_t *slot) +parse_table_entry (char *p, struct ld_plugin_symbol *entry, + struct sym_aux *aux) { unsigned char t; enum ld_plugin_symbol_kind translate_kind[] = @@ -170,7 +178,7 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot) entry->size = *(uint64_t *) p; p += 8; - *slot = *(uint32_t *) p; + aux->slot = *(uint32_t *) p; p += 4; entry->resolution = LDPR_UNKNOWN; @@ -178,16 +186,51 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot) return p; } -/* Return the section in ELF that is named NAME. */ +#define LTO_SECTION_PREFIX ".gnu.lto_.symtab" + +/* Translate the IL symbol table SYMTAB. Append the slots and symbols to OUT. */ + +static void +translate (Elf_Data *symtab, struct plugin_symtab *out) +{ + struct sym_aux *aux; + char *data = symtab->d_buf; + char *end = data + symtab->d_size; + struct ld_plugin_symbol *syms = NULL; + int n, len; + + /* This overestimates the output buffer sizes, but at least + the algorithm is O(1) now. */ + + len = (end - data)/8 + out->nsyms + 1; + syms = xrealloc (out->syms, len * sizeof (struct ld_plugin_symbol)); + aux = xrealloc (out->aux, len * sizeof (struct sym_aux)); + + for (n = out->nsyms; data < end; n++) + { + aux[n].id = out->id; + data = parse_table_entry (data, &syms[n], &aux[n]); + } + + fprintf (stderr, "n = %d len = %d end-data=%lu\n", n, len, end-data); + assert(n < len); + + out->nsyms = n; + out->syms = syms; + out->aux = aux; +} + +/* Process all lto symtabs of file ELF. */ -static Elf_Scn * -get_section (Elf *elf, const char *name) +static int +process_symtab (Elf *elf, struct plugin_symtab *out) { + int found = 0; Elf_Scn *section = 0; GElf_Ehdr header; GElf_Ehdr *t = gelf_getehdr (elf, &header); if (t == NULL) - return NULL; + return 0; assert (t == &header); while ((section = elf_nextscn(elf, section)) != 0) @@ -198,51 +241,16 @@ get_section (Elf *elf, const char *name) assert (tshdr == &shdr); t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name); assert (t != NULL); - if (strcmp (t, name) == 0) - return section; - } - return NULL; -} - -/* Returns the IL symbol table of file ELF. */ - -static Elf_Data * -get_symtab (Elf *elf) -{ - Elf_Data *data = 0; - Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab"); - if (!section) - return NULL; - - data = elf_getdata (section, data); - assert (data); - return data; -} - -/* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */ - -static void -translate (Elf_Data *symtab, struct plugin_symtab *out) -{ - uint32_t *slots = NULL; - char *data = symtab->d_buf; - char *end = data + symtab->d_size; - struct ld_plugin_symbol *syms = NULL; - int n = 0; - - while (data < end) - { - n++; - syms = xrealloc (syms, n * sizeof (struct ld_plugin_symbol)); - check (syms, LDPL_FATAL, "could not allocate memory"); - slots = xrealloc (slots, n * sizeof (uint32_t)); - check (slots, LDPL_FATAL, "could not allocate memory"); - data = parse_table_entry (data, &syms[n - 1], &slots[n - 1]); + if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0) + { + char *s = strrchr (t, '.'); + if (s) + sscanf (s, ".%x", &out->id); + translate (elf_getdata (section, NULL), out); + found = 1; + } } - - out->nsyms = n; - out->syms = syms; - out->slots = slots; + return found; } /* Free all memory that is no longer needed after writing the symbol @@ -279,7 +287,7 @@ free_2 (void) { struct plugin_file_info *info = &claimed_files[i]; struct plugin_symtab *symtab = &info->symtab; - free (symtab->slots); + free (symtab->aux); free (info->name); } @@ -323,9 +331,10 @@ write_resolution (void) for (j = 0; j < info->symtab.nsyms; j++) { - uint32_t slot = symtab->slots[j]; + uint32_t slot = symtab->aux[j].slot; unsigned int resolution = syms[j].resolution; - fprintf (f, "%d %s %s\n", slot, lto_resolution_str[resolution], syms[j].name); + fprintf (f, "%d %x %s %s\n", slot, symtab->aux[j].id, + lto_resolution_str[resolution], syms[j].name); } } fclose (f); @@ -551,7 +560,8 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) enum ld_plugin_status status; Elf *elf; struct plugin_file_info lto_file; - Elf_Data *symtab; + + memset (<o_file, 0, sizeof (struct plugin_file_info)); if (file->offset != 0) { @@ -588,15 +598,9 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) *claimed = 0; - if (!elf) + if (!elf || !process_symtab (elf, <o_file.symtab)) goto err; - symtab = get_symtab (elf); - if (!symtab) - goto err; - - translate (symtab, <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"); |