This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix section symbols in objcopy when removing sections with relocations from Elf objects


Hi,

This patch fixes a problem where, if sections are removed during objcopy with Elf object files, the section symbols corresponding to the relocation sections for the removed sections may be left in the target object file.

In my test case, the file being manipulated is a "crt1.o", and the command-line to do the stripping is:

arm-none-linux-gnueabi-objcopy -R .debug_info [-R more debug sections] /path/to/crt1.o

I.e. "-R" is being used to remove various debugging sections, which in the source object file contain sections such as ".debug_info" along with a corresponding ".rel.debug_info" containing relocations. The -R switch removes both the section itself and its relocations.

However, the resulting file contains invalid section symbols like so:

Symbol table '.symtab' contains 34 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
    ...
    11: 00000000     0 SECTION LOCAL  DEFAULT   14
    12: 00000000     0 SECTION LOCAL  DEFAULT   16
    13: 00000000     0 SECTION LOCAL  DEFAULT   19
    14: 00000000     0 SECTION LOCAL  DEFAULT   10
    15: 00000000     0 SECTION LOCAL  DEFAULT   22
    16: 00000000     0 SECTION LOCAL  DEFAULT   23
    17: 00000000     0 SECTION LOCAL  DEFAULT   24

Even though the sections in the file are now only numbered up to 13. These symbols correspond to the relocation sections for the removed debug sections. Internally, bfd knows little about these sections -- they are folded into the bfd section containing information on the relocatee during Elf parsing.

Fixing this cleanly isn't particularly easy, because there isn't any one point at which all the right information seems to be readily available. The obvious point to remove the extraneous symbols is in objcopy.c:filter_symbols(), though that function is supposed to be target-independent, so this involves an Elf-specific hack.

Other choices might have been to remove the bad symbols whilst parsing in or writing out the Elf file, though since the right information isn't really available in either of those places either, that would probably involve similar or worse hacks (elf.c:bfd_section_from_shdr knows nothing about symbols, and elf.c:swap_out_symbols knows nothing about the input bfd).

Once the bad symbol sections are removed, another problem becomes apparent, which is that higher-numbered section symbols (for .shstrtab, .symtab, .strtab) are not rewritten to point to their now lower-numbered sections correctly. I think there's existing logic which is supposed to handle this, e.g. elf.c:swap_out_syms has a comment:

    /* This symbol is in a real ELF section which we did
       not create as a BFD section.  Undo the mapping done
       by copy_private_symbol_data.  */

With code following to handle several specific sections, including the ones which are now numbered wrongly in this case. Unfortunately, during an objcopy invocation, copy_private_symbol_data isn't actually ever called to set up the mapping before this reverse mapping takes place, so I've added a call to it in filter_symbols. I then discovered that the necessary private fields to make this to work aren't set when reading in the source file, so I've added those (to bfd_section_from_shdr).

I've tested the patch against the proprietary linker which originally barfed on the bad crt1.o file, and against hand-written tests (based on tweaked compiler output with -ffunction-sections turned on), and I believe it DTRT, at least in those cases. It's also tested with "make check" for --enable-targets=all.

The patch is currently against the CSL branch. OK to apply there? On mainline? Does this need a new testcase?

Cheers,

Julian

ChangeLog:

bfd/

    * elf.c (bfd_section_from_shdr): Set symtab_shndx_section,
    shstrtab_section, strtab_section in ELF private data.

binutils/

    * objcopy.c (filter_symbols): Filter out section symbols for
    sections which are being stripped and their associated relocation
    sections. Call bfd_copy_private_symbol_data for each symbol which
    passes the filter.
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.329
diff -c -p -r1.329 elf.c
*** bfd/elf.c	16 Mar 2006 12:20:15 -0000	1.329
--- bfd/elf.c	24 May 2006 12:52:58 -0000
*************** bfd_section_from_shdr (bfd *abfd, unsign
*** 1935,1940 ****
--- 1935,1941 ----
        BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
        elf_symtab_shndx (abfd) = shindex;
        elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
+       elf_tdata (abfd)->symtab_shndx_section = shindex;
        elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
        return TRUE;
  
*************** bfd_section_from_shdr (bfd *abfd, unsign
*** 1944,1949 ****
--- 1945,1951 ----
        if (ehdr->e_shstrndx == shindex)
  	{
  	  elf_tdata (abfd)->shstrtab_hdr = *hdr;
+           elf_tdata (abfd)->shstrtab_section = shindex;
  	  elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
  	  return TRUE;
  	}
*************** bfd_section_from_shdr (bfd *abfd, unsign
*** 1951,1956 ****
--- 1953,1959 ----
  	{
  	symtab_strtab:
  	  elf_tdata (abfd)->strtab_hdr = *hdr;
+           elf_tdata (abfd)->strtab_section = shindex;
  	  elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
  	  return TRUE;
  	}
Index: binutils/objcopy.c
===================================================================
RCS file: /cvs/src/src/binutils/objcopy.c,v
retrieving revision 1.95
diff -c -p -r1.95 objcopy.c
*** binutils/objcopy.c	28 Feb 2006 16:09:01 -0000	1.95
--- binutils/objcopy.c	24 May 2006 12:52:58 -0000
*************** filter_symbols (bfd *abfd, bfd *obfd, as
*** 915,920 ****
--- 915,959 ----
  	       || undefined
  	       || bfd_is_com_section (bfd_get_section (sym)))
  	keep = strip_symbols != STRIP_UNNEEDED;
+       else if ((flags & BSF_SECTION_SYM) != 0)  /* Section symbol.  */
+         {
+           struct bfd_section *section = sym->section;
+ 
+           keep = 1;
+ 
+           if (!bfd_is_abs_section (section)
+               && is_strip_section (abfd, section))
+ 	    keep = 0;
+           else if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+             {
+               Elf_Internal_Shdr **elfsections = elf_elfsections (abfd);
+               unsigned int sec;
+               
+               for (sec = 0; sec < elf_numsections (abfd); sec++)
+                 {
+                   Elf_Internal_Shdr *elfhdr = elfsections[sec];
+                   if ((elfhdr->sh_type == SHT_REL
+                        || elfhdr->sh_type == SHT_RELA))
+                     {
+                       char *secname =
+                         bfd_elf_string_from_elf_section (abfd,
+                           elf_elfheader (abfd)->e_shstrndx,
+                           elfhdr->sh_name);
+ 
+                       if (strcmp (secname, name) == 0)
+                         {
+                           struct bfd_section *targsec =
+                             bfd_section_from_elf_index (abfd, elfhdr->sh_info);
+                           if (targsec && is_strip_section (abfd, targsec))
+                             {
+                               keep = 0;
+                               break;
+                             }
+                         }
+                     }
+                 }
+             }
+         }
        else if ((flags & BSF_DEBUGGING) != 0)	/* Debugging symbol.  */
  	keep = (strip_symbols != STRIP_DEBUG
  		&& strip_symbols != STRIP_UNNEEDED
*************** filter_symbols (bfd *abfd, bfd *obfd, as
*** 969,975 ****
  	      sym->flags |= BSF_GLOBAL;
  	    }
  
! 	  to[dst_count++] = sym;
  	}
      }
  
--- 1008,1016 ----
  	      sym->flags |= BSF_GLOBAL;
  	    }
  
! 	  to[dst_count] = sym;
!           bfd_copy_private_symbol_data (abfd, sym, obfd, to[dst_count]);
!           dst_count++;
  	}
      }
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]