1 /* Program to read the IL symbol table.
2 Copyright (C) 2008 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 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
27 #include "plugin-api.h"
28 #include "../gcc/lto/common.h"
30 /* The presence of gelf.h is checked by the toplevel configure script. */
33 static ld_plugin_claim_file_handler claim_file_handler
;
34 static ld_plugin_all_symbols_read_handler all_symbols_read_handler
;
35 static ld_plugin_cleanup_handler cleanup_handler
;
36 static void *plugin_handle
;
40 struct ld_plugin_symbol
*syms
;
43 static struct file_handle
**all_file_handles
= NULL
;
44 static unsigned int num_file_handles
;
46 /* Write NSYMS symbols from file HANDLE in SYMS. */
48 static enum ld_plugin_status
49 get_symbols (const void *handle
, int nsyms
, struct ld_plugin_symbol
*syms
)
52 struct file_handle
*h
= (struct file_handle
*) handle
;
53 assert (h
->nsyms
== nsyms
);
55 for (i
= 0; i
< nsyms
; i
++)
61 /* Register HANDLER as the callback for notifying the plugin that all symbols
64 static enum ld_plugin_status
65 register_all_symbols_read (ld_plugin_all_symbols_read_handler handler
)
67 all_symbols_read_handler
= handler
;
71 /* Register HANDLER as the callback for claiming a file. */
73 static enum ld_plugin_status
74 register_claim_file(ld_plugin_claim_file_handler handler
)
76 claim_file_handler
= handler
;
80 /* Register HANDLER as the callback to removing temporary files. */
82 static enum ld_plugin_status
83 register_cleanup (ld_plugin_cleanup_handler handler
)
85 cleanup_handler
= handler
;
89 /* For a file identified by HANDLE, add NSYMS symbols from SYMS. */
91 static enum ld_plugin_status
92 add_symbols (void *handle
, int nsyms
,
93 const struct ld_plugin_symbol
*syms
)
96 struct file_handle
*h
= (struct file_handle
*) handle
;
98 h
->syms
= calloc (nsyms
, sizeof (struct ld_plugin_symbol
));
101 for (i
= 0; i
< nsyms
; i
++)
103 h
->syms
[i
] = syms
[i
];
104 h
->syms
[i
].name
= strdup (h
->syms
[i
].name
);
105 if (h
->syms
[i
].version
)
106 h
->syms
[i
].version
= strdup (h
->syms
[i
].version
);
107 if (h
->syms
[i
].comdat_key
)
108 h
->syms
[i
].comdat_key
= strdup (h
->syms
[i
].comdat_key
);
114 struct ld_plugin_tv tv
[] = {
115 {LDPT_REGISTER_CLAIM_FILE_HOOK
,
116 {.tv_register_claim_file
= register_claim_file
}
119 {.tv_add_symbols
= add_symbols
}
122 {LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
,
123 {.tv_register_all_symbols_read
= register_all_symbols_read
}
126 {.tv_get_symbols
= get_symbols
}
128 {LDPT_REGISTER_CLEANUP_HOOK
,
129 {.tv_register_cleanup
= register_cleanup
}
134 /* Load a plugin from a file named NAME. */
137 load_plugin (const char *name
)
139 ld_plugin_onload onload
;
140 plugin_handle
= dlopen (name
, RTLD_LAZY
);
142 assert (plugin_handle
!= NULL
);
143 onload
= dlsym (plugin_handle
, "onload");
146 assert (claim_file_handler
);
149 /* Send object to the plugin. The file (archive or object) name is NAME.
150 FD is an open file descriptor. The object data starts at OFFSET and is
151 FILESIZE bytes long. */
154 register_object (const char *name
, int fd
, off_t offset
, off_t filesize
)
157 struct ld_plugin_input_file file
;
161 all_file_handles
= realloc (all_file_handles
, num_file_handles
162 * sizeof (struct file_handle
*));
163 assert (all_file_handles
);
165 all_file_handles
[num_file_handles
- 1] = calloc (1,
166 sizeof (struct file_handle
));
167 handle
= all_file_handles
[num_file_handles
- 1];
170 file
.name
= (char *) name
;
172 file
.offset
= offset
;
173 file
.filesize
= filesize
;
175 file
.handle
= handle
;
177 claim_file_handler (&file
, &claimed
);
180 /* Send file named NAME to the plugin. */
183 register_file (const char *name
)
185 int fd
= open (name
, O_RDONLY
);
190 elf
= elf_begin (fd
, ELF_C_READ
, NULL
);
193 Elf_Kind kind
= elf_kind (elf
);
195 assert (kind
== ELF_K_ELF
|| kind
== ELF_K_AR
);
197 if (kind
== ELF_K_AR
)
199 Elf
*member
= elf_begin (fd
, ELF_C_READ
, elf
);
202 Elf_Arhdr
*h
= elf_getarhdr (member
);
205 if (h
->ar_name
[0] != '/')
207 off_t offset
= elf_getbase (member
);
208 register_object (name
, fd
, offset
, h
->ar_size
);
211 Elf_Cmd cmd
= elf_next (member
);
213 member
= elf_begin (fd
, cmd
, elf
);
216 else /* Single File */
217 register_object (name
, fd
, 0, 0);
222 /* Fake symbol resolution for testing. */
228 for (j
= 0; j
< num_file_handles
; j
++)
230 struct file_handle
*handle
= all_file_handles
[j
];
231 unsigned int nsyms
= handle
->nsyms
;
232 struct ld_plugin_symbol
*syms
= handle
->syms
;
234 for (i
= 0; i
< nsyms
; i
++)
241 syms
[i
].resolution
= LDPR_PREVAILING_DEF
;
245 syms
[i
].resolution
= LDPR_RESOLVED_IR
;
252 /* Print all symbol information. */
258 for (j
= 0; j
< num_file_handles
; j
++)
260 struct file_handle
*handle
= all_file_handles
[j
];
261 unsigned int nsyms
= handle
->nsyms
;
262 struct ld_plugin_symbol
*syms
= handle
->syms
;
264 for (i
= 0; i
< nsyms
; i
++)
266 printf("name: %s; ", syms
[i
].name
);
268 printf("version: %s;", syms
[i
].version
);
270 printf("not versioned; ");
271 printf("kind: %s; ", lto_kind_str
[syms
[i
].def
]);
272 printf("visibility: %s; ", lto_visibility_str
[syms
[i
].visibility
]);
273 printf("size: %" PRId64
"; ", syms
[i
].size
);
274 if (syms
[i
].comdat_key
)
275 printf("comdat_key: %s; ", syms
[i
].comdat_key
);
277 printf("no comdat_key; ");
278 printf ("resolution: %s\n", lto_resolution_str
[syms
[i
].resolution
]);
283 /* Unload the plugin. */
288 unsigned err
= dlclose (plugin_handle
);
290 claim_file_handler
= 0;
291 all_symbols_read_handler
= 0;
294 /* Free all memory allocated by us that hasn't been freed yet. */
300 for (j
= 0; j
< num_file_handles
; j
++)
302 struct file_handle
*handle
= all_file_handles
[j
];
303 unsigned int nsyms
= handle
->nsyms
;
304 struct ld_plugin_symbol
*syms
= handle
->syms
;
306 for (i
= 0; i
< nsyms
; i
++)
312 free (syms
[i
].version
);
315 if (syms
[i
].comdat_key
)
317 free (syms
[i
].comdat_key
);
318 syms
[i
].comdat_key
= 0;
324 free (all_file_handles
[j
]);
325 all_file_handles
[j
] = NULL
;
328 free (all_file_handles
);
329 all_file_handles
= NULL
;
330 num_file_handles
= 0;
334 main(int argc
, char *argv
[])
341 load_plugin (plugin
);
343 for (i
= 2; i
< argc
; i
++)
344 register_file (argv
[i
]);
350 all_symbols_read_handler ();