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:
parent
2a143b99fc
commit
f8ad251375
7 changed files with 802 additions and 36 deletions
|
@ -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>
|
2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
* dwarfnames.c (DW_FIRST_IDX, DW_END_IDX, DW_IDX, DW_IDX_DUP): New.
|
* 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>
|
2017-05-31 DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
* configure.ac (strnlen): Add to AC_CHECK_DECLS.
|
* configure.ac (strnlen): Add to AC_CHECK_DECLS.
|
||||||
* configure: Likewise.
|
* configure: Likewise.
|
||||||
* config.in: Add HACE_DECL_STRNLEN.
|
* 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>
|
2017-05-27 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||||
|
|
||||||
* d-demangle.c (dlang_identifier): Prefix mangled init symbols
|
* d-demangle.c (dlang_identifier): Prefix mangled init symbols
|
||||||
|
@ -32,6 +94,11 @@
|
||||||
the demangled hexadecimal directly to string.
|
the demangled hexadecimal directly to string.
|
||||||
* testsuite/d-demangle-expected: Add tests.
|
* 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>
|
2017-05-02 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||||
|
|
||||||
* d-demangle.c (dlang_hexdigit): New function.
|
* d-demangle.c (dlang_hexdigit): New function.
|
||||||
|
|
|
@ -800,5 +800,6 @@ const struct simple_object_functions simple_object_coff_functions =
|
||||||
simple_object_coff_release_attributes,
|
simple_object_coff_release_attributes,
|
||||||
simple_object_coff_start_write,
|
simple_object_coff_start_write,
|
||||||
simple_object_coff_write_to_file,
|
simple_object_coff_write_to_file,
|
||||||
simple_object_coff_release_write
|
simple_object_coff_release_write,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -141,6 +141,12 @@ struct simple_object_functions
|
||||||
|
|
||||||
/* Release the private data for an simple_object_write. */
|
/* Release the private data for an simple_object_write. */
|
||||||
void (*release_write) (void *);
|
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. */
|
/* The known object file formats. */
|
||||||
|
|
|
@ -122,9 +122,12 @@ typedef struct {
|
||||||
|
|
||||||
/* Special section index values. */
|
/* Special section index values. */
|
||||||
|
|
||||||
|
#define SHN_UNDEF 0 /* Undefined section */
|
||||||
#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_XINDEX 0xFFFF /* Section index is held elsewhere */
|
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
|
||||||
|
|
||||||
|
|
||||||
/* 32-bit ELF program header. */
|
/* 32-bit ELF program header. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -183,8 +186,57 @@ typedef struct {
|
||||||
|
|
||||||
/* Values for sh_type field. */
|
/* Values for sh_type field. */
|
||||||
|
|
||||||
|
#define SHT_NULL 0 /* Section header table entry unused */
|
||||||
#define SHT_PROGBITS 1 /* Program data */
|
#define SHT_PROGBITS 1 /* Program data */
|
||||||
|
#define SHT_SYMTAB 2 /* Link editing symbol table */
|
||||||
#define SHT_STRTAB 3 /* A string 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
|
/* Functions to fetch and store different ELF types, depending on the
|
||||||
endianness and size. */
|
endianness and size. */
|
||||||
|
@ -348,6 +400,14 @@ struct simple_object_elf_attributes
|
||||||
unsigned int flags;
|
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. */
|
/* See if we have an ELF file. */
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -527,6 +587,11 @@ simple_object_elf_find_sections (simple_object_read *sobj,
|
||||||
|
|
||||||
/* Read the section names. */
|
/* Read the section names. */
|
||||||
|
|
||||||
|
if (eor->shstrndx == 0)
|
||||||
|
{
|
||||||
|
XDELETEVEC (shdrs);
|
||||||
|
return "ELF section header string table missing";
|
||||||
|
}
|
||||||
shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
|
shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
|
||||||
name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
||||||
shstrhdr, sh_size, Elf_Addr);
|
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 *attrs =
|
||||||
(struct simple_object_elf_attributes *) attributes_data;
|
(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
|
/* We're just going to record the attributes, but we need to make a
|
||||||
copy because the user may delete them. */
|
copy because the user may delete them. */
|
||||||
ret = XNEW (struct simple_object_elf_attributes);
|
ret = XNEW (struct simple_object_elf_write);
|
||||||
*ret = *attrs;
|
ret->attrs = *attrs;
|
||||||
|
ret->shdrs = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,8 +832,11 @@ static int
|
||||||
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
|
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
|
||||||
off_t offset, unsigned int sh_name,
|
off_t offset, unsigned int sh_name,
|
||||||
unsigned int sh_type, unsigned int sh_flags,
|
unsigned int sh_type, unsigned int sh_flags,
|
||||||
|
off_t sh_addr,
|
||||||
unsigned int sh_offset, unsigned int sh_size,
|
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)
|
const char **errmsg, int *err)
|
||||||
{
|
{
|
||||||
struct simple_object_elf_attributes *attrs =
|
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_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_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_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_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_size, Elf_Addr, sh_size);
|
||||||
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
|
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);
|
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,
|
return simple_object_internal_write (descriptor, offset, buf, shdr_size,
|
||||||
errmsg, err);
|
errmsg, err);
|
||||||
|
@ -811,8 +881,9 @@ static const char *
|
||||||
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
|
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
|
||||||
int *err)
|
int *err)
|
||||||
{
|
{
|
||||||
struct simple_object_elf_attributes *attrs =
|
struct simple_object_elf_write *eow =
|
||||||
(struct simple_object_elf_attributes *) sobj->data;
|
(struct simple_object_elf_write *) sobj->data;
|
||||||
|
struct simple_object_elf_attributes *attrs = &eow->attrs;
|
||||||
unsigned char cl;
|
unsigned char cl;
|
||||||
size_t ehdr_size;
|
size_t ehdr_size;
|
||||||
size_t shdr_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;
|
unsigned int first_sh_link;
|
||||||
size_t sh_name;
|
size_t sh_name;
|
||||||
unsigned char zero;
|
unsigned char zero;
|
||||||
|
unsigned secnum;
|
||||||
|
|
||||||
if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
|
if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
|
||||||
return errmsg;
|
return errmsg;
|
||||||
|
@ -862,21 +934,54 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
|
||||||
else
|
else
|
||||||
first_sh_link = shnum - 1;
|
first_sh_link = shnum - 1;
|
||||||
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
||||||
0, 0, 0, 0, first_sh_size, first_sh_link,
|
0, 0, 0, 0, 0, first_sh_size, first_sh_link,
|
||||||
0, &errmsg, err))
|
0, 0, 0, &errmsg, err))
|
||||||
return errmsg;
|
return errmsg;
|
||||||
|
|
||||||
shdr_offset += shdr_size;
|
shdr_offset += shdr_size;
|
||||||
|
|
||||||
sh_name = 1;
|
sh_name = 1;
|
||||||
|
secnum = 0;
|
||||||
for (section = sobj->sections; section != NULL; section = section->next)
|
for (section = sobj->sections; section != NULL; section = section->next)
|
||||||
{
|
{
|
||||||
size_t mask;
|
size_t mask;
|
||||||
size_t new_sh_offset;
|
size_t new_sh_offset;
|
||||||
size_t sh_size;
|
size_t sh_size;
|
||||||
struct simple_object_write_section_buffer *buffer;
|
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 = sh_offset + mask;
|
||||||
new_sh_offset &= ~ mask;
|
new_sh_offset &= ~ mask;
|
||||||
while (new_sh_offset > sh_offset)
|
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,
|
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
||||||
sh_name, SHT_PROGBITS, 0, sh_offset,
|
sh_name, sh_type, sh_flags,
|
||||||
sh_size, 0, 1U << section->align,
|
sh_addr, sh_offset,
|
||||||
|
sh_size, sh_link, sh_info,
|
||||||
|
sh_addralign, sh_entsize,
|
||||||
&errmsg, err))
|
&errmsg, err))
|
||||||
return errmsg;
|
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,
|
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
||||||
sh_name, SHT_STRTAB, 0, sh_offset,
|
sh_name, SHT_STRTAB, 0, 0, sh_offset,
|
||||||
sh_name + strlen (".shstrtab") + 1, 0,
|
sh_name + strlen (".shstrtab") + 1, 0, 0,
|
||||||
1, &errmsg, err))
|
1, 0, &errmsg, err))
|
||||||
return errmsg;
|
return errmsg;
|
||||||
|
|
||||||
/* .shstrtab has a leading zero byte. */
|
/* .shstrtab has a leading zero byte. */
|
||||||
|
@ -954,9 +1061,356 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
|
||||||
static void
|
static void
|
||||||
simple_object_elf_release_write (void *data)
|
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);
|
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. */
|
/* The ELF functions. */
|
||||||
|
|
||||||
const struct simple_object_functions simple_object_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_release_attributes,
|
||||||
simple_object_elf_start_write,
|
simple_object_elf_start_write,
|
||||||
simple_object_elf_write_to_file,
|
simple_object_elf_write_to_file,
|
||||||
simple_object_elf_release_write
|
simple_object_elf_release_write,
|
||||||
|
simple_object_elf_copy_lto_debug_sections
|
||||||
};
|
};
|
||||||
|
|
|
@ -1374,5 +1374,6 @@ const struct simple_object_functions simple_object_mach_o_functions =
|
||||||
simple_object_mach_o_release_attributes,
|
simple_object_mach_o_release_attributes,
|
||||||
simple_object_mach_o_start_write,
|
simple_object_mach_o_start_write,
|
||||||
simple_object_mach_o_write_to_file,
|
simple_object_mach_o_write_to_file,
|
||||||
simple_object_mach_o_release_write
|
simple_object_mach_o_release_write,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -138,7 +138,7 @@ struct external_syment
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
union {
|
union {
|
||||||
/* The name of the symbol. There is an implicit null character
|
/* The name of the symbol. There is an implicit null character
|
||||||
after the end of the array. */
|
after the end of the array. */
|
||||||
char n_name[N_SYMNMLEN];
|
char n_name[N_SYMNMLEN];
|
||||||
struct {
|
struct {
|
||||||
|
@ -255,8 +255,14 @@ union external_auxent
|
||||||
#define IMAGE_SYM_TYPE \
|
#define IMAGE_SYM_TYPE \
|
||||||
((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
|
((IMAGE_SYM_DTYPE_NULL << 4) | IMAGE_SYM_TYPE_NULL)
|
||||||
|
|
||||||
|
#define C_EXT (2)
|
||||||
#define C_STAT (3)
|
#define C_STAT (3)
|
||||||
#define C_FILE (103)
|
#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. */
|
/* Private data for an simple_object_read. */
|
||||||
|
|
||||||
|
@ -398,11 +404,13 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
|
||||||
size_t scnhdr_size;
|
size_t scnhdr_size;
|
||||||
unsigned char *scnbuf;
|
unsigned char *scnbuf;
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
|
unsigned short (*fetch_16) (const unsigned char *);
|
||||||
unsigned int (*fetch_32) (const unsigned char *);
|
unsigned int (*fetch_32) (const unsigned char *);
|
||||||
ulong_type (*fetch_64) (const unsigned char *);
|
ulong_type (*fetch_64) (const unsigned char *);
|
||||||
unsigned int nscns;
|
unsigned int nscns;
|
||||||
char *strtab;
|
char *strtab;
|
||||||
size_t strtab_size;
|
size_t strtab_size;
|
||||||
|
struct external_syment *symtab = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
|
scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32;
|
||||||
|
@ -416,6 +424,7 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetch_16 = simple_object_fetch_big_16;
|
||||||
fetch_32 = simple_object_fetch_big_32;
|
fetch_32 = simple_object_fetch_big_32;
|
||||||
fetch_64 = simple_object_fetch_big_64;
|
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 namebuf[SCNNMLEN + 1];
|
||||||
char *name;
|
char *name;
|
||||||
off_t scnptr;
|
off_t scnptr;
|
||||||
unsigned int size;
|
off_t size;
|
||||||
|
|
||||||
scnhdr = scnbuf + i * scnhdr_size;
|
scnhdr = scnbuf + i * scnhdr_size;
|
||||||
scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
|
scnname = scnhdr + offsetof (struct external_scnhdr, s_name);
|
||||||
|
@ -489,6 +498,151 @@ simple_object_xcoff_find_sections (simple_object_read *sobj,
|
||||||
break;
|
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)
|
if (strtab != NULL)
|
||||||
XDELETEVEC (strtab);
|
XDELETEVEC (strtab);
|
||||||
XDELETEVEC (scnbuf);
|
XDELETEVEC (scnbuf);
|
||||||
|
@ -894,5 +1048,6 @@ const struct simple_object_functions simple_object_xcoff_functions =
|
||||||
simple_object_xcoff_release_attributes,
|
simple_object_xcoff_release_attributes,
|
||||||
simple_object_xcoff_start_write,
|
simple_object_xcoff_start_write,
|
||||||
simple_object_xcoff_write_to_file,
|
simple_object_xcoff_write_to_file,
|
||||||
simple_object_xcoff_release_write
|
simple_object_xcoff_release_write,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA. */
|
||||||
#include "simple-object.h"
|
#include "simple-object.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef HAVE_STDLIB_H
|
#ifdef HAVE_STDLIB_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -249,6 +250,86 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
|
||||||
return 1;
|
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. */
|
/* Fetch attributes. */
|
||||||
|
|
||||||
simple_object_attributes *
|
simple_object_attributes *
|
||||||
|
@ -315,7 +396,7 @@ simple_object_start_write (simple_object_attributes *attrs,
|
||||||
return NULL;
|
return NULL;
|
||||||
ret = XNEW (simple_object_write);
|
ret = XNEW (simple_object_write);
|
||||||
ret->functions = attrs->functions;
|
ret->functions = attrs->functions;
|
||||||
ret->segment_name = xstrdup (segment_name);
|
ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
|
||||||
ret->sections = NULL;
|
ret->sections = NULL;
|
||||||
ret->last_section = NULL;
|
ret->last_section = NULL;
|
||||||
ret->data = data;
|
ret->data = data;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue