diff options
author | Nick Clifton <nickc@redhat.com> | 2017-09-01 10:52:53 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2017-09-01 10:52:53 +0100 |
commit | f8ad2513754f5a53fecb407cf64fcb586836b60c (patch) | |
tree | 3c36dbde3a7db99d9a05fafd5d1de1b93184b0c0 /libiberty/simple-object-xcoff.c | |
parent | 2a143b99fc4a5094a9cf128f3184d8e6818c8229 (diff) | |
download | binutils-gdb-f8ad2513754f5a53fecb407cf64fcb586836b60c.tar.gz |
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.
Diffstat (limited to 'libiberty/simple-object-xcoff.c')
-rw-r--r-- | libiberty/simple-object-xcoff.c | 177 |
1 files changed, 166 insertions, 11 deletions
diff --git a/libiberty/simple-object-xcoff.c b/libiberty/simple-object-xcoff.c index 8a159398787..9a8f581563f 100644 --- a/libiberty/simple-object-xcoff.c +++ b/libiberty/simple-object-xcoff.c @@ -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 }; |