re PR lto/81968 (early lto debug objects make Solaris ld SEGV)
authorRichard Biener <rguenther@suse.de>
Thu, 11 Jan 2018 12:12:39 +0000 (12:12 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 11 Jan 2018 12:12:39 +0000 (12:12 +0000)
2018-01-11  Richard Biener  <rguenther@suse.de>
Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

PR lto/81968
libiberty/
* simple-object-common.h (struct simple_object_functions):
Change copy_lto_debug_sections callback signature.
* simple-object-elf.c (SHN_HIRESERVE, SHT_SYMTAB_SHNDX,
SHF_INFO_LINK): Add defines.
(simple_object_elf_copy_lto_debug_sections): Instead of
leaving not to be copied sections empty unnamed SHT_NULL
remove them from the target section headers and adjust section
reference everywhere.  Handle SHN_XINDEX in the symbol table
processing properly.
* simple-object.c (handle_lto_debug_sections): Change
interface to return a modified string and handle renaming
of relocation sections.

Co-Authored-By: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
From-SVN: r256528

libiberty/ChangeLog
libiberty/simple-object-common.h
libiberty/simple-object-elf.c
libiberty/simple-object.c

index 817ebc644ea68f458565f821c5b6b78f5e9b71eb..2b834372c9a74a3f2fd61bce9f6159a8bce6accf 100644 (file)
@@ -1,3 +1,20 @@
+2018-01-11  Richard Biener  <rguenther@suse.de>
+       Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+
+       PR lto/81968
+       * simple-object-common.h (struct simple_object_functions):
+       Change copy_lto_debug_sections callback signature.
+       * simple-object-elf.c (SHN_HIRESERVE, SHT_SYMTAB_SHNDX,
+       SHF_INFO_LINK): Add defines.
+       (simple_object_elf_copy_lto_debug_sections): Instead of
+       leaving not to be copied sections empty unnamed SHT_NULL
+       remove them from the target section headers and adjust section
+       reference everywhere.  Handle SHN_XINDEX in the symbol table
+       processing properly.
+       * simple-object.c (handle_lto_debug_sections): Change
+       interface to return a modified string and handle renaming
+       of relocation sections.
+
 2018-01-10  Daniel van Gerpen  <daniel@vangerpen.de>
 
        * argv.c (expandargv): Correct check for dynamically
index 53501df8fd95c02942601f4d4a54952dffab199b..858209f9b059156c2d806538e5715c7b9b7b2635 100644 (file)
@@ -145,7 +145,7 @@ struct simple_object_functions
   /* Copy LTO debug sections.  */
   const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
                                          simple_object_write *dobj,
-                                         int (*pfn) (const char **),
+                                         char *(*pfn) (const char *),
                                          int *err);
 };
 
index b249146fc6003912d8cf702eb3765ba9199dc85d..7468a1adc3dd1da2584d7324d98b9314a18f91ce 100644 (file)
@@ -126,6 +126,7 @@ typedef struct {
 #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_HIRESERVE  0xffff          /* End of reserved indices */
 
 
 /* 32-bit ELF program header.  */
@@ -193,9 +194,11 @@ typedef struct {
 #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 */
+#define SHT_SYMTAB_SHNDX 18            /* Extended section indeces */
 
 /* Values for sh_flags field.  */
 
+#define SHF_INFO_LINK  0x00000040      /* `sh_info' contains SHT index */
 #define SHF_EXECINSTR  0x00000004      /* Executable section.  */
 #define SHF_EXCLUDE    0x80000000      /* Link editor is to exclude this
                                           section from executable and
@@ -1070,7 +1073,7 @@ simple_object_elf_release_write (void *data)
 static const char *
 simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                                           simple_object_write *dobj,
-                                          int (*pfn) (const char **),
+                                          char *(*pfn) (const char *),
                                           int *err)
 {
   struct simple_object_elf_read *eor =
@@ -1091,7 +1094,10 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
   int changed;
   int *pfnret;
   const char **pfnname;
+  unsigned new_i;
+  unsigned *sh_map;
   unsigned first_shndx = 0;
+  unsigned int *symtab_indices_shndx;
 
   shdr_size = (ei_class == ELFCLASS32
               ? sizeof (Elf32_External_Shdr)
@@ -1130,18 +1136,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       return errmsg;
     }
 
-  eow->shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
   pfnret = XNEWVEC (int, shnum);
   pfnname = XNEWVEC (const char *, shnum);
 
+  /* Map of symtab to index section.  */
+  symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
+
   /* 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;
+      unsigned int sh_name, sh_type;
       const char *name;
-      int ret;
+      char *ret;
 
       shdr = shdrs + (i - 1) * shdr_size;
       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
@@ -1156,12 +1164,28 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 
       name = (const char *) names + sh_name;
 
-      ret = (*pfn) (&name);
-      pfnret[i - 1] = ret == 1 ? 0 : -1;
-      pfnname[i - 1] = name;
+      ret = (*pfn) (name);
+      pfnret[i - 1] = ret == NULL ? -1 : 0;
+      pfnname[i - 1] = ret == NULL ? name : ret;
       if (first_shndx == 0
          && pfnret[i - 1] == 0)
        first_shndx = i;
+
+      /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections.  */
+      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                shdr, sh_type, Elf_Word);
+      if (sh_type == SHT_SYMTAB_SHNDX)
+       {
+         unsigned int sh_link;
+         sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                    shdr, sh_link, Elf_Word);
+         symtab_indices_shndx[sh_link - 1] = i;
+         /* Always discard the extended index sections, after
+            copying it will not be needed.  This way we don't need to
+            update it and deal with the ordering constraints of
+            processing the existing symtab and changing the index.  */
+         pfnret[i - 1] = -1;
+       }
     }
 
   /* Mark sections as preserved that are required by to be preserved
@@ -1244,7 +1268,26 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
     }
   while (changed);
 
+  /* Compute a mapping of old -> new section numbers.  */
+  sh_map = XNEWVEC (unsigned, shnum);
+  sh_map[0] = 0;
+  new_i = 1;
+  for (i = 1; i < shnum; ++i)
+    {
+      if (pfnret[i - 1] == -1)
+       sh_map[i] = 0;
+      else
+       sh_map[i] = new_i++;
+    }
+  if (new_i - 1 >= SHN_LORESERVE)
+    {
+      *err = ENOTSUP;
+      return "Too many copied sections";
+    }
+  eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
+
   /* Then perform the actual copying.  */
