]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libiberty/simple-object-elf.c
GCC: Check if AR works with --plugin and rc
[thirdparty/gcc.git] / libiberty / simple-object-elf.c
index 22c9ae7ed2df01dfe221e9627b82e6d56f225824..eee07039984da28d69a2c914da81995f1d1d0727 100644 (file)
@@ -1,5 +1,5 @@
 /* simple-object-elf.c -- routines to manipulate ELF object files.
-   Copyright (C) 2010-2019 Free Software Foundation, Inc.
+   Copyright (C) 2010-2023 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Google.
 
 This program is free software; you can redistribute it and/or modify it
@@ -528,7 +528,7 @@ simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
             not handle objects with more than SHN_LORESERVE sections
             correctly.  All large section indexes were offset by
             0x100.  There is more information at
-            http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
+            https://sourceware.org/PR5900 .
             Fortunately these object files are easy to detect, as the
             GNU binutils always put the section header string table
             near the end of the list of sections.  Thus if the
@@ -548,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;
 }
 
@@ -1183,7 +1191,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
          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;
+         symtab_indices_shndx[sh_link - 1] = i - 1;
          /* 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
@@ -1358,50 +1366,73 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
          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 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);
-         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;
+         size_t prevailing_name_idx = 0;
          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)
            {
-             unsigned char *sidxhdr = shdrs + (strtab - 1) * shdr_size;
+             unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 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);
+             unsigned int shndx_type
+               = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+                                  sidxhdr, sh_type, Elf_Word);
+             if (shndx_type != SHT_SYMTAB_SHNDX)
+               return "Wrong section type of a SYMTAB SECTION INDICES section";
              shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
              simple_object_internal_read (sobj->descriptor,
                                           sobj->offset + sidxoff,
                                           (unsigned char *)shndx_table,
                                           sidxsz, &errmsg, err);
            }
+
+         /* 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 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)
+               {
+                 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,
@@ -1424,9 +1455,10 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
              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.  */
+             /* 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
@@ -1438,6 +1470,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                       && st_shndx < shnum
                       && pfnret[st_shndx - 1] == -1)
                discard = 1;
+             /* We also need to remove global UNDEFs which can
+                cause link fails later.  */
+             else if (st_shndx == SHN_UNDEF
+                      && ELF_ST_BIND (*st_info) == STB_GLOBAL)
+               discard = 1;
 
              if (discard)
                {
@@ -1458,13 +1495,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                  else
                    {
                      /* Make discarded global symbols hidden weak
-                        undefined and sharing the gnu_lto_ name.  */
+                        undefined and sharing a name of a prevailing
+                        symbol.  */
                      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_name, Elf_Word,
+                                    prevailing_name_idx);
                      ELF_SET_FIELD (type_functions, ei_class, Sym,
                                     ent, st_shndx, Elf_Half, SHN_UNDEF);
                    }
@@ -1481,7 +1518,6 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                ELF_SET_FIELD (type_functions, ei_class, Sym,
                               ent, st_shndx, Elf_Half, sh_map[st_shndx]);
            }
-         XDELETEVEC (strings);
          XDELETEVEC (shndx_table);
        }
       else if (sh_type == SHT_GROUP)
@@ -1523,17 +1559,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
          {
            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];
+           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];
+       sh_link = sh_map[sh_link];
        ELF_SET_FIELD (type_functions, ei_class, Shdr,
                       shdr, sh_link, Elf_Word, sh_link);
       }