mirror of git://gcc.gnu.org/git/gcc.git
re PR lto/81968 (early lto debug objects make Solaris ld SEGV)
2018-01-11 Richard Biener <rguenther@suse.de> Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> PR lto/81968 libiberty/ * simple-object-common.h (struct simple_object_functions): Change copy_lto_debug_sections callback signature. * simple-object-elf.c (SHN_HIRESERVE, SHT_SYMTAB_SHNDX, SHF_INFO_LINK): Add defines. (simple_object_elf_copy_lto_debug_sections): Instead of leaving not to be copied sections empty unnamed SHT_NULL remove them from the target section headers and adjust section reference everywhere. Handle SHN_XINDEX in the symbol table processing properly. * simple-object.c (handle_lto_debug_sections): Change interface to return a modified string and handle renaming of relocation sections. Co-Authored-By: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> From-SVN: r256528
This commit is contained in:
parent
ec538483a1
commit
bf6f2cc7be
|
@ -1,3 +1,20 @@
|
||||||
|
2018-01-11 Richard Biener <rguenther@suse.de>
|
||||||
|
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||||
|
|
||||||
|
PR lto/81968
|
||||||
|
* simple-object-common.h (struct simple_object_functions):
|
||||||
|
Change copy_lto_debug_sections callback signature.
|
||||||
|
* simple-object-elf.c (SHN_HIRESERVE, SHT_SYMTAB_SHNDX,
|
||||||
|
SHF_INFO_LINK): Add defines.
|
||||||
|
(simple_object_elf_copy_lto_debug_sections): Instead of
|
||||||
|
leaving not to be copied sections empty unnamed SHT_NULL
|
||||||
|
remove them from the target section headers and adjust section
|
||||||
|
reference everywhere. Handle SHN_XINDEX in the symbol table
|
||||||
|
processing properly.
|
||||||
|
* simple-object.c (handle_lto_debug_sections): Change
|
||||||
|
interface to return a modified string and handle renaming
|
||||||
|
of relocation sections.
|
||||||
|
|
||||||
2018-01-10 Daniel van Gerpen <daniel@vangerpen.de>
|
2018-01-10 Daniel van Gerpen <daniel@vangerpen.de>
|
||||||
|
|
||||||
* argv.c (expandargv): Correct check for dynamically
|
* argv.c (expandargv): Correct check for dynamically
|
||||||
|
|
|
@ -145,7 +145,7 @@ struct simple_object_functions
|
||||||
/* Copy LTO debug sections. */
|
/* Copy LTO debug sections. */
|
||||||
const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
|
const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
|
||||||
simple_object_write *dobj,
|
simple_object_write *dobj,
|
||||||
int (*pfn) (const char **),
|
char *(*pfn) (const char *),
|
||||||
int *err);
|
int *err);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ typedef struct {
|
||||||
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
|
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
|
||||||
#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
|
#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
|
||||||
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
|
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
|
||||||
|
#define SHN_HIRESERVE 0xffff /* End of reserved indices */
|
||||||
|
|
||||||
|
|
||||||
/* 32-bit ELF program header. */
|
/* 32-bit ELF program header. */
|
||||||
|
@ -193,9 +194,11 @@ typedef struct {
|
||||||
#define SHT_RELA 4 /* Relocation entries with addends */
|
#define SHT_RELA 4 /* Relocation entries with addends */
|
||||||
#define SHT_REL 9 /* Relocation entries, no addends */
|
#define SHT_REL 9 /* Relocation entries, no addends */
|
||||||
#define SHT_GROUP 17 /* Section contains a section group */
|
#define SHT_GROUP 17 /* Section contains a section group */
|
||||||
|
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
||||||
|
|
||||||
/* Values for sh_flags field. */
|
/* Values for sh_flags field. */
|
||||||
|
|
||||||
|
#define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */
|
||||||
#define SHF_EXECINSTR 0x00000004 /* Executable section. */
|
#define SHF_EXECINSTR 0x00000004 /* Executable section. */
|
||||||
#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
|
#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
|
||||||
section from executable and
|
section from executable and
|
||||||
|
@ -1070,7 +1073,7 @@ simple_object_elf_release_write (void *data)
|
||||||
static const char *
|
static const char *
|
||||||
simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
simple_object_write *dobj,
|
simple_object_write *dobj,
|
||||||
int (*pfn) (const char **),
|
char *(*pfn) (const char *),
|
||||||
int *err)
|
int *err)
|
||||||
{
|
{
|
||||||
struct simple_object_elf_read *eor =
|
struct simple_object_elf_read *eor =
|
||||||
|
@ -1091,7 +1094,10 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
int changed;
|
int changed;
|
||||||
int *pfnret;
|
int *pfnret;
|
||||||
const char **pfnname;
|
const char **pfnname;
|
||||||
|
unsigned new_i;
|
||||||
|
unsigned *sh_map;
|
||||||
unsigned first_shndx = 0;
|
unsigned first_shndx = 0;
|
||||||
|
unsigned int *symtab_indices_shndx;
|
||||||
|
|
||||||
shdr_size = (ei_class == ELFCLASS32
|
shdr_size = (ei_class == ELFCLASS32
|
||||||
? sizeof (Elf32_External_Shdr)
|
? sizeof (Elf32_External_Shdr)
|
||||||
|
@ -1130,18 +1136,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
eow->shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
|
|
||||||
pfnret = XNEWVEC (int, shnum);
|
pfnret = XNEWVEC (int, shnum);
|
||||||
pfnname = XNEWVEC (const char *, shnum);
|
pfnname = XNEWVEC (const char *, shnum);
|
||||||
|
|
||||||
|
/* Map of symtab to index section. */
|
||||||
|
symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
|
||||||
|
|
||||||
/* First perform the callbacks to know which sections to preserve and
|
/* First perform the callbacks to know which sections to preserve and
|
||||||
what name to use for those. */
|
what name to use for those. */
|
||||||
for (i = 1; i < shnum; ++i)
|
for (i = 1; i < shnum; ++i)
|
||||||
{
|
{
|
||||||
unsigned char *shdr;
|
unsigned char *shdr;
|
||||||
unsigned int sh_name;
|
unsigned int sh_name, sh_type;
|
||||||
const char *name;
|
const char *name;
|
||||||
int ret;
|
char *ret;
|
||||||
|
|
||||||
shdr = shdrs + (i - 1) * shdr_size;
|
shdr = shdrs + (i - 1) * shdr_size;
|
||||||
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
@ -1156,12 +1164,28 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
|
|
||||||
name = (const char *) names + sh_name;
|
name = (const char *) names + sh_name;
|
||||||
|
|
||||||
ret = (*pfn) (&name);
|
ret = (*pfn) (name);
|
||||||
pfnret[i - 1] = ret == 1 ? 0 : -1;
|
pfnret[i - 1] = ret == NULL ? -1 : 0;
|
||||||
pfnname[i - 1] = name;
|
pfnname[i - 1] = ret == NULL ? name : ret;
|
||||||
if (first_shndx == 0
|
if (first_shndx == 0
|
||||||
&& pfnret[i - 1] == 0)
|
&& pfnret[i - 1] == 0)
|
||||||
first_shndx = i;
|
first_shndx = i;
|
||||||
|
|
||||||
|
/* Remember the indexes of existing SHT_SYMTAB_SHNDX sections. */
|
||||||
|
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_type, Elf_Word);
|
||||||
|
if (sh_type == SHT_SYMTAB_SHNDX)
|
||||||
|
{
|
||||||
|
unsigned int sh_link;
|
||||||
|
sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_link, Elf_Word);
|
||||||
|
symtab_indices_shndx[sh_link - 1] = i;
|
||||||
|
/* Always discard the extended index sections, after
|
||||||
|
copying it will not be needed. This way we don't need to
|
||||||
|
update it and deal with the ordering constraints of
|
||||||
|
processing the existing symtab and changing the index. */
|
||||||
|
pfnret[i - 1] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark sections as preserved that are required by to be preserved
|
/* Mark sections as preserved that are required by to be preserved
|
||||||
|
@ -1244,7 +1268,26 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
}
|
}
|
||||||
while (changed);
|
while (changed);
|
||||||
|
|
||||||
|
/* Compute a mapping of old -> new section numbers. */
|
||||||
|
sh_map = XNEWVEC (unsigned, shnum);
|
||||||
|
sh_map[0] = 0;
|
||||||
|
new_i = 1;
|
||||||
|
for (i = 1; i < shnum; ++i)
|
||||||
|
{
|
||||||
|
if (pfnret[i - 1] == -1)
|
||||||
|
sh_map[i] = 0;
|
||||||
|
else
|
||||||
|
sh_map[i] = new_i++;
|
||||||
|
}
|
||||||
|
if (new_i - 1 >= SHN_LORESERVE)
|
||||||
|
{
|
||||||
|
*err = ENOTSUP;
|
||||||
|
return "Too many copied sections";
|
||||||
|
}
|
||||||
|
eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
|
||||||
|
|
||||||
/* Then perform the actual copying. */
|
/* Then perform the actual copying. */
|
||||||
|
new_i = 0;
|
||||||
for (i = 1; i < shnum; ++i)
|
for (i = 1; i < shnum; ++i)
|
||||||
{
|
{
|
||||||
unsigned char *shdr;
|
unsigned char *shdr;
|
||||||
|
@ -1252,11 +1295,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
const char *name;
|
const char *name;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
off_t length;
|
off_t length;
|
||||||
int ret;
|
|
||||||
simple_object_write_section *dest;
|
simple_object_write_section *dest;
|
||||||
off_t flags;
|
off_t flags;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
|
||||||
|
if (pfnret[i - 1])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
new_i++;
|
||||||
shdr = shdrs + (i - 1) * shdr_size;
|
shdr = shdrs + (i - 1) * shdr_size;
|
||||||
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
shdr, sh_name, Elf_Word);
|
shdr, sh_name, Elf_Word);
|
||||||
|
@ -1265,10 +1311,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
*err = 0;
|
*err = 0;
|
||||||
XDELETEVEC (names);
|
XDELETEVEC (names);
|
||||||
XDELETEVEC (shdrs);
|
XDELETEVEC (shdrs);
|
||||||
|
XDELETEVEC (symtab_indices_shndx);
|
||||||
return "ELF section name out of range";
|
return "ELF section name out of range";
|
||||||
}
|
}
|
||||||
|
|
||||||
name = (const char *) names + sh_name;
|
name = pfnname[i - 1];
|
||||||
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
shdr, sh_offset, Elf_Addr);
|
shdr, sh_offset, Elf_Addr);
|
||||||
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
@ -1276,178 +1323,223 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
shdr, sh_type, Elf_Word);
|
shdr, sh_type, Elf_Word);
|
||||||
|
|
||||||
ret = pfnret[i - 1];
|
dest = simple_object_write_create_section (dobj, pfnname[i - 1],
|
||||||
name = ret == 0 ? pfnname[i - 1] : "";
|
0, &errmsg, err);
|
||||||
|
|
||||||
dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err);
|
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
{
|
{
|
||||||
XDELETEVEC (names);
|
XDELETEVEC (names);
|
||||||
XDELETEVEC (shdrs);
|
XDELETEVEC (shdrs);
|
||||||
|
XDELETEVEC (symtab_indices_shndx);
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the SHDR of the source. */
|
/* Record the SHDR of the source. */
|
||||||
memcpy (eow->shdrs + (i - 1) * shdr_size, shdr, shdr_size);
|
memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
|
||||||
shdr = eow->shdrs + (i - 1) * shdr_size;
|
shdr = eow->shdrs + (new_i - 1) * shdr_size;
|
||||||
|
|
||||||
/* Copy the data.
|
/* Copy the data.
|
||||||
??? This is quite wasteful and ideally would be delayed until
|
??? This is quite wasteful and ideally would be delayed until
|
||||||
write_to_file (). Thus it questions the interfacing
|
write_to_file (). Thus it questions the interfacing
|
||||||
which eventually should contain destination creation plus
|
which eventually should contain destination creation plus
|
||||||
writing. */
|
writing. */
|
||||||
/* Keep empty sections for sections we should discard. This avoids
|
buf = XNEWVEC (unsigned char, length);
|
||||||
the need to rewrite section indices in symtab and relocation
|
if (!simple_object_internal_read (sobj->descriptor,
|
||||||
sections. */
|
sobj->offset + offset, buf,
|
||||||
if (ret == 0)
|
(size_t) length, &errmsg, err))
|
||||||
{
|
{
|
||||||
buf = XNEWVEC (unsigned char, length);
|
XDELETEVEC (buf);
|
||||||
if (!simple_object_internal_read (sobj->descriptor,
|
XDELETEVEC (names);
|
||||||
sobj->offset + offset, buf,
|
XDELETEVEC (shdrs);
|
||||||
(size_t) length, &errmsg, err))
|
XDELETEVEC (symtab_indices_shndx);
|
||||||
{
|
return errmsg;
|
||||||
XDELETEVEC (buf);
|
}
|
||||||
XDELETEVEC (names);
|
|
||||||
XDELETEVEC (shdrs);
|
|
||||||
return errmsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we are processing .symtab purge __gnu_lto_v1 and
|
/* If we are processing .symtab purge __gnu_lto_v1 and
|
||||||
__gnu_lto_slim symbols from it. */
|
__gnu_lto_slim symbols from it and any symbols in discarded
|
||||||
if (sh_type == SHT_SYMTAB)
|
sections. */
|
||||||
|
if (sh_type == SHT_SYMTAB)
|
||||||
|
{
|
||||||
|
unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_entsize, Elf_Addr);
|
||||||
|
unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_link, Elf_Word);
|
||||||
|
unsigned char *strshdr = shdrs + (strtab - 1) * shdr_size;
|
||||||
|
off_t stroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
strshdr, sh_offset, Elf_Addr);
|
||||||
|
size_t strsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
strshdr, sh_size, Elf_Addr);
|
||||||
|
char *strings = XNEWVEC (char, strsz);
|
||||||
|
char *gnu_lto = strings;
|
||||||
|
unsigned char *ent;
|
||||||
|
unsigned *shndx_table = NULL;
|
||||||
|
simple_object_internal_read (sobj->descriptor,
|
||||||
|
sobj->offset + stroff,
|
||||||
|
(unsigned char *)strings,
|
||||||
|
strsz, &errmsg, err);
|
||||||
|
/* Find gnu_lto_ in strings. */
|
||||||
|
while ((gnu_lto = (char *) memchr (gnu_lto, 'g',
|
||||||
|
strings + strsz - gnu_lto)))
|
||||||
|
if (strncmp (gnu_lto, "gnu_lto_v1",
|
||||||
|
strings + strsz - gnu_lto) == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
gnu_lto++;
|
||||||
|
/* Read the section index table if present. */
|
||||||
|
if (symtab_indices_shndx[i - 1] != 0)
|
||||||
{
|
{
|
||||||
unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
unsigned char *sidxhdr = shdrs + (strtab - 1) * shdr_size;
|
||||||
shdr, sh_entsize, Elf_Addr);
|
off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
sidxhdr, sh_offset, Elf_Addr);
|
||||||
shdr, sh_link, Elf_Word);
|
size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
unsigned char *strshdr = shdrs + (strtab - 1) * shdr_size;
|
sidxhdr, sh_size, Elf_Addr);
|
||||||
off_t stroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
|
||||||
strshdr, sh_offset, Elf_Addr);
|
|
||||||
size_t strsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
||||||
strshdr, sh_size, Elf_Addr);
|
|
||||||
char *strings = XNEWVEC (char, strsz);
|
|
||||||
unsigned char *ent;
|
|
||||||
simple_object_internal_read (sobj->descriptor,
|
simple_object_internal_read (sobj->descriptor,
|
||||||
sobj->offset + stroff,
|
sobj->offset + sidxoff,
|
||||||
(unsigned char *)strings,
|
(unsigned char *)shndx_table,
|
||||||
strsz, &errmsg, err);
|
sidxsz, &errmsg, err);
|
||||||
/* Find gnu_lto_ in strings. */
|
}
|
||||||
char *gnu_lto = strings;
|
for (ent = buf; ent < buf + length; ent += entsize)
|
||||||
while ((gnu_lto = memchr (gnu_lto, 'g',
|
{
|
||||||
strings + strsz - gnu_lto)))
|
unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
|
||||||
if (strncmp (gnu_lto, "gnu_lto_v1",
|
Sym, ent,
|
||||||
strings + strsz - gnu_lto) == 0)
|
st_shndx, Elf_Half);
|
||||||
break;
|
unsigned raw_st_shndx = st_shndx;
|
||||||
else
|
unsigned char *st_info;
|
||||||
gnu_lto++;
|
unsigned char *st_other;
|
||||||
for (ent = buf; ent < buf + length; ent += entsize)
|
int discard = 0;
|
||||||
|
if (ei_class == ELFCLASS32)
|
||||||
{
|
{
|
||||||
unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
|
st_info = &((Elf32_External_Sym *)ent)->st_info;
|
||||||
Sym, ent,
|
st_other = &((Elf32_External_Sym *)ent)->st_other;
|
||||||
st_shndx, Elf_Half);
|
}
|
||||||
unsigned char *st_info;
|
else
|
||||||
unsigned char *st_other;
|
{
|
||||||
int discard = 0;
|
st_info = &((Elf64_External_Sym *)ent)->st_info;
|
||||||
if (ei_class == ELFCLASS32)
|
st_other = &((Elf64_External_Sym *)ent)->st_other;
|
||||||
|
}
|
||||||
|
if (st_shndx == SHN_XINDEX)
|
||||||
|
st_shndx = type_functions->fetch_Elf_Word
|
||||||
|
((unsigned char *)(shndx_table + (ent - buf) / entsize));
|
||||||
|
/* Eliminate all COMMONs - this includes __gnu_lto_v1
|
||||||
|
and __gnu_lto_slim which otherwise cause endless
|
||||||
|
LTO plugin invocation. */
|
||||||
|
if (st_shndx == SHN_COMMON)
|
||||||
|
discard = 1;
|
||||||
|
/* We also need to remove symbols refering to sections
|
||||||
|
we'll eventually remove as with fat LTO objects
|
||||||
|
we otherwise get duplicate symbols at final link
|
||||||
|
(with GNU ld, gold is fine and ignores symbols in
|
||||||
|
sections marked as EXCLUDE). ld/20513 */
|
||||||
|
else if (st_shndx != SHN_UNDEF
|
||||||
|
&& st_shndx < shnum
|
||||||
|
&& pfnret[st_shndx - 1] == -1)
|
||||||
|
discard = 1;
|
||||||
|
|
||||||
|
if (discard)
|
||||||
|
{
|
||||||
|
/* Make discarded symbols undefined and unnamed
|
||||||
|
in case it is local. */
|
||||||
|
int bind = ELF_ST_BIND (*st_info);
|
||||||
|
int other = STV_DEFAULT;
|
||||||
|
if (bind == STB_LOCAL)
|
||||||
{
|
{
|
||||||
st_info = &((Elf32_External_Sym *)ent)->st_info;
|
/* Make discarded local symbols unnamed and
|
||||||
st_other = &((Elf32_External_Sym *)ent)->st_other;
|
defined in the first prevailing section. */
|
||||||
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
|
ent, st_name, Elf_Word, 0);
|
||||||
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
|
ent, st_shndx, Elf_Half,
|
||||||
|
sh_map[first_shndx]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
st_info = &((Elf64_External_Sym *)ent)->st_info;
|
/* Make discarded global symbols hidden weak
|
||||||
st_other = &((Elf64_External_Sym *)ent)->st_other;
|
undefined and sharing the gnu_lto_ name. */
|
||||||
}
|
bind = STB_WEAK;
|
||||||
/* Eliminate all COMMONs - this includes __gnu_lto_v1
|
other = STV_HIDDEN;
|
||||||
and __gnu_lto_slim which otherwise cause endless
|
if (gnu_lto)
|
||||||
LTO plugin invocation. */
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
if (st_shndx == SHN_COMMON)
|
ent, st_name, Elf_Word,
|
||||||
discard = 1;
|
gnu_lto - strings);
|
||||||
/* We also need to remove symbols refering to sections
|
|
||||||
we'll eventually remove as with fat LTO objects
|
|
||||||
we otherwise get duplicate symbols at final link
|
|
||||||
(with GNU ld, gold is fine and ignores symbols in
|
|
||||||
sections marked as EXCLUDE). ld/20513 */
|
|
||||||
else if (st_shndx != SHN_UNDEF
|
|
||||||
&& st_shndx < shnum
|
|
||||||
&& pfnret[st_shndx - 1] == -1)
|
|
||||||
discard = 1;
|
|
||||||
|
|
||||||
if (discard)
|
|
||||||
{
|
|
||||||
/* Make discarded symbols undefined and unnamed
|
|
||||||
in case it is local. */
|
|
||||||
int bind = ELF_ST_BIND (*st_info);
|
|
||||||
int other = STV_DEFAULT;
|
|
||||||
if (bind == STB_LOCAL)
|
|
||||||
{
|
|
||||||
/* Make discarded local symbols unnamed and
|
|
||||||
defined in the first prevailing section. */
|
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
||||||
ent, st_name, Elf_Word, 0);
|
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
||||||
ent, st_shndx, Elf_Half, first_shndx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make discarded global symbols hidden weak
|
|
||||||
undefined and sharing the gnu_lto_ name. */
|
|
||||||
bind = STB_WEAK;
|
|
||||||
other = STV_HIDDEN;
|
|
||||||
if (gnu_lto)
|
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
||||||
ent, st_name, Elf_Word,
|
|
||||||
gnu_lto - strings);
|
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
||||||
ent, st_shndx, Elf_Half, SHN_UNDEF);
|
|
||||||
}
|
|
||||||
*st_other = other;
|
|
||||||
*st_info = ELF_ST_INFO (bind, STT_NOTYPE);
|
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
ent, st_value, Elf_Addr, 0);
|
ent, st_shndx, Elf_Half, SHN_UNDEF);
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
||||||
ent, st_size, Elf_Word, 0);
|
|
||||||
}
|
}
|
||||||
|
*st_other = other;
|
||||||
|
*st_info = ELF_ST_INFO (bind, STT_NOTYPE);
|
||||||
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
|
ent, st_value, Elf_Addr, 0);
|
||||||
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
|
ent, st_size, Elf_Word, 0);
|
||||||
}
|
}
|
||||||
XDELETEVEC (strings);
|
else if (raw_st_shndx < SHN_LORESERVE
|
||||||
}
|
|| raw_st_shndx == SHN_XINDEX)
|
||||||
|
/* Remap the section reference. */
|
||||||
errmsg = simple_object_write_add_data (dobj, dest,
|
ELF_SET_FIELD (type_functions, ei_class, Sym,
|
||||||
buf, length, 1, err);
|
ent, st_shndx, Elf_Half, sh_map[st_shndx]);
|
||||||
XDELETEVEC (buf);
|
|
||||||
if (errmsg)
|
|
||||||
{
|
|
||||||
XDELETEVEC (names);
|
|
||||||
XDELETEVEC (shdrs);
|
|
||||||
return errmsg;
|
|
||||||
}
|
}
|
||||||
|
XDELETEVEC (strings);
|
||||||
|
XDELETEVEC (shndx_table);
|
||||||
}
|
}
|
||||||
else
|
else if (sh_type == SHT_GROUP)
|
||||||
{
|
{
|
||||||
/* For deleted sections mark the section header table entry as
|
/* Remap section indices in groups and remove removed members. */
|
||||||
unused. That allows the link editor to remove it in a partial
|
unsigned char *ent, *dst;
|
||||||
link. */
|
for (dst = ent = buf + 4; ent < buf + length; ent += 4)
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
{
|
||||||
shdr, sh_type, Elf_Word, SHT_NULL);
|
unsigned shndx = type_functions->fetch_Elf_Word (ent);
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
if (pfnret[shndx - 1] == -1)
|
||||||
shdr, sh_info, Elf_Word, 0);
|
;
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
else
|
||||||
shdr, sh_link, Elf_Word, 0);
|
{
|
||||||
|
type_functions->set_Elf_Word (dst, sh_map[shndx]);
|
||||||
|
dst += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Adjust the length. */
|
||||||
|
length = dst - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
errmsg = simple_object_write_add_data (dobj, dest,
|
||||||
|
buf, length, 1, err);
|
||||||
|
XDELETEVEC (buf);
|
||||||
|
if (errmsg)
|
||||||
|
{
|
||||||
|
XDELETEVEC (names);
|
||||||
|
XDELETEVEC (shdrs);
|
||||||
|
XDELETEVEC (symtab_indices_shndx);
|
||||||
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
shdr, sh_flags, Elf_Addr);
|
shdr, sh_flags, Elf_Addr);
|
||||||
if (ret == 0)
|
/* Remap the section references. */
|
||||||
{
|
{
|
||||||
/* The debugobj doesn't contain any code, thus no trampolines.
|
unsigned int sh_info, sh_link;
|
||||||
Even when the original object needs trampolines, debugobj
|
if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
|
||||||
doesn't. */
|
{
|
||||||
if (strcmp (name, ".note.GNU-stack") == 0)
|
sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
flags &= ~SHF_EXECINSTR;
|
shdr, sh_info, Elf_Word);
|
||||||
flags &= ~SHF_EXCLUDE;
|
if (sh_info < SHN_LORESERVE
|
||||||
}
|
|| sh_info > SHN_HIRESERVE)
|
||||||
else if (ret == -1)
|
sh_info = sh_map[sh_info];
|
||||||
flags = SHF_EXCLUDE;
|
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_info, Elf_Word, sh_info);
|
||||||
|
}
|
||||||
|
sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_link, Elf_Word);
|
||||||
|
if (sh_link < SHN_LORESERVE
|
||||||
|
|| sh_link > SHN_HIRESERVE)
|
||||||
|
sh_link = sh_map[sh_link];
|
||||||
|
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
||||||
|
shdr, sh_link, Elf_Word, sh_link);
|
||||||
|
}
|
||||||
|
/* The debugobj doesn't contain any code, thus no trampolines.
|
||||||
|
Even when the original object needs trampolines, debugobj
|
||||||
|
doesn't. */
|
||||||
|
if (strcmp (name, ".note.GNU-stack") == 0)
|
||||||
|
flags &= ~SHF_EXECINSTR;
|
||||||
|
/* Clear SHF_EXCLUDE on to be preserved sections. */
|
||||||
|
flags &= ~SHF_EXCLUDE;
|
||||||
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
||||||
shdr, sh_flags, Elf_Addr, flags);
|
shdr, sh_flags, Elf_Addr, flags);
|
||||||
}
|
}
|
||||||
|
@ -1456,6 +1548,8 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
||||||
XDELETEVEC (shdrs);
|
XDELETEVEC (shdrs);
|
||||||
XDELETEVEC (pfnret);
|
XDELETEVEC (pfnret);
|
||||||
XDELETEVEC (pfnname);
|
XDELETEVEC (pfnname);
|
||||||
|
XDELETEVEC (symtab_indices_shndx);
|
||||||
|
XDELETEVEC (sh_map);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,30 +253,38 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
|
||||||
/* Callback to identify and rename LTO debug sections by name.
|
/* Callback to identify and rename LTO debug sections by name.
|
||||||
Returns 1 if NAME is a LTO debug section, 0 if not. */
|
Returns 1 if NAME is a LTO debug section, 0 if not. */
|
||||||
|
|
||||||
static int
|
static char *
|
||||||
handle_lto_debug_sections (const char **name)
|
handle_lto_debug_sections (const char *name)
|
||||||
{
|
{
|
||||||
|
char *newname = XCNEWVEC (char, strlen (name) + 1);
|
||||||
|
|
||||||
/* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
|
/* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
|
||||||
complains about bogus section flags. Which means we need to arrange
|
complains about bogus section flags. Which means we need to arrange
|
||||||
for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
|
for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
|
||||||
fat lto object tooling work for the fat part). */
|
fat lto object tooling work for the fat part). */
|
||||||
|
/* Also include corresponding reloc sections. */
|
||||||
|
if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
|
||||||
|
{
|
||||||
|
strncpy (newname, name, sizeof (".rela") - 1);
|
||||||
|
name += sizeof (".rela") - 1;
|
||||||
|
}
|
||||||
|
else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
|
||||||
|
{
|
||||||
|
strncpy (newname, name, sizeof (".rel") - 1);
|
||||||
|
name += sizeof (".rel") - 1;
|
||||||
|
}
|
||||||
/* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
|
/* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
|
||||||
sections. */
|
sections. */
|
||||||
/* Copy LTO debug sections and rename them to their non-LTO name. */
|
/* Copy LTO debug sections and rename them to their non-LTO name. */
|
||||||
if (strncmp (*name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
|
if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
|
||||||
{
|
return strcat (newname, name + sizeof (".gnu.debuglto_") - 1);
|
||||||
*name = *name + sizeof (".gnu.debuglto_") - 1;
|
else if (strncmp (name, ".gnu.lto_.debug_",
|
||||||
return 1;
|
sizeof (".gnu.lto_.debug_") -1) == 0)
|
||||||
}
|
return strcat (newname, name + sizeof (".gnu.lto_") - 1);
|
||||||
else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
|
|
||||||
{
|
|
||||||
*name = *name + sizeof (".gnu.lto_") - 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Copy over .note.GNU-stack section under the same name if present. */
|
/* Copy over .note.GNU-stack section under the same name if present. */
|
||||||
else if (strcmp (*name, ".note.GNU-stack") == 0)
|
else if (strcmp (name, ".note.GNU-stack") == 0)
|
||||||
return 1;
|
return strcpy (newname, name);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy LTO debug sections. */
|
/* Copy LTO debug sections. */
|
||||||
|
|
Loading…
Reference in New Issue