1 /* LTO plugin for gold.
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3 Contributed by Rafael Avila de Espindola (espindola@google.com).
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
22 #include <libiberty.h>
26 /* The presence of gelf.h is checked by the toplevel configure script. */
29 /* Common definitions that the object format dependent code needs. */
30 #include "lto-plugin.h"
32 /* Process all lto symtabs of file ELF. */
35 process_symtab (Elf
*elf
, struct plugin_symtab
*out
)
40 GElf_Ehdr
*t
= gelf_getehdr (elf
, &header
);
43 assert (t
== &header
);
45 while ((section
= elf_nextscn(elf
, section
)) != 0)
48 GElf_Shdr
*tshdr
= gelf_getshdr (section
, &shdr
);
51 assert (tshdr
== &shdr
);
52 t
= elf_strptr (elf
, header
.e_shstrndx
, shdr
.sh_name
);
54 if (strncmp (t
, LTO_SECTION_PREFIX
, strlen (LTO_SECTION_PREFIX
)) == 0)
56 char *s
= strrchr (t
, '.');
58 sscanf (s
, ".%x", &out
->id
);
59 symtab
= elf_getdata (section
, NULL
);
60 translate (symtab
->d_buf
, symtab
->d_buf
+ symtab
->d_size
, out
);
67 /* Callback used by gold to check if the plugin will claim FILE. Writes
68 the result in CLAIMED. */
71 claim_file_handler (const struct ld_plugin_input_file
*file
, int *claimed
)
73 enum ld_plugin_status status
;
75 struct plugin_file_info lto_file
;
78 memset (<o_file
, 0, sizeof (struct plugin_file_info
));
80 if (file
->offset
!= 0)
85 /* We pass the offset of the actual file, not the archive header. */
86 int t
= asprintf (&objname
, "%s@0x%" PRIx64
, file
->name
,
87 (int64_t) file
->offset
);
88 check (t
>= 0, LDPL_FATAL
, "asprintf failed");
89 lto_file
.name
= objname
;
91 archive
= elf_begin (file
->fd
, ELF_C_READ
, NULL
);
92 check (elf_kind (archive
) == ELF_K_AR
, LDPL_FATAL
,
93 "Not an archive and offset not 0");
95 /* elf_rand expects the offset to point to the ar header, not the
96 object itself. Subtract the size of the ar header (60 bytes).
97 We don't uses sizeof (struct ar_hd) to avoid including ar.h */
99 offset
= file
->offset
- 60;
100 check (offset
== elf_rand (archive
, offset
), LDPL_FATAL
,
101 "could not seek in archive");
102 elf
= elf_begin (file
->fd
, ELF_C_READ
, archive
);
103 check (elf
!= NULL
, LDPL_FATAL
, "could not find archive member");
108 lto_file
.name
= xstrdup (file
->name
);
109 elf
= elf_begin (file
->fd
, ELF_C_READ
, NULL
);
111 lto_file
.handle
= file
->handle
;
118 n
= process_symtab (elf
, <o_file
.symtab
);
123 resolve_conflicts (<o_file
.symtab
, <o_file
.conflicts
);
125 status
= add_symbols (file
->handle
, lto_file
.symtab
.nsyms
,
126 lto_file
.symtab
.syms
);
127 check (status
== LDPS_OK
, LDPL_FATAL
, "could not add symbols");
132 xrealloc (claimed_files
,
133 num_claimed_files
* sizeof (struct plugin_file_info
));
134 claimed_files
[num_claimed_files
- 1] = lto_file
;
139 free (lto_file
.name
);
148 /* Method called first thing at onload time to perform sanity checks. */
150 enum ld_plugin_status
151 onload_format_checks (struct ld_plugin_tv
*tv
)
153 unsigned version
= elf_version (EV_CURRENT
);
154 check (version
!= EV_NONE
, LDPL_FATAL
, "invalid ELF version");