Import latest fixes to libiberty from GCC.

PR lto/81968
	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
	Keep names of removed global symbols.

	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
	Improve .go_export csect handling.  Don't make assumptions
	on containing section or number of auxiliary entries.

	PR lto/81968
	* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
	Adjust field with for sh_type write, set SHF_EXCLUDE only for
	removed sections.

	PR lto/81925
	* simple-object-elf.c (simple_object_elf_write_shdr): Adjust
	type of sh_addralign and sh_entsize and properly write
	sh_entsize as Elf_Addr.
	(simple_object_elf_write_to_file): Read sh_entsize as Elf_Addr.

	* simple-object-common.h (struct simple_object_functions): Add
	copy_lto_debug_sections hook.
	* simple-object.c: Include fcntl.h.
	(handle_lto_debug_sections): New helper function.
	(simple_object_copy_lto_debug_sections): New function copying
	early LTO debug sections to regular debug sections in a new file.
	(simple_object_start_write): Handle NULL segment_name.
	* simple-object-coff.c (simple_object_coff_functions): Adjust
	for not implemented copy_lto_debug_sections hook.
	* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
	* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
	* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
	SHT_GROUP): Add various sectopn header types.
	(SHF_EXCLUDE): Add flag.
	(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
	(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
	(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
	(STV_DEFAULT): Add symbol visibility.
	(SHN_COMMON): Add special section index name.
	(struct simple_object_elf_write): New.
	(simple_object_elf_start_write): Adjust for new private data.
	(simple_object_elf_write_shdr): Pass in values for all fields
	we write.
	(simple_object_elf_write_to_file): Adjust.  Copy from recorded
	section headers if requested.
	(simple_object_elf_release_write): Release private data.
	(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
	as denoted by PFN and all their dependences, symbols and relocations
	to the empty destination file.
	(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.

	* simple-object-xcoff.c (simple_object_xcoff_find_sections):
	Search symbol table for .go_export symbol and apply pfn if found.
This commit is contained in:
Nick Clifton 2017-09-01 10:52:53 +01:00
parent 2a143b99fc
commit f8ad251375
7 changed files with 802 additions and 36 deletions

View File

@ -1,18 +1,80 @@
2017-08-31 Richard Biener <rguenther@suse.de>
PR lto/81968
* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
Keep names of removed global symbols.
2017-08-29 Tony Reix <tony.reix@atos.net>
* simple-object-xcoff.c (simple_object_xcoff_find_sections):
Improve .go_export csect handling. Don't make assumptions
on containing section or number of auxiliary entries.
2017-08-28 Richard Biener <rguenther@suse.de>
PR lto/81968
* simple-object-elf.c (simple_object_elf_copy_lto_debug_section):
Adjust field with for sh_type write, set SHF_EXCLUDE only for
removed sections.
2017-08-22 Richard Biener <rguenther@suse.de>
PR lto/81925
* simple-object-elf.c (simple_object_elf_write_shdr): Adjust
type of sh_addralign and sh_entsize and properly write
sh_entsize as Elf_Addr.
(simple_object_elf_write_to_file): Read sh_entsize as Elf_Addr.
2017-08-21 Richard Biener <rguenther@suse.de>
* simple-object-common.h (struct simple_object_functions): Add
copy_lto_debug_sections hook.
* simple-object.c: Include fcntl.h.
(handle_lto_debug_sections): New helper function.
(simple_object_copy_lto_debug_sections): New function copying
early LTO debug sections to regular debug sections in a new file.
(simple_object_start_write): Handle NULL segment_name.
* simple-object-coff.c (simple_object_coff_functions): Adjust
for not implemented copy_lto_debug_sections hook.
* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
SHT_GROUP): Add various sectopn header types.
(SHF_EXCLUDE): Add flag.
(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
(STV_DEFAULT): Add symbol visibility.
(SHN_COMMON): Add special section index name.
(struct simple_object_elf_write): New.
(simple_object_elf_start_write): Adjust for new private data.
(simple_object_elf_write_shdr): Pass in values for all fields
we write.
(simple_object_elf_write_to_file): Adjust. Copy from recorded
section headers if requested.
(simple_object_elf_release_write): Release private data.
(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
as denoted by PFN and all their dependences, symbols and relocations
to the empty destination file.
(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.
2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarfnames.c (DW_FIRST_IDX, DW_END_IDX, DW_IDX, DW_IDX_DUP): New.
2017-06-07 Tony Reix <tony.reix@atos.net>
Matthieu Sarter <matthieu.sarter.external@atos.net>
David Edelsohn <dje.gcc@gmail.com>
* simple-object-xcoff.c (simple_object_xcoff_find_sections):
Search symbol table for .go_export symbol and apply pfn if found.
2017-05-31 DJ Delorie <dj@redhat.com>
* configure.ac (strnlen): Add to AC_CHECK_DECLS.
* configure: Likewise.
* config.in: Add HACE_DECL_STRNLEN.
2017-05-31 Eli Zaretskii <eliz@gnu.org>
* waitpid.c (wait) [__MINGW32__]: Define as a macro
that calls _cwait, so that this function works on MinGW.
2017-05-27 Iain Buclaw <ibuclaw@gdcproject.org>
* d-demangle.c (dlang_identifier): Prefix mangled init symbols
@ -32,6 +94,11 @@
the demangled hexadecimal directly to string.
* testsuite/d-demangle-expected: Add tests.
2017-05-24 Eli Zaretskii <eliz@gnu.org>
* waitpid.c (wait) [__MINGW32__]: Define as a macro
that calls _cwait, so that this function works on MinGW.
2017-05-02 Iain Buclaw <ibuclaw@gdcproject.org>
* d-demangle.c (dlang_hexdigit): New function.

View File

@ -800,5 +800,6 @@ const struct simple_object_functions simple_object_coff_functions =
simple_object_coff_release_attributes,
simple_object_coff_start_write,
simple_object_coff_write_to_file,
simple_object_coff_release_write
simple_object_coff_release_write,
NULL
};

View File

@ -141,6 +141,12 @@ struct simple_object_functions
/* Release the private data for an simple_object_write. */
void (*release_write) (void *);
/* Copy LTO debug sections. */
const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
simple_object_write *dobj,
int (*pfn) (const char **),
int *err);
};
/* The known object file formats. */

View File

@ -122,9 +122,12 @@ typedef struct {
/* Special section index values. */
#define SHN_UNDEF 0 /* Undefined section */
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
/* 32-bit ELF program header. */
typedef struct {
@ -183,8 +186,57 @@ typedef struct {
/* Values for sh_type field. */
#define SHT_NULL 0 /* Section header table entry unused */
#define SHT_PROGBITS 1 /* Program data */
#define SHT_SYMTAB 2 /* Link editing symbol table */
#define SHT_STRTAB 3 /* A string table */
#define SHT_RELA 4 /* Relocation entries with addends */
#define SHT_REL 9 /* Relocation entries, no addends */
#define SHT_GROUP 17 /* Section contains a section group */
/* Values for sh_flags field. */
#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
section from executable and
shared library that it builds
when those objects are not to be
further relocated. */
/* Symbol table entry. */
typedef struct
{
unsigned char st_name[4]; /* Symbol name (string tbl index) */
unsigned char st_value[4]; /* Symbol value */
unsigned char st_size[4]; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
unsigned char st_shndx[2]; /* Section index */
} Elf32_External_Sym;
typedef struct
{
unsigned char st_name[4]; /* Symbol name (string tbl index) */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
unsigned char st_shndx[2]; /* Section index */
unsigned char st_value[8]; /* Symbol value */
unsigned char st_size[8]; /* Symbol size */
} Elf64_External_Sym;
#define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)
#define ELF_ST_TYPE(val) ((val) & 0xf)
#define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define STT_NOTYPE 0 /* Symbol type is unspecified */
#define STT_OBJECT 1 /* Symbol is a data object */
#define STT_FUNC 2 /* Symbol is a code object */
#define STT_TLS 6 /* Thread local data object */
#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STV_DEFAULT 0 /* Visibility is specified by binding type */
/* Functions to fetch and store different ELF types, depending on the
endianness and size. */
@ -348,6 +400,14 @@ struct simple_object_elf_attributes
unsigned int flags;
};
/* Private data for an simple_object_write. */
struct simple_object_elf_write
{
struct simple_object_elf_attributes attrs;
unsigned char *shdrs;
};
/* See if we have an ELF file. */
static void *
@ -527,6 +587,11 @@ simple_object_elf_find_sections (simple_object_read *sobj,
/* Read the section names. */
if (eor->shstrndx == 0)
{
XDELETEVEC (shdrs);
return "ELF section header string table missing";
}
shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shstrhdr, sh_size, Elf_Addr);
@ -675,12 +740,13 @@ simple_object_elf_start_write (void *attributes_data,
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) attributes_data;
struct simple_object_elf_attributes *ret;
struct simple_object_elf_write *ret;
/* We're just going to record the attributes, but we need to make a
copy because the user may delete them. */
ret = XNEW (struct simple_object_elf_attributes);
*ret = *attrs;
ret = XNEW (struct simple_object_elf_write);
ret->attrs = *attrs;
ret->shdrs = NULL;
return ret;
}
@ -766,8 +832,11 @@ static int
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
off_t offset, unsigned int sh_name,
unsigned int sh_type, unsigned int sh_flags,
off_t sh_addr,
unsigned int sh_offset, unsigned int sh_size,
unsigned int sh_link, unsigned int sh_addralign,
unsigned int sh_link, unsigned int sh_info,
size_t sh_addralign,
size_t sh_entsize,
const char **errmsg, int *err)
{
struct simple_object_elf_attributes *attrs =
@ -788,12 +857,13 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
/* sh_info left as zero. */
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
/* sh_entsize left as zero. */
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
return simple_object_internal_write (descriptor, offset, buf, shdr_size,
errmsg, err);
@ -811,8 +881,9 @@ static const char *
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
int *err)
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) sobj->data;
struct simple_object_elf_write *eow =
(struct simple_object_elf_write *) sobj->data;
struct simple_object_elf_attributes *attrs = &eow->attrs;
unsigned char cl;
size_t ehdr_size;
size_t shdr_size;
@ -825,6 +896,7 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
unsigned int first_sh_link;
size_t sh_name;
unsigned char zero;
unsigned secnum;
if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
return errmsg;
@ -862,21 +934,54 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
else
first_sh_link = shnum - 1;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
0, 0, 0, 0, first_sh_size, first_sh_link,
0, &errmsg, err))
0, 0, 0, 0, 0, first_sh_size, first_sh_link,
0, 0, 0, &errmsg, err))
return errmsg;
shdr_offset += shdr_size;
sh_name = 1;
secnum = 0;
for (section = sobj->sections; section != NULL; section = section->next)
{
size_t mask;
size_t new_sh_offset;
size_t sh_size;
struct simple_object_write_section_buffer *buffer;
unsigned int sh_type = SHT_PROGBITS;
unsigned int sh_flags = 0;
off_t sh_addr = 0;
unsigned int sh_link = 0;
unsigned int sh_info = 0;
size_t sh_addralign = 1U << section->align;
size_t sh_entsize = 0;
if (eow->shdrs)
{
sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_type, Elf_Word);
sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_flags, Elf_Addr);
sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_addr, Elf_Addr);
sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_link, Elf_Word);
sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_info, Elf_Word);
sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_addralign, Elf_Addr);
sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_entsize, Elf_Addr);
secnum++;
}
mask = (1U << section->align) - 1;
mask = sh_addralign - 1;
new_sh_offset = sh_offset + mask;
new_sh_offset &= ~ mask;
while (new_sh_offset > sh_offset)
@ -906,8 +1011,10 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_PROGBITS, 0, sh_offset,
sh_size, 0, 1U << section->align,
sh_name, sh_type, sh_flags,
sh_addr, sh_offset,
sh_size, sh_link, sh_info,
sh_addralign, sh_entsize,
&errmsg, err))
return errmsg;
@ -917,9 +1024,9 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_STRTAB, 0, sh_offset,
sh_name + strlen (".shstrtab") + 1, 0,
1, &errmsg, err))
sh_name, SHT_STRTAB, 0, 0, sh_offset,
sh_name + strlen (".shstrtab") + 1, 0, 0,
1, 0, &errmsg, err))
return errmsg;
/* .shstrtab has a leading zero byte. */
@ -954,9 +1061,356 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
static void
simple_object_elf_release_write (void *data)
{
struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
if (eow->shdrs)
XDELETE (eow->shdrs);
XDELETE (data);
}
/* Copy all sections in an ELF file. */
static const char *
simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
simple_object_write *dobj,
int (*pfn) (const char **),
int *err)
{
struct simple_object_elf_read *eor =
(struct simple_object_elf_read *) sobj->data;
const struct elf_type_functions *type_functions = eor->type_functions;
struct simple_object_elf_write *eow =
(struct simple_object_elf_write *) dobj->data;
unsigned char ei_class = eor->ei_class;
size_t shdr_size;
unsigned int shnum;
unsigned char *shdrs;
const char *errmsg;
unsigned char *shstrhdr;
size_t name_size;
off_t shstroff;
unsigned char *names;
unsigned int i;
int *pfnret;
const char **pfnname;
shdr_size = (ei_class == ELFCLASS32
? sizeof (Elf32_External_Shdr)
: sizeof (Elf64_External_Shdr));
/* Read the section headers. We skip section 0, which is not a
useful section. */
shnum = eor->shnum;
shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + eor->shoff + shdr_size,
shdrs,
shdr_size * (shnum - 1),
&errmsg, err))
{
XDELETEVEC (shdrs);
return errmsg;
}
/* Read the section names. */
shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shstrhdr, sh_size, Elf_Addr);
shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shstrhdr, sh_offset, Elf_Addr);
names = XNEWVEC (unsigned char, name_size);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + shstroff,
names, name_size, &errmsg, err))
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
eow->shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
pfnret = XNEWVEC (int, shnum);
pfnname = XNEWVEC (const char *, shnum);
/* First perform the callbacks to know which sections to preserve and
what name to use for those. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_name;
const char *name;
int ret;
shdr = shdrs + (i - 1) * shdr_size;
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_name, Elf_Word);
if (sh_name >= name_size)
{
*err = 0;
XDELETEVEC (names);
XDELETEVEC (shdrs);
return "ELF section name out of range";
}
name = (const char *) names + sh_name;
ret = (*pfn) (&name);
pfnret[i - 1] = ret == 1 ? 0 : -1;
pfnname[i - 1] = name;
}
/* Mark sections as preserved that are required by to be preserved
sections. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_type, sh_info, sh_link;
off_t offset;
off_t length;
shdr = shdrs + (i - 1) * shdr_size;
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Word);
sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_info, Elf_Word);
sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_link, Elf_Word);
if (sh_type == SHT_GROUP)
{
/* Mark groups containing copied sections. */
unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_entsize, Elf_Addr);
unsigned char *ent, *buf;
int keep = 0;
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_offset, Elf_Addr);
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_size, Elf_Addr);
buf = XNEWVEC (unsigned char, length);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + offset, buf,
(size_t) length, &errmsg, err))
{
XDELETEVEC (buf);
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
for (ent = buf + entsize; ent < buf + length; ent += entsize)
{
unsigned sec = type_functions->fetch_Elf_Word (ent);
if (pfnret[sec - 1] == 0)
keep = 1;
}
if (keep)
{
pfnret[sh_link - 1] = 0;
pfnret[i - 1] = 0;
}
}
if (sh_type == SHT_RELA
|| sh_type == SHT_REL)
{
/* Mark relocation sections and symtab of copied sections. */
if (pfnret[sh_info - 1] == 0)
{
pfnret[sh_link - 1] = 0;
pfnret[i - 1] = 0;
}
}
if (sh_type == SHT_SYMTAB)
{
/* Mark strings sections of copied symtabs. */
if (pfnret[i - 1] == 0)
pfnret[sh_link - 1] = 0;
}
}
/* Then perform the actual copying. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_name, sh_type;
const char *name;
off_t offset;
off_t length;
int ret;
const char *errmsg;
simple_object_write_section *dest;
off_t flags;
unsigned char *buf;
shdr = shdrs + (i - 1) * shdr_size;
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_name, Elf_Word);
if (sh_name >= name_size)
{
*err = 0;
XDELETEVEC (names);
XDELETEVEC (shdrs);
return "ELF section name out of range";
}
name = (const char *) names + sh_name;
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_offset, Elf_Addr);
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_size, Elf_Addr);
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Word);
ret = pfnret[i - 1];
name = ret == 0 ? pfnname[i - 1] : "";
dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err);
if (dest == NULL)
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
/* Record the SHDR of the source. */
memcpy (eow->shdrs + (i - 1) * shdr_size, shdr, shdr_size);
shdr = eow->shdrs + (i - 1) * shdr_size;
/* Copy the data.
??? This is quite wasteful and ideally would be delayed until
write_to_file (). Thus it questions the interfacing
which eventually should contain destination creation plus
writing. */
/* Keep empty sections for sections we should discard. This avoids
the need to rewrite section indices in symtab and relocation
sections. */
if (ret == 0)
{
buf = XNEWVEC (unsigned char, length);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + offset, buf,
(size_t) length, &errmsg, err))
{
XDELETEVEC (buf);
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
/* If we are processing .symtab purge __gnu_lto_v1 and
__gnu_lto_slim symbols from it. */
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);
unsigned char *ent;
simple_object_internal_read (sobj->descriptor,
sobj->offset + stroff,
(unsigned char *)strings,
strsz, &errmsg, err);
for (ent = buf; ent < buf + length; ent += entsize)
{
unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
Sym, ent,
st_shndx, Elf_Half);
unsigned char *st_info;
unsigned char *st_other;
int discard = 0;
if (ei_class == ELFCLASS32)
{
st_info = &((Elf32_External_Sym *)ent)->st_info;
st_other = &((Elf32_External_Sym *)ent)->st_other;
}
else
{
st_info = &((Elf64_External_Sym *)ent)->st_info;
st_other = &((Elf64_External_Sym *)ent)->st_other;
}
/* Eliminate all COMMONs - this includes __gnu_lto_v1
and __gnu_lto_slim which otherwise cause endless
LTO plugin invocation. */
if (st_shndx == SHN_COMMON)
/* Setting st_name to "" seems to work to purge
COMMON symbols (in addition to setting their
size to zero). */
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. */
if (ELF_ST_BIND (*st_info) == STB_LOCAL)
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_name, Elf_Word, 0);
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);
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_shndx, Elf_Half, SHN_UNDEF);
*st_info = ELF_ST_INFO (ELF_ST_BIND (*st_info),
STT_NOTYPE);
*st_other = STV_DEFAULT;
}
}
XDELETEVEC (strings);
}
errmsg = simple_object_write_add_data (dobj, dest,
buf, length, 1, err);
XDELETEVEC (buf);
if (errmsg)
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
}
else
{
/* For deleted sections mark the section header table entry as
unused. That allows the link editor to remove it in a partial
link. */
ELF_SET_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Word, SHT_NULL);
}
flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_flags, Elf_Addr);
if (ret == 0)
flags &= ~SHF_EXCLUDE;
else if (ret == -1)
flags = SHF_EXCLUDE;
ELF_SET_FIELD (type_functions, ei_class, Shdr,
shdr, sh_flags, Elf_Addr, flags);
}
XDELETEVEC (names);
XDELETEVEC (shdrs);
XDELETEVEC (pfnret);
XDELETEVEC (pfnname);
return NULL;
}
/* The ELF functions. */
const struct simple_object_functions simple_object_elf_functions =
@ -969,5 +1423,6 @@ const struct simple_object_functions simple_object_elf_functions =
simple_object_elf_release_attributes,
simple_object_elf_start_write,
simple_object_elf_write_to_file,
simple_object_elf_release_write
simple_object_elf_release_write,
simple_object_elf_copy_lto_debug_sections
};