+  new_i = 0;
   for (i = 1; i < shnum; ++i)
     {
       unsigned char *shdr;
@@ -1252,11 +1295,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       const char *name;
       off_t offset;
       off_t length;
-      int ret;
       simple_object_write_section *dest;
       off_t flags;
       unsigned char *buf;
 
+      if (pfnret[i - 1])
+       continue;
+
+      new_i++;
       shdr = shdrs + (i - 1) * shdr_size;
       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                 shdr, sh_name, Elf_Word);
@@ -1265,10 +1311,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
          *err = 0;
          XDELETEVEC (names);
          XDELETEVEC (shdrs);
+         XDELETEVEC (symtab_indices_shndx);
          return "ELF section name out of range";
        }
 
-      name = (const char *) names + sh_name;
+      name = pfnname[i - 1];
       offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                shdr, sh_offset, Elf_Addr);
       length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
@@ -1276,178 +1323,223 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       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);
+      dest = simple_object_write_create_section (dobj, pfnname[i - 1],
+                                                0, &errmsg, err);
       if (dest == NULL)
        {
          XDELETEVEC (names);
          XDELETEVEC (shdrs);
+         XDELETEVEC (symtab_indices_shndx);
          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;
+      memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
+      shdr = eow->shdrs + (new_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
+      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);
+         XDELETEVEC (symtab_indices_shndx);
+         return errmsg;
+       }
+
+      /* If we are processing .symtab purge __gnu_lto_v1 and
+        __gnu_lto_slim symbols from it and any symbols in discarded
         sections.  */
-      if (ret == 0)
+      if (sh_type == SHT_SYMTAB)
        {
-         buf = XNEWVEC (unsigned char, length);
-         if (!simple_object_internal_read (sobj->descriptor,
-                                           sobj->offset + offset, buf,
-                                           (size_t) length, &errmsg, err))
+         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);
+         char *gnu_lto = strings;
+         unsigned char *ent;
+         unsigned *shndx_table = NULL;
+         simple_object_internal_read (sobj->descriptor,
+                                      sobj->offset + stroff,
+                                      (unsigned char *)strings,
+                                      strsz, &errmsg, err);
+         /* Find gnu_lto_ in strings.  */
+         while ((gnu_lto = (char *) memchr (gnu_lto, 'g',
+                                            strings + strsz - gnu_lto)))
+           if (strncmp (gnu_lto, "gnu_lto_v1",
+                        strings + strsz - gnu_lto) == 0)
+             break;
+           else
+             gnu_lto++;
+         /* Read the section index table if present.  */
+         if (symtab_indices_shndx[i - 1] != 0)
            {
-             XDELETEVEC (buf);
-             XDELETEVEC (names);
-             XDELETEVEC (shdrs);
-             return errmsg;
+             unsigned char *sidxhdr = shdrs + (strtab - 1) * shdr_size;
+             off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                              sidxhdr, sh_offset, Elf_Addr);
+             size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                              sidxhdr, sh_size, Elf_Addr);
+             shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
+             simple_object_internal_read (sobj->descriptor,
+                                          sobj->offset + sidxoff,
+                                          (unsigned char *)shndx_table,
+                                          sidxsz, &errmsg, err);
            }
