summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Reix <tony.reix@atos.net>2017-06-07 23:23:55 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>2017-06-07 19:23:55 -0400
commitc1d2490437926047d030a011a8839c3ee613391b (patch)
treebbc528826e3402c9e25a0f45e8bcc12a825e8f5f
parent989cc652ee02ab598a01ccbeec55ca8e2b7df72d (diff)
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 <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. Co-Authored-By: David Edelsohn <dje.gcc@gmail.com> Co-Authored-By: Matthieu Sarter <matthieu.sarter.external@atos.net> From-SVN: r248999
-rw-r--r--libiberty/ChangeLog7
-rw-r--r--libiberty/simple-object-xcoff.c130
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 <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.
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);