Commit 73ce4d1e by Andi Kleen Committed by Andi Kleen

re PR lto/44992 (ld -r breaks LTO)

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.

From-SVN: r162443
parent 0011a34c
2010-07-10 Andi Kleen <ak@linux.intel.com> 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. * lto-opts.c (lto_read_file_options): Check for missing section.
2010-07-22 Bernd Schmidt <bernds@codesourcery.com> 2010-07-22 Bernd Schmidt <bernds@codesourcery.com>
......
...@@ -294,7 +294,7 @@ output_options (struct lto_output_stream *stream) ...@@ -294,7 +294,7 @@ output_options (struct lto_output_stream *stream)
void void
lto_write_options (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_output_stream stream;
struct lto_simple_header header; struct lto_simple_header header;
struct lto_output_stream *header_stream; struct lto_output_stream *header_stream;
......
...@@ -486,7 +486,7 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob) ...@@ -486,7 +486,7 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
struct lto_simple_header header; struct lto_simple_header header;
struct lto_output_stream *header_stream; 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); lto_begin_section (section_name, !flag_wpa);
free (section_name); free (section_name);
......
...@@ -1810,10 +1810,10 @@ produce_asm (struct output_block *ob, tree fn) ...@@ -1810,10 +1810,10 @@ produce_asm (struct output_block *ob, tree fn)
if (section_type == LTO_section_function_body) if (section_type == LTO_section_function_body)
{ {
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn)); 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 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); lto_begin_section (section_name, !flag_wpa);
free (section_name); free (section_name);
...@@ -2041,7 +2041,7 @@ copy_function (struct cgraph_node *node) ...@@ -2041,7 +2041,7 @@ copy_function (struct cgraph_node *node)
size_t len; size_t len;
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)); const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
char *section_name = 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; size_t i, j;
struct lto_in_decl_state *in_state; struct lto_in_decl_state *in_state;
struct lto_out_decl_state *out_state = lto_get_out_decl_state (); struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
...@@ -2398,7 +2398,7 @@ produce_symtab (struct output_block *ob, ...@@ -2398,7 +2398,7 @@ produce_symtab (struct output_block *ob,
cgraph_node_set set, varpool_node_set vset) cgraph_node_set set, varpool_node_set vset)
{ {
struct lto_streamer_cache_d *cache = ob->writer_cache; 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; bitmap seen;
struct cgraph_node *node, *alias; struct cgraph_node *node, *alias;
struct varpool_node *vnode, *valias; struct varpool_node *vnode, *valias;
...@@ -2477,7 +2477,7 @@ produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset) ...@@ -2477,7 +2477,7 @@ produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset)
memset (&header, 0, sizeof (struct lto_decl_header)); 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); lto_begin_section (section_name, !flag_wpa);
free (section_name); free (section_name);
......
...@@ -133,57 +133,45 @@ lto_bitmap_free (bitmap b) ...@@ -133,57 +133,45 @@ lto_bitmap_free (bitmap b)
/* Get a section name for a particular type or name. The NAME field /* 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 is only used if SECTION_TYPE is LTO_section_function_body. For all
LTO_static_initializer. For all others it is ignored. The callee others it is ignored. The callee of this function is responsible
of this function is responcible to free the returned name. */ to free the returned name. */
char * 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); gcc_assert (name != NULL);
if (name[0] == '*') if (name[0] == '*')
name++; name++;
return concat (LTO_SECTION_NAME_PREFIX, name, NULL); add = name;
sep = "";
case LTO_section_static_initializer: }
return concat (LTO_SECTION_NAME_PREFIX, ".statics", NULL); else if (section_type < LTO_N_SECTION_TYPES)
{
case LTO_section_symtab: add = lto_section_name[section_type];
return concat (LTO_SECTION_NAME_PREFIX, ".symtab", NULL); sep = ".";
}
case LTO_section_decls: else
return concat (LTO_SECTION_NAME_PREFIX, ".decls", NULL); internal_error ("bytecode stream: unexpected LTO section %s", name);
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);
case LTO_section_opts: /* Make the section name unique so that ld -r combining sections
return concat (LTO_SECTION_NAME_PREFIX, ".opts", NULL); doesn't confuse the reader with merged sections.
case LTO_section_cgraph_opt_sum: For options don't add a ID, the option reader cannot deal with them
return concat (LTO_SECTION_NAME_PREFIX, ".cgraphopt", NULL); and merging should be ok here.
default: XXX: use crc64 to minimize collisions? */
internal_error ("bytecode stream: unexpected LTO section %s", name); 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);
} }
......
...@@ -600,6 +600,15 @@ struct GTY(()) lto_file_decl_data ...@@ -600,6 +600,15 @@ struct GTY(()) lto_file_decl_data
/* Hash new name of renamed global declaration to its original name. */ /* Hash new name of renamed global declaration to its original name. */
htab_t GTY((skip)) renaming_hash_table; 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; typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
...@@ -815,7 +824,7 @@ extern void lto_record_function_out_decl_state (tree, ...@@ -815,7 +824,7 @@ extern void lto_record_function_out_decl_state (tree,
extern const char *lto_tag_name (enum LTO_tags); extern const char *lto_tag_name (enum LTO_tags);
extern bitmap lto_bitmap_alloc (void); extern bitmap lto_bitmap_alloc (void);
extern void lto_bitmap_free (bitmap); 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 void print_lto_report (void);
extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree, extern bool lto_streamer_cache_insert (struct lto_streamer_cache_d *, tree,
int *, unsigned *); int *, unsigned *);
......
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> 2010-07-08 Manuel López-Ibáñez <manu@gcc.gnu.org>
* lto-coff.c: Include diagnostic-core.h in every file that * lto-coff.c: Include diagnostic-core.h in every file that
......
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> 2010-07-22 Richard Guenther <rguenther@suse.de>
* Makefile.am: New copy_lto_plugin rule to install the plugin * Makefile.am: New copy_lto_plugin rule to install the plugin
......
...@@ -55,11 +55,18 @@ along with this program; see the file COPYING3. If not see ...@@ -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 must keep SYMS until all_symbols_read is called to give the linker time to
copy the symbol information. */ copy the symbol information. */
struct sym_aux
{
uint32_t slot;
unsigned id;
};
struct plugin_symtab struct plugin_symtab
{ {
int nsyms; int nsyms;
uint32_t *slots; struct sym_aux *aux;
struct ld_plugin_symbol *syms; struct ld_plugin_symbol *syms;
unsigned id;
}; };
/* All that we have to remember about a file. */ /* All that we have to remember about a file. */
...@@ -120,7 +127,8 @@ check (bool gate, enum ld_plugin_level level, const char *text) ...@@ -120,7 +127,8 @@ check (bool gate, enum ld_plugin_level level, const char *text)
Returns the address of the next entry. */ Returns the address of the next entry. */
static char * 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; unsigned char t;
enum ld_plugin_symbol_kind translate_kind[] = enum ld_plugin_symbol_kind translate_kind[] =
...@@ -170,7 +178,7 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot) ...@@ -170,7 +178,7 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
entry->size = *(uint64_t *) p; entry->size = *(uint64_t *) p;
p += 8; p += 8;
*slot = *(uint32_t *) p; aux->slot = *(uint32_t *) p;
p += 4; p += 4;
entry->resolution = LDPR_UNKNOWN; entry->resolution = LDPR_UNKNOWN;
...@@ -178,16 +186,51 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot) ...@@ -178,16 +186,51 @@ parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
return p; 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 * static int
get_section (Elf *elf, const char *name) process_symtab (Elf *elf, struct plugin_symtab *out)
{ {
int found = 0;
Elf_Scn *section = 0; Elf_Scn *section = 0;
GElf_Ehdr header; GElf_Ehdr header;
GElf_Ehdr *t = gelf_getehdr (elf, &header); GElf_Ehdr *t = gelf_getehdr (elf, &header);
if (t == NULL) if (t == NULL)
return NULL; return 0;
assert (t == &header); assert (t == &header);
while ((section = elf_nextscn(elf, section)) != 0) while ((section = elf_nextscn(elf, section)) != 0)
...@@ -198,51 +241,16 @@ get_section (Elf *elf, const char *name) ...@@ -198,51 +241,16 @@ get_section (Elf *elf, const char *name)
assert (tshdr == &shdr); assert (tshdr == &shdr);
t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name); t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
assert (t != NULL); assert (t != NULL);
if (strcmp (t, name) == 0) if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0)
return section; {
} char *s = strrchr (t, '.');
return NULL; if (s)
} sscanf (s, ".%x", &out->id);
translate (elf_getdata (section, NULL), out);
/* Returns the IL symbol table of file ELF. */ found = 1;
}
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]);
} }
return found;
out->nsyms = n;
out->syms = syms;
out->slots = slots;
} }
/* Free all memory that is no longer needed after writing the symbol /* Free all memory that is no longer needed after writing the symbol
...@@ -279,7 +287,7 @@ free_2 (void) ...@@ -279,7 +287,7 @@ free_2 (void)
{ {
struct plugin_file_info *info = &claimed_files[i]; struct plugin_file_info *info = &claimed_files[i];
struct plugin_symtab *symtab = &info->symtab; struct plugin_symtab *symtab = &info->symtab;
free (symtab->slots); free (symtab->aux);
free (info->name); free (info->name);
} }
...@@ -323,9 +331,10 @@ write_resolution (void) ...@@ -323,9 +331,10 @@ write_resolution (void)
for (j = 0; j < info->symtab.nsyms; j++) 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; 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); fclose (f);
...@@ -551,7 +560,8 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) ...@@ -551,7 +560,8 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
enum ld_plugin_status status; enum ld_plugin_status status;
Elf *elf; Elf *elf;
struct plugin_file_info lto_file; struct plugin_file_info lto_file;
Elf_Data *symtab;
memset (&lto_file, 0, sizeof (struct plugin_file_info));
if (file->offset != 0) if (file->offset != 0)
{ {
...@@ -588,15 +598,9 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) ...@@ -588,15 +598,9 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
*claimed = 0; *claimed = 0;
if (!elf) if (!elf || !process_symtab (elf, &lto_file.symtab))
goto err; goto err;
symtab = get_symtab (elf);
if (!symtab)
goto err;
translate (symtab, &lto_file.symtab);
status = add_symbols (file->handle, lto_file.symtab.nsyms, status = add_symbols (file->handle, lto_file.symtab.nsyms,
lto_file.symtab.syms); lto_file.symtab.syms);
check (status == LDPS_OK, LDPL_FATAL, "could not add symbols"); check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment