gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libiberty / simple-object-elf.c
index 9799e725465e7dacbf953d37d8c6530b9c30e6d7..c62d5bba551c099e9f33c3a0b33dd4612952411c 100644 (file)
@@ -1,5 +1,5 @@
 /* simple-object-elf.c -- routines to manipulate ELF object files.
-   Copyright (C) 2010-2017 Free Software Foundation, Inc.
+   Copyright (C) 2010-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 This program is free software; you can redistribute it and/or modify it
@@ -22,6 +22,10 @@ Boston, MA 02110-1301, USA.  */
 #include "simple-object.h"
 
 #include <errno.h>
+/* mingw.org's MinGW doesn't have ENOTSUP.  */
+#ifndef ENOTSUP
+# define ENOTSUP ENOSYS
+#endif
 #include <stddef.h>
 
 #ifdef HAVE_STDLIB_H
@@ -126,6 +130,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 +198,12 @@ 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
                                           shared library that it builds
@@ -235,8 +243,10 @@ typedef struct
 
 #define STB_LOCAL      0       /* Local symbol */
 #define STB_GLOBAL     1       /* Global symbol */
+#define STB_WEAK       2       /* Weak global */
 
 #define STV_DEFAULT    0       /* Visibility is specified by binding type */
+#define STV_HIDDEN     2       /* Can only be seen inside currect component */
 
 /* Functions to fetch and store different ELF types, depending on the
    endianness and size.  */
@@ -538,7 +548,15 @@ simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
       XDELETE (eor);
       return NULL;
     }
-
+  
+  if (eor->shstrndx == 0)
+    {
+      *errmsg = "invalid ELF shstrndx == 0";
+      *err = 0;
+      XDELETE (eor);
+      return NULL;
+    }
+  
   return (void *) eor;
 }
 
@@ -587,11 +605,6 @@ simple_object_elf_find_sections (simple_object_read *sobj,
 
   /* Read the section names.  */
 
-  if (eor->shstrndx == 0)
-    {
-      XDELETEVEC (shdrs);
-      return "ELF section header string table missing";
-    }
   shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
   name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                               shstrhdr, sh_size, Elf_Addr);
@@ -1072,7 +1085,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 =
@@ -1090,8 +1103,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
   off_t shstroff;
   unsigned char *names;
   unsigned int i;
+  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 +1148,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,79 +1176,130 @@ 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
      sections.  */
-  for (i = 1; i < shnum; ++i)
+  do
     {
-      unsigned char *shdr;
-      unsigned int sh_type, sh_info, sh_link;
-      off_t offset;
-      off_t length;
-
-      shdr = shdrs + (i - 1) * shdr_size;
-      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                shdr, sh_type, Elf_Word);
-      sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                shdr, sh_info, Elf_Word);
-      sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                shdr, sh_link, Elf_Word);
-      if (sh_type == SHT_GROUP)
+      changed = 0;
+      for (i = 1; i < shnum; ++i)
        {
-         /* Mark groups containing copied sections.  */
-         unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                             shdr, sh_entsize, Elf_Addr);
-         unsigned char *ent, *buf;
-         int keep = 0;
-         offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                   shdr, sh_offset, Elf_Addr);
-         length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                   shdr, sh_size, Elf_Addr);
-         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);
-             return errmsg;
-           }
-         for (ent = buf + entsize; ent < buf + length; ent += entsize)
+         unsigned char *shdr;
+         unsigned int sh_type, sh_info, sh_link;
+         off_t offset;
+         off_t length;
+
+         shdr = shdrs + (i - 1) * shdr_size;
+         sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                    shdr, sh_type, Elf_Word);
+         sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                    shdr, sh_info, Elf_Word);
+         sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                    shdr, sh_link, Elf_Word);
+         if (sh_type == SHT_GROUP)
            {
-             unsigned sec = type_functions->fetch_Elf_Word (ent);
-             if (pfnret[sec - 1] == 0)
-               keep = 1;
+             /* Mark groups containing copied sections.  */
+             unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class,
+                                                 Shdr, shdr, sh_entsize,
+                                                 Elf_Addr);
+             unsigned char *ent, *buf;
+             int keep = 0;
+             offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                       shdr, sh_offset, Elf_Addr);
+             length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                       shdr, sh_size, Elf_Addr);
+             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);
+                 return errmsg;
+               }
+             for (ent = buf + entsize; ent < buf + length; ent += entsize)
+               {
+                 unsigned sec = type_functions->fetch_Elf_Word (ent);
+                 if (pfnret[sec - 1] == 0)
+                   keep = 1;
+               }
+             if (keep)
+               {
+                 changed |= (pfnret[sh_link - 1] == -1
+                             || pfnret[i - 1] == -1);
+                 pfnret[sh_link - 1] = 0;
+                 pfnret[i - 1] = 0;
+               }
            }