-
-         /* If we are processing .symtab purge __gnu_lto_v1 and
-            __gnu_lto_slim symbols from it.  */
-         if (sh_type == SHT_SYMTAB)
+         for (ent = buf; ent < buf + length; ent += entsize)
            {
-             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);
-             /* Find gnu_lto_ in strings.  */
-             char *gnu_lto = strings;
-             while ((gnu_lto = memchr (gnu_lto, 'g',
-                                       strings + strsz - gnu_lto)))
-               if (strncmp (gnu_lto, "gnu_lto_v1",
-                            strings + strsz - gnu_lto) == 0)
-                 break;
-               else
-                 gnu_lto++;
-             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 raw_st_shndx = st_shndx;
+             unsigned char *st_info;
+             unsigned char *st_other;
+             int discard = 0;
+             if (ei_class == ELFCLASS32)
                {
-                 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;
+               }
+             if (st_shndx == SHN_XINDEX)
+               st_shndx = type_functions->fetch_Elf_Word
+                   ((unsigned char *)(shndx_table + (ent - buf) / entsize));
+             /* Eliminate all COMMONs - this includes __gnu_lto_v1
+                and __gnu_lto_slim which otherwise cause endless
+                LTO plugin invocation.  */
+             if (st_shndx == SHN_COMMON)
+               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.  */
+                 int bind = ELF_ST_BIND (*st_info);
+                 int other = STV_DEFAULT;
+                 if (bind == STB_LOCAL)
                    {
-                     st_info = &((Elf32_External_Sym *)ent)->st_info;
-                     st_other = &((Elf32_External_Sym *)ent)->st_other;
+                     /* Make discarded local symbols unnamed and
+                        defined in the first prevailing section.  */
+                     ELF_SET_FIELD (type_functions, ei_class, Sym,
+                                    ent, st_name, Elf_Word, 0);
+                     ELF_SET_FIELD (type_functions, ei_class, Sym,
+                                    ent, st_shndx, Elf_Half,
+                                    sh_map[first_shndx]);
                    }
                  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)
-                   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.  */
-                     int bind = ELF_ST_BIND (*st_info);
-                     int other = STV_DEFAULT;
-                     if (bind == STB_LOCAL)
-                       {
-                         /* Make discarded local symbols unnamed and
-                            defined in the first prevailing section.  */
-                         ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                        ent, st_name, Elf_Word, 0);
-                         ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                        ent, st_shndx, Elf_Half, first_shndx);
-                       }
-                     else
-                       {
-                         /* Make discarded global symbols hidden weak
-                            undefined and sharing the gnu_lto_ name.  */
-                         bind = STB_WEAK;
-                         other = STV_HIDDEN;
-                         if (gnu_lto)
-                           ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                          ent, st_name, Elf_Word,
-                                          gnu_lto - strings);
-                         ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                        ent, st_shndx, Elf_Half, SHN_UNDEF);
-                       }
-                     *st_other = other;
-                     *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
-                     ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                    ent, st_value, Elf_Addr, 0);
+                     /* Make discarded global symbols hidden weak
+                        undefined and sharing the gnu_lto_ name.  */
+                     bind = STB_WEAK;
+                     other = STV_HIDDEN;
+                     if (gnu_lto)
+                       ELF_SET_FIELD (type_functions, ei_class, Sym,
+                                      ent, st_name, Elf_Word,
+                                      gnu_lto - strings);
                      ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                    ent, st_size, Elf_Word, 0);
+                                    ent, st_shndx, Elf_Half, SHN_UNDEF);
                    }
+                 *st_other = other;
+                 *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
+                 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);
                }
-             XDELETEVEC (strings);
+             else if (raw_st_shndx < SHN_LORESERVE
+                      || raw_st_shndx == SHN_XINDEX)
+               /* Remap the section reference.  */
+               ELF_SET_FIELD (type_functions, ei_class, Sym,
+                              ent, st_shndx, Elf_Half, sh_map[st_shndx]);
            }
-
-         errmsg = simple_object_write_add_data (dobj, dest,
-                                                buf, length, 1, err);
-         XDELETEVEC (buf);
-         if (errmsg)
+         XDELETEVEC (strings);
+         XDELETEVEC (shndx_table);
+       }
+      else if (sh_type == SHT_GROUP)
+       {
+         /* Remap section indices in groups and remove removed members.  */
+         unsigned char *ent, *dst;
+         for (dst = ent = buf + 4; ent < buf + length; ent += 4)
            {
-             XDELETEVEC (names);
-             XDELETEVEC (shdrs);
-             return errmsg;
+             unsigned shndx = type_functions->fetch_Elf_Word (ent);
+             if (pfnret[shndx - 1] == -1)
+               ;
+             else
+               {
+                 type_functions->set_Elf_Word (dst, sh_map[shndx]);
+                 dst += 4;
+               }
            }
+         /* Adjust the length.  */
+         length = dst - buf;
        }
