This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][LTO][RFC] AR archive support for LTO
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: espindola at google dot com, ccoutant at google dot com
- Date: Sun, 1 Nov 2009 14:04:16 +0100 (CET)
- Subject: Re: [PATCH][LTO][RFC] AR archive support for LTO
- References: <alpine.LNX.2.00.0911011202540.4520@zhemvz.fhfr.qr>
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);