From c1d2490437926047d030a011a8839c3ee613391b Mon Sep 17 00:00:00 2001 From: Tony Reix Date: Wed, 7 Jun 2017 23:23:55 +0000 Subject: [PATCH] simple-object-xcoff.c (simple_object_xcoff_find_sections): Search symbol table for .go_export symbol and apply pfn if found. 2017-06-07 Tony Reix Matthieu Sarter David Edelsohn * simple-object-xcoff.c (simple_object_xcoff_find_sections): Search symbol table for .go_export symbol and apply pfn if found. Co-Authored-By: David Edelsohn Co-Authored-By: Matthieu Sarter From-SVN: r248999 --- libiberty/ChangeLog | 7 ++ libiberty/simple-object-xcoff.c | 130 +++++++++++++++++++++++++++++--- 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 0bc64a5d1de..6e9ff713de1 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2017-06-07 Tony Reix + Matthieu Sarter + David Edelsohn + + * 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 * configure.ac (strnlen): Add to AC_CHECK_DECLS. diff --git a/libiberty/simple-object-xcoff.c b/libiberty/simple-object-xcoff.c index 8a159398787..7be1bf33fe3 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. */ @@ -258,6 +258,8 @@ union external_auxent #define C_STAT (3) #define C_FILE (103) +#define DBXMASK 0x80 + /* Private data for an simple_object_read. */ struct simple_object_xcoff_read @@ -403,7 +405,9 @@ simple_object_xcoff_find_sections (simple_object_read *sobj, unsigned int nscns; char *strtab; size_t strtab_size; + struct external_syment *symtab = NULL; unsigned int i; + off_t textptr = 0; scnhdr_size = u64 ? SCNHSZ64 : SCNHSZ32; scnbuf = XNEWVEC (unsigned char, scnhdr_size * ocr->nscns); @@ -485,10 +489,118 @@ simple_object_xcoff_find_sections (simple_object_read *sobj, u.xcoff32.s_size)); } + if (strcmp (name, ".text") == 0) + textptr = scnptr; if (!(*pfn) (data, name, scnptr, size)) break; } + /* Special handling for .go_export CSECT. */ + if (textptr != 0 && ocr->nsyms > 0) + { + unsigned char *sym, *aux; + const char *n_name; + unsigned long n_value, n_offset, n_zeroes, x_scnlen; + + /* 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) + { + sym = (unsigned char *)&symtab[i]; + + if (symtab[i].n_sclass[0] & DBXMASK) + { + /* Skip debug symbols whose names are in stabs. */ + i += symtab[i].n_numaux[0]; + 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) + { + /* Skip auxiliary entries. */ + i += symtab[i].n_numaux[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 section 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 "section string index out of range"; + } + n_name = strtab + n_offset; + + if (!strcmp(n_name, ".go_export")) + { + /* Found .go_export symbol, read auxiliary entry. */ + if (i + 1 >= ocr->nsyms) + break; + + aux = (unsigned char *)&symtab[i + 1]; + if (u64) + { + x_scnlen = fetch_32 (aux + offsetof (union external_auxent, + u.xcoff64.x_csect.x_scnlen_lo)); + } + else + { + x_scnlen = fetch_32 (aux + offsetof (union external_auxent, + u.xcoff32.x_csect.x_scnlen)); + } + (*pfn) (data, ".go_export", textptr + n_value, x_scnlen); + break; + } + /* Skip auxiliary entries. */ + i += symtab[i].n_numaux[0]; + } + } + + if (symtab != NULL) + XDELETEVEC (symtab); if (strtab != NULL) XDELETEVEC (strtab); XDELETEVEC (scnbuf);