-      else
+
+      errmsg = simple_object_write_add_data (dobj, dest,
+                                            buf, length, 1, err);
+      XDELETEVEC (buf);
+      if (errmsg)
        {
-         /* 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);
-         ELF_SET_FIELD (type_functions, ei_class, Shdr,
-                        shdr, sh_info, Elf_Word, 0);
-         ELF_SET_FIELD (type_functions, ei_class, Shdr,
-                        shdr, sh_link, Elf_Word, 0);
+         XDELETEVEC (names);
+         XDELETEVEC (shdrs);
+         XDELETEVEC (symtab_indices_shndx);
+         return errmsg;
        }
 
       flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                               shdr, sh_flags, Elf_Addr);
-      if (ret == 0)
-       {
-         /* The debugobj doesn't contain any code, thus no trampolines.
-            Even when the original object needs trampolines, debugobj
-            doesn't.  */
-         if (strcmp (name, ".note.GNU-stack") == 0)
-           flags &= ~SHF_EXECINSTR;
-         flags &= ~SHF_EXCLUDE;
-       }
-      else if (ret == -1)
-       flags = SHF_EXCLUDE;
+      /* Remap the section references.  */
+      {
+       unsigned int sh_info, sh_link;
+       if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
+         {
+           sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                      shdr, sh_info, Elf_Word);
+           if (sh_info < SHN_LORESERVE
+               || sh_info > SHN_HIRESERVE)
+             sh_info = sh_map[sh_info];
+           ELF_SET_FIELD (type_functions, ei_class, Shdr,
+                          shdr, sh_info, Elf_Word, sh_info);
+         }
+       sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                  shdr, sh_link, Elf_Word);
+       if (sh_link < SHN_LORESERVE
+           || sh_link > SHN_HIRESERVE)
+         sh_link = sh_map[sh_link];
+       ELF_SET_FIELD (type_functions, ei_class, Shdr,
+                      shdr, sh_link, Elf_Word, sh_link);
+      }
+      /* The debugobj doesn't contain any code, thus no trampolines.
+        Even when the original object needs trampolines, debugobj
+        doesn't.  */
+      if (strcmp (name, ".note.GNU-stack") == 0)
+       flags &= ~SHF_EXECINSTR;
+      /* Clear SHF_EXCLUDE on to be preserved sections.  */
+      flags &= ~SHF_EXCLUDE;
       ELF_SET_FIELD (type_functions, ei_class, Shdr,
                     shdr, sh_flags, Elf_Addr, flags);
     }
@@ -1456,6 +1548,8 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
   XDELETEVEC (shdrs);
   XDELETEVEC (pfnret);
   XDELETEVEC (pfnname);
+  XDELETEVEC (symtab_indices_shndx);
+  XDELETEVEC (sh_map);
 
   return NULL;
 }
index 5b95fb2d56daf6c5cabcf1bdfde4228c273d069c..56dc9566167f46546006b72200f84f9ef02b6aca 100644 (file)
@@ -253,30 +253,38 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
 /* 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)
+static char *
+handle_lto_debug_sections (const char *name)
 {
+  char *newname = XCNEWVEC (char, strlen (name) + 1);
+
   /* ???  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)
+  /* Also include corresponding reloc sections.  */
+  if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
     {
-      *name = *name + sizeof (".gnu.debuglto_") - 1;
-      return 1;
+      strncpy (newname, name, sizeof (".rela") - 1);
+      name += sizeof (".rela") - 1;
     }
-  else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
+  else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
     {
-      *name = *name + sizeof (".gnu.lto_") - 1;
-      return 1;
+      strncpy (newname, name, sizeof (".rel") - 1);
+      name += sizeof (".rel") - 1;
     }
+  /* ???  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)
+    return strcat (newname, name + sizeof (".gnu.debuglto_") - 1);
+  else if (strncmp (name, ".gnu.lto_.debug_",
+                   sizeof (".gnu.lto_.debug_") -1) == 0)
+    return strcat (newname, name + sizeof (".gnu.lto_") - 1);
   /* Copy over .note.GNU-stack section under the same name if present.  */
-  else if (strcmp (*name, ".note.GNU-stack") == 0)
-    return 1;
-  return 0;
+  else if (strcmp (name, ".note.GNU-stack") == 0)
+    return strcpy (newname, name);
+  return NULL;
 }
 
 /* Copy LTO debug sections.  */