Description:
 * This patch enables libiberty to read AIX XCOFF.

Tests:
 * Fedora25/x86_64 + GCC v7.1.0 : Configure/Build: SUCCESS
   - build made by means of a .spec file based on Fedora gcc-7.0.1-0.12 .spec 
file
     ../configure --enable-bootstrap 
--enable-languages=c,c++,objc,obj-c++,fortran,go,lto --prefix=/usr 
--mandir=/usr/share/man --infodir=/usr/share/info 
--with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared 
--enable-threads=posix --enable-checking=release
 --enable-multilib --with-system-zlib --enable-__cxa_atexit 
--disable-libunwind-exceptions --enable-gnu-unique-object 
--enable-linker-build-id --with-gcc-major-version-only 
--with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl 
--enable-libmpx
 --enable-offload-targets=nvptx-none --without-cuda-driver 
--enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 
--build=x86_64-redhat-linux

ChangeLog:
  * libiberty/simple-object-xcoff.c: Enable libiberty to read AIX XCOFF


Regards,

Tony Reix
Bull - ATOS
IBM Coop Architect & Technical Leader
Office : +33 (0) 4 76 29 72 67
1 rue de Provence - 38432 Échirolles - France
www.atos.net
--- ./libiberty/simple-object-xcoff.c.ORIGIN    2017-03-21 17:08:59 -0500
+++ ./libiberty/simple-object-xcoff.c   2017-03-21 16:45:43 -0500
@@ -258,6 +258,8 @@
 #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 @@
   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,116 @@
                                              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);

Reply via email to