-         if (keep)
+         if (sh_type == SHT_RELA
+             || sh_type == SHT_REL)
            {
-             pfnret[sh_link - 1] = 0;
-             pfnret[i - 1] = 0;
+             /* Mark relocation sections and symtab of copied sections.  */
+             if (pfnret[sh_info - 1] == 0)
+               {
+                 changed |= (pfnret[sh_link - 1] == -1
+                             || pfnret[i - 1] == -1);
+                 pfnret[sh_link - 1] = 0;
+                 pfnret[i - 1] = 0;
+               }
            }
-       }
-      if (sh_type == SHT_RELA
-         || sh_type == SHT_REL)
-       {
-         /* Mark relocation sections and symtab of copied sections.  */
-         if (pfnret[sh_info - 1] == 0)
+         if (sh_type == SHT_SYMTAB)
            {
-             pfnret[sh_link - 1] = 0;
-             pfnret[i - 1] = 0;
+             /* Mark strings sections of copied symtabs.  */
+             if (pfnret[i - 1] == 0)
+               {
+                 changed |= pfnret[sh_link - 1] == -1;
+                 pfnret[sh_link - 1] = 0;
+               }
            }
        }
-      if (sh_type == SHT_SYMTAB)
-       {
-         /* Mark strings sections of copied symtabs.  */
-         if (pfnret[i - 1] == 0)
-           pfnret[sh_link - 1] = 0;
-       }
     }
+  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;
@@ -1236,12 +1307,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       const char *name;
       off_t offset;
       off_t length;
-      int ret;
-      const char *errmsg;
       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);
@@ -1250,10 +1323,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,
@@ -1261,143 +1335,243 @@ 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
-        sections.  */
-      if (ret == 0)
+      buf = XNEWVEC (unsigned char, length);
+      if (!simple_object_internal_read (sobj->descriptor,
+                                       sobj->offset + offset, buf,
+                                       (size_t) length, &errmsg, err))
        {
-         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 any symbols
+        in discarded sections.  */
+      if (sh_type == SHT_SYMTAB)
+       {
+         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);
+         size_t prevailing_name_idx = 0;
+         unsigned char *ent;
+         unsigned *shndx_table = NULL;
+         /* 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)
+         /* Find a WEAK HIDDEN symbol which name we will use for removed
+            symbols.  We know there's a prevailing weak hidden symbol
+            at the start of the .debug_info section.  */
+         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);
-             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 char *st_info;
+             unsigned char *st_other;
+             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));
+
+             if (st_shndx != SHN_COMMON
+                 && !(st_shndx != SHN_UNDEF
+                      && st_shndx < shnum
+                      && pfnret[st_shndx - 1] == -1)
+                 && ELF_ST_BIND (*st_info) == STB_WEAK
+                 && *st_other == STV_HIDDEN)
                {
-                 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)
+                 prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
+                                                        ei_class, Sym, ent,
+                                                        st_name, Elf_Word);
+                 break;
+               }
+           }
+
+         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)
+               {
+                 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_slim
+                which otherwise cause endless LTO plugin invocation.
+                FIXME: remove the condition once we remove emission
+                of __gnu_lto_slim symbol.  */
+             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)
-                   /* Setting st_name to "" seems to work to purge
-                      COMMON symbols (in addition to setting their
-                      size to zero).  */
-                   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.  */
-                     if (ELF_ST_BIND (*st_info) == STB_LOCAL)
-                       ELF_SET_FIELD (type_functions, ei_class, Sym,
-                                      ent, st_name, Elf_Word, 0);
+                     /* Make discarded global symbols hidden weak
+                        undefined and sharing a name of a prevailing
+                        symbol.  */
+                     bind = STB_WEAK;
+                     other = STV_HIDDEN;
                      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);
+                                    ent, st_name, Elf_Word,
+                                    prevailing_name_idx);
                      ELF_SET_FIELD (type_functions, ei_class, Sym,
                                     ent, st_shndx, Elf_Half, SHN_UNDEF);
-                     *st_info = ELF_ST_INFO (ELF_ST_BIND (*st_info),
-                                             STT_NOTYPE);
-                     *st_other = STV_DEFAULT;
                    }
+                 *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 (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);
+         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)
-       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);
     }
@@ -1406,6 +1580,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;
 }
This page took 0.030719 seconds and 4 git commands to generate.