re PR libstdc++/43554 (profile-mode version of forward_list missing)
[official-gcc.git] / lto-plugin / lto-plugin-elf.c
blobafd79dac05687a6ba19cfaa1565e8eabab21887d
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)
8 any later version.
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/>. */
19 #include <assert.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <libiberty.h>
23 #include <stdlib.h>
24 #include <inttypes.h>
26 /* The presence of gelf.h is checked by the toplevel configure script. */
27 #include <gelf.h>
29 /* Common definitions that the object format dependent code needs. */
30 #include "lto-plugin.h"
32 /* Process all lto symtabs of file ELF. */
34 static int
35 process_symtab (Elf *elf, struct plugin_symtab *out)
37 int found = 0;
38 Elf_Scn *section = 0;
39 GElf_Ehdr header;
40 GElf_Ehdr *t = gelf_getehdr (elf, &header);
41 if (t == NULL)
42 return 0;
43 assert (t == &header);
45 while ((section = elf_nextscn(elf, section)) != 0)
47 GElf_Shdr shdr;
48 GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
49 Elf_Data *symtab;
50 const char *t;
51 assert (tshdr == &shdr);
52 t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
53 assert (t != NULL);
54 if (strncmp (t, LTO_SECTION_PREFIX, strlen (LTO_SECTION_PREFIX)) == 0)
56 char *s = strrchr (t, '.');
57 if (s)
58 sscanf (s, ".%x", &out->id);
59 symtab = elf_getdata (section, NULL);
60 translate (symtab->d_buf, symtab->d_buf + symtab->d_size, out);
61 found++;
64 return found;
67 /* Callback used by gold to check if the plugin will claim FILE. Writes
68 the result in CLAIMED. */
70 enum ld_plugin_status
71 claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
73 enum ld_plugin_status status;
74 Elf *elf;
75 struct plugin_file_info lto_file;
76 int n;
78 memset (&lto_file, 0, sizeof (struct plugin_file_info));
80 if (file->offset != 0)
82 char *objname;
83 Elf *archive;
84 off_t offset;
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");
104 elf_end (archive);
106 else
108 lto_file.name = xstrdup (file->name);
109 elf = elf_begin (file->fd, ELF_C_READ, NULL);
111 lto_file.handle = file->handle;
113 *claimed = 0;
115 if (!elf)
116 goto err;
118 n = process_symtab (elf, &lto_file.symtab);
119 if (n == 0)
120 goto err;
122 if (n > 1)
123 resolve_conflicts (&lto_file.symtab, &lto_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");
129 *claimed = 1;
130 num_claimed_files++;
131 claimed_files =
132 xrealloc (claimed_files,
133 num_claimed_files * sizeof (struct plugin_file_info));
134 claimed_files[num_claimed_files - 1] = lto_file;
136 goto cleanup;
138 err:
139 free (lto_file.name);
141 cleanup:
142 if (elf)
143 elf_end (elf);
145 return LDPS_OK;
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");
155 return LDPS_OK;