View File

@ -1374,5 +1374,6 @@ const struct simple_object_functions simple_object_mach_o_functions =
simple_object_mach_o_release_attributes,
simple_object_mach_o_start_write,
simple_object_mach_o_write_to_file,
simple_object_mach_o_release_write
simple_object_mach_o_release_write,
NULL
};

View File

@ -138,15 +138,15 @@ struct external_syment
union {
struct {
union {
/* The name of the symbol. There is an implicit null character
after the end of the array. */
char n_name[N_SYMNMLEN];
struct {
/* If n_zeroes is zero, n_offset is the offset the name from
the start of the string table. */
unsigned char n_zeroes[4];
unsigned char n_offset[4];
} n;
/* The name of the symbol. There is an implicit null character
after the end of the array. */
char n_name[N_SYMNMLEN];
struct {
/* If n_zeroes is zero, n_offset is the offset the name from
the start of the string table. */
unsigned char n_zeroes[4];
unsigned char n_offset[4];
} n;
} n;
/* The symbol's value. */
@ -255,8 +255,14 @@ union external_auxent
#define IMAGE_SYM_TYPE \
((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
#define C_EXT (2)
#define C_STAT (3)
#define C_FILE (103)
#define C_HIDEXT (107)
#define XTY_SD (1) /* section definition */
#define XMC_XO (7) /* extended operation */
/* Private data for an simple_object_read. */
@ -398,11 +404,13 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
size_t scnhdr_size;
unsigned char *scnbuf;
const char *errmsg;
unsigned short (*fetch_16) (const unsigned char *);
unsigned int (*fetch_32) (const unsigned char *);
ulong_type (*fetch_64) (const unsigned char *);
unsigned int nscns;
char *strtab;
size_t strtab_size;
struct external_syment *symtab = NULL;
unsigned int i;
scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
@ -416,6 +424,7 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
return errmsg;
}
fetch_16 = simple_object_fetch_big_16;
fetch_32 = simple_object_fetch_big_32;
fetch_64 = simple_object_fetch_big_64;
@ -429,7 +438,7 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
char namebuf[SCNNMLEN + 1];
char *name;
off_t scnptr;
unsigned int size;
off_t size;
scnhdr = scnbuf + i * scnhdr_size;
scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
@ -489,6 +498,151 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
break;
}
/* Special handling for .go_export csect. */
if (ocr->nsyms > 0)
{
unsigned char *sym;
const char *n_name;
off_t size, n_value;
unsigned int n_numaux, n_offset, n_zeroes;
short n_scnum;
/* Read symbol table. */
symtab = XNEWVEC (struct external_syment, ocr->nsyms * SYMESZ);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + ocr->symptr,
(unsigned char *) symtab,
ocr->nsyms * SYMESZ,
&errmsg, err))
{
XDELETEVEC (symtab);
XDELETEVEC (scnbuf);
return NULL;
}
/* Search in symbol table if we have a ".go_export" symbol. */
for (i = 0; i < ocr->nsyms; i += n_numaux + 1)
{
sym = (unsigned char *) &symtab[i];
n_numaux = symtab[i].n_numaux[0];
if (symtab[i].n_sclass[0] != C_EXT
&& symtab[i].n_sclass[0] != C_HIDEXT)
continue;
/* Must have at least one csect auxiliary entry. */
if (n_numaux < 1 || i + n_numaux >= ocr->nsyms)
continue;
n_scnum = fetch_16 (sym + offsetof (struct external_syment,
n_scnum));
if (n_scnum < 1 || (unsigned int) n_scnum > nscns)
continue;
if (u64)
{
n_value = fetch_64 (sym + offsetof (struct external_syment,
u.xcoff64.n_value));
n_offset = fetch_32 (sym + offsetof (struct external_syment,
u.xcoff64.n_offset));
}
else
{
/* ".go_export" is longer than N_SYMNMLEN. */
n_zeroes = fetch_32 (sym + offsetof (struct external_syment,
u.xcoff32.n.n.n_zeroes));
if (n_zeroes != 0)
continue;
n_value = fetch_32 (sym + offsetof (struct external_syment,
u.xcoff32.n_value));
n_offset = fetch_32 (sym + offsetof (struct external_syment,
u.xcoff32.n.n.n_offset));
}
/* The real symbol name is found in the string table. */
if (strtab == NULL)
{
strtab = simple_object_xcoff_read_strtab (sobj,
&strtab_size,
&errmsg, err);
if (strtab == NULL)
{
XDELETEVEC (symtab);
XDELETEVEC (scnbuf);
return errmsg;
}
}
if (n_offset >= strtab_size)
{
XDELETEVEC (strtab);
XDELETEVEC (symtab);
XDELETEVEC (scnbuf);
*err = 0;
return "symbol string index out of range";
}
n_name = strtab + n_offset;
if (!strcmp (n_name, ".go_export"))
{
union external_auxent *auxent;
unsigned char *aux, *scnhdr;
off_t scnptr, x_scnlen;
/* Found .go_export symbol, read its csect auxiliary entry.
By convention, it is the last auxiliary entry. */
auxent = (union external_auxent *) &symtab[i + n_numaux];
aux = (unsigned char *) auxent;
if (u64)
{
if ((auxent->u.xcoff64.x_csect.x_smtyp & 0x7) != XTY_SD
|| auxent->u.xcoff64.x_csect.x_smclas != XMC_XO)
continue;
x_scnlen = fetch_32 (aux + offsetof (union external_auxent,
u.xcoff64.x_csect.x_scnlen_hi));
x_scnlen = x_scnlen << 32
| fetch_32 (aux + offsetof (union external_auxent,
u.xcoff64.x_csect.x_scnlen_lo));
}
else
{
if ((auxent->u.xcoff32.x_csect.x_smtyp & 0x7) != XTY_SD
|| auxent->u.xcoff32.x_csect.x_smclas != XMC_XO)
continue;
x_scnlen = fetch_32 (aux + offsetof (union external_auxent,
u.xcoff32.x_csect.x_scnlen));
}
/* Get header of containing section. */
scnhdr = scnbuf + (n_scnum - 1) * scnhdr_size;
if (u64)
{
scnptr = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
u.xcoff64.s_scnptr));
size = fetch_64 (scnhdr + offsetof (struct external_scnhdr,
u.xcoff64.s_size));
}
else
{
scnptr = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
u.xcoff32.s_scnptr));
size = fetch_32 (scnhdr + offsetof (struct external_scnhdr,
u.xcoff32.s_size));
}
if (n_value + x_scnlen > size)
break;
(*pfn) (data, ".go_export", scnptr + n_value, x_scnlen);
break;
}
}
}
if (symtab != NULL)
XDELETEVEC (symtab);
if (strtab != NULL)
XDELETEVEC (strtab);
XDELETEVEC (scnbuf);
@ -894,5 +1048,6 @@ const struct simple_object_functions simple_object_xcoff_functions =
simple_object_xcoff_release_attributes,
simple_object_xcoff_start_write,
simple_object_xcoff_write_to_file,
simple_object_xcoff_release_write
simple_object_xcoff_release_write,
NULL
};

View File

@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA. */
#include "simple-object.h"
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@ -249,6 +250,86 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
return 1;
}
/* Callback to identify and rename LTO debug sections by name.
Returns 1 if NAME is a LTO debug section, 0 if not. */
static int
handle_lto_debug_sections (const char **name)
{
/* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
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
fat lto object tooling work for the fat part). */
/* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
sections. */
/* Copy LTO debug sections and rename them to their non-LTO name. */
if (strncmp (*name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
{
*name = *name + sizeof (".gnu.debuglto_") - 1;
return 1;
}
else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
{
*name = *name + sizeof (".gnu.lto_") - 1;
return 1;
}
return 0;
}
/* Copy LTO debug sections. */
const char *
simple_object_copy_lto_debug_sections (simple_object_read *sobj,
const char *dest, int *err)
{
const char *errmsg;
simple_object_write *dest_sobj;
simple_object_attributes *attrs;
int outfd;
if (! sobj->functions->copy_lto_debug_sections)
{
*err = EINVAL;
return "simple_object_copy_lto_debug_sections not implemented";
}
attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
if (! attrs)
return errmsg;
dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
simple_object_release_attributes (attrs);
if (! dest_sobj)
return errmsg;
errmsg = sobj->functions->copy_lto_debug_sections (sobj, dest_sobj,
handle_lto_debug_sections,
err);
if (errmsg)
{
simple_object_release_write (dest_sobj);
return errmsg;
}
outfd = creat (dest, 00777);
if (outfd == -1)
{
*err = errno;
simple_object_release_write (dest_sobj);
return "open failed";
}
errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
close (outfd);
if (errmsg)
{
simple_object_release_write (dest_sobj);
return errmsg;
}
simple_object_release_write (dest_sobj);
return NULL;
}
/* Fetch attributes. */
simple_object_attributes *
@ -315,7 +396,7 @@ simple_object_start_write (simple_object_attributes *attrs,
return NULL;
ret = XNEW (simple_object_write);
ret->functions = attrs->functions;
ret->segment_name = xstrdup (segment_name);
ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
ret->sections = NULL;
ret->last_section = NULL;
ret->data = data;