This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

Re: [PATCH][LTO][RFC] AR archive support for LTO


On Sun, 1 Nov 2009, Richard Guenther wrote:

> 
> This implements a simple way of retrofitting AR support into the
> existing LTO ELF machinery.  It avoids breaking the number-of-files
> == number-of-objects equality and thus avoids touching the various
> places we iterate over files.  It also avoids that LTO would need
> to think about partially LTOed archives.
> 
> The hack is that the LTO frontend now knows how to address a
> single ELF object inside an ar archive.  lto1 gets passed
> these objects as ARCHIVE@OBJECT, for example t.a@t1.o.  This
> should avoid the need to extract the archive inside the linker
> plugin and should allow straight-forward support for archives
> inside collect2.
> 
> The patch re-introduces the problem of unaligned accesses as
> ar archive members are only 2-byte aligned.  I guess strict-align
> hosts would need to fall back to read instead of mmap here,
> or we need to audit all places that read from the mmapped memory
> with non-char pointers ...
> 
> The patch doesn't try to limit the users ability of shooting
> himself in the foot, like when linking with --whole-archive
> and mixed LTO / non-LTO archives.  As is I consider the patch
> a cleanup for the existing AR support in the linker plugin.
> 
> Once again libelfs are broken.  libelf 0.8.12 doesn't have
> elf_getaroff and at least elfutils is broken when iterating
> through archive members (it repeats the last entry forever,
> at increasing offsets).  I have worked around both issues...
> 
> Tested manually on archives up to two members (yay!).
> 
> Comments?
> 
> Volunteers to hack this support into the linker-plugin?

Actually I can avoid most of the mess by using elf_getbase like
the following.  The elfutils libelf bug persists though, so we
have to leave the workaround in.

Richard.

2009-11-01  Richard Guenther  <rguenther@suse.de>

	lto/
	* lto-elf.c (lto_elf_build_section_table): Add the base offset.
	(lto_elf_file_open): Handle object files in ar archives
	named archive@object.

Index: gcc/lto/lto-elf.c
===================================================================
*** gcc/lto/lto-elf.c	(revision 153774)
--- gcc/lto/lto-elf.c	(working copy)
*************** lto_elf_build_section_table (lto_file *l
*** 167,175 ****
--- 167,177 ----
    lto_elf_file *elf_file = (lto_elf_file *)lto_file;
    htab_t section_hash_table;
    Elf_Scn *section;
+   size_t base_offset;
  
    section_hash_table = htab_create (37, hash_name, eq_name, free);
  
+   base_offset = elf_getbase (elf_file->elf);
    for (section = elf_getscn (elf_file->elf, 0);
         section;
         section = elf_nextscn (elf_file->elf, section)) 
*************** lto_elf_build_section_table (lto_file *l
*** 206,212 ****
  
  	  new_slot->name = new_name;
  	  /* The offset into the file for this section.  */
! 	  new_slot->start = shdr->sh_offset;
  	  new_slot->len = shdr->sh_size;
  	  *slot = new_slot;
  	}
--- 208,214 ----
  
  	  new_slot->name = new_name;
  	  /* The offset into the file for this section.  */
! 	  new_slot->start = base_offset + shdr->sh_offset;
  	  new_slot->len = shdr->sh_size;
  	  *slot = new_slot;
  	}
*************** init_ehdr (lto_elf_file *elf_file)
*** 530,536 ****
      }
  }
  
- 
  /* Open ELF file FILENAME.  If WRITABLE is true, the file is opened for write
     and, if necessary, created.  Otherwise, the file is opened for reading.
     Returns the opened file.  */
--- 532,537 ----
*************** lto_elf_file_open (const char *filename,
*** 540,557 ****
  {
    lto_elf_file *elf_file;
    lto_file *result;
  
    /* Set up.  */
    elf_file = XCNEW (lto_elf_file);
    result = (lto_file *) elf_file;
!   lto_file_init (result, filename);
    elf_file->fd = -1;
  
    /* Open the file.  */
!   elf_file->fd = open (filename, writable ? O_WRONLY|O_CREAT : O_RDONLY, 0666);
    if (elf_file->fd == -1)
      {
!       error ("could not open file %s", filename);
        goto fail;
      }
  
--- 541,571 ----
  {
    lto_elf_file *elf_file;
    lto_file *result;
+   const char *entry_name;
+   char *fname;
+ 
+   entry_name = strchr (filename, '@');
+   if (!entry_name)
+     fname = xstrdup (filename);
+   else
+     {
+       fname = (char *)xmalloc (entry_name - filename + 1);
+       memcpy (fname, filename, entry_name - filename);
+       fname[entry_name - filename] = '\0';
+       entry_name++;
+     }
  
    /* Set up.  */
    elf_file = XCNEW (lto_elf_file);
    result = (lto_file *) elf_file;
!   lto_file_init (result, fname);
    elf_file->fd = -1;
  
    /* Open the file.  */
!   elf_file->fd = open (fname, writable ? O_WRONLY|O_CREAT : O_RDONLY, 0666);
    if (elf_file->fd == -1)
      {
!       error ("could not open file %s", fname);
        goto fail;
      }
  
*************** lto_elf_file_open (const char *filename,
*** 571,576 ****
--- 585,634 ----
        goto fail;
      }
  
+   if (elf_kind (elf_file->elf) == ELF_K_AR)
+     {
+       Elf *e;
+       struct stat sbuf;
+ 
+       if (!entry_name)
+ 	{
+ 	  error ("need ar entry name for %s", fname);
+ 	  goto fail;
+ 	}
+ 
+       fstat (elf_file->fd, &sbuf);
+       do
+ 	{
+ 	  Elf_Arhdr *arh;
+ 	  e = elf_begin (elf_file->fd, ELF_C_READ, elf_file->elf);
+ 	  if (!e
+ 	      /* ???  The iterator seems to stick on the last entry but
+ 		 advances offsets for elfutils libelf.  */
+ 	      || sbuf.st_size < elf_getbase (e))
+ 	    break;
+ 	  arh = elf_getarhdr (e);
+ 	  if (arh
+ 	      && strcmp (arh->ar_name, entry_name) == 0)
+ 	    break;
+ 
+ 	  elf_next (e);
+ 	  elf_end (e);
+ 	}
+       while (1);
+       if (!e)
+ 	{
+ 	  error ("ar entry %s not found in archive %s", entry_name, fname);
+ 	  goto fail;
+ 	}
+       elf_end (elf_file->elf);
+       elf_file->elf = e;
+     }
+   else if (entry_name)
+     {
+       error ("ar entry name specified for non-archive %s", fname);
+       goto fail;
+     }
+ 
    if (writable)
      {
        init_ehdr (elf_file);


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