4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Routines for retrieving CTF data from a .SUNW_ctf ELF section
38 #include <sys/types.h>
44 typedef int read_cb_f(tdata_t *, char *, void *);
47 * Return the source types that the object was generated from.
50 built_source_types(Elf *elf, char const *file)
52 source_types_t types = SOURCE_NONE;
55 if ((si = symit_new(elf, file)) == NULL)
58 while (symit_next(si, STT_FILE) != NULL) {
59 char *name = symit_name(si);
60 size_t len = strlen(name);
61 if (len < 2 || name[len - 2] != '.') {
62 types |= SOURCE_UNKNOWN;
66 switch (name[len - 1]) {
78 types |= SOURCE_UNKNOWN;
87 read_file(Elf *elf, char *file, char *label, read_cb_f *func, void *arg,
91 Elf_Data *ctfdata = NULL;
92 symit_data_t *si = NULL;
96 if ((ctfscnidx = findelfsecidx(elf, file, ".SUNW_ctf")) < 0) {
98 (built_source_types(elf, file) & SOURCE_C)) {
99 terminate("Input file %s was partially built from "
100 "C sources, but no CTF data was present\n", file);
105 if ((ctfscn = elf_getscn(elf, ctfscnidx)) == NULL ||
106 (ctfdata = elf_getdata(ctfscn, NULL)) == NULL)
107 elfterminate(file, "Cannot read CTF section");
109 /* Reconstruction of type tree */
110 if ((si = symit_new(elf, file)) == NULL) {
111 warning("%s has no symbol table - skipping", file);
115 td = ctf_load(file, ctfdata->d_buf, ctfdata->d_size, si, label);
116 tdata_build_hashes(td);
121 if (func(td, file, arg) < 0)
130 read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
131 void *arg, int require_ctf)
134 Elf_Cmd cmd = ELF_C_READ;
136 int secnum = 1, found = 0;
138 while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
141 if ((arh = elf_getarhdr(melf)) == NULL) {
142 elfterminate(file, "Can't get archive header for "
143 "member %d", secnum);
146 /* skip special sections - their names begin with "/" */
147 if (*arh->ar_name != '/') {
148 size_t memlen = strlen(file) + 1 +
149 strlen(arh->ar_name) + 1 + 1;
150 char *memname = xmalloc(memlen);
152 snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);
154 switch (elf_kind(melf)) {
156 rc = read_archive(fd, melf, memname, label,
157 func, arg, require_ctf);
160 rc = read_file(melf, memname, label,
161 func, arg, require_ctf);
164 terminate("%s: Unknown elf kind %d\n",
165 memname, elf_kind(melf));
171 cmd = elf_next(melf);
172 (void) elf_end(melf);
185 read_ctf_common(char *file, char *label, read_cb_f *func, void *arg,
192 debug(3, "Reading %s (label %s)\n", file, (label ? label : "NONE"));
194 (void) elf_version(EV_CURRENT);
196 if ((fd = open(file, O_RDONLY)) < 0)
197 terminate("%s: Cannot open for reading", file);
198 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
199 elfterminate(file, "Cannot read");
201 switch (elf_kind(elf)) {
203 found = read_archive(fd, elf, file, label,
204 func, arg, require_ctf);
208 found = read_file(elf, file, label,
209 func, arg, require_ctf);
213 terminate("%s: Unknown elf kind %d\n", file, elf_kind(elf));
224 read_ctf_save_cb(tdata_t *td, char *name __unused, void *retp)
226 tdata_t **tdp = retp;
234 read_ctf(char **files, int n, char *label, read_cb_f *func, void *private,
240 for (i = 0, found = 0; i < n; i++) {
241 if ((rc = read_ctf_common(files[i], label, func,
242 private, require_ctf)) < 0)
251 count_archive(int fd, Elf *elf, char *file)
254 Elf_Cmd cmd = ELF_C_READ;
256 int nfiles = 0, err = 0;
258 while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
259 if ((arh = elf_getarhdr(melf)) == NULL) {
260 warning("Can't process input archive %s\n",
265 if (*arh->ar_name != '/')
268 cmd = elf_next(melf);
269 (void) elf_end(melf);
279 count_files(char **files, int n)
281 int nfiles = 0, err = 0;
285 (void) elf_version(EV_CURRENT);
287 for (i = 0; i < n; i++) {
288 char *file = files[i];
290 if ((fd = open(file, O_RDONLY)) < 0) {
291 warning("Can't read input file %s", file);
296 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
297 warning("Can't open input file %s: %s\n", file,
304 switch (elf_kind(elf)) {
306 if ((rc = count_archive(fd, elf, file)) < 0)
315 warning("Input file %s is corrupt\n", file);
326 debug(2, "Found %d files in %d input files\n", nfiles, n);
343 symit_new(Elf *elf, const char *file)
349 if ((symtabidx = findelfsecidx(elf, file, ".symtab")) < 0)
352 si = xcalloc(sizeof (symit_data_t));
354 if ((scn = elf_getscn(elf, symtabidx)) == NULL ||
355 gelf_getshdr(scn, &si->si_shdr) == NULL ||
356 (si->si_symd = elf_getdata(scn, NULL)) == NULL)
357 elfterminate(file, "Cannot read .symtab");
359 if ((scn = elf_getscn(elf, si->si_shdr.sh_link)) == NULL ||
360 (si->si_strd = elf_getdata(scn, NULL)) == NULL)
361 elfterminate(file, "Cannot read strings for .symtab");
363 si->si_nument = si->si_shdr.sh_size / si->si_shdr.sh_entsize;
369 symit_free(symit_data_t *si)
375 symit_reset(symit_data_t *si)
381 symit_curfile(symit_data_t *si)
383 return (si->si_curfile);
387 symit_next(symit_data_t *si, int type)
390 int check_sym = (type == STT_OBJECT || type == STT_FUNC);
392 for (; si->si_next < si->si_nument; si->si_next++) {
393 gelf_getsym(si->si_symd, si->si_next, &si->si_cursym);
394 gelf_getsym(si->si_symd, si->si_next, &sym);
395 si->si_curname = (caddr_t)si->si_strd->d_buf + sym.st_name;
397 if (GELF_ST_TYPE(sym.st_info) == STT_FILE)
398 si->si_curfile = si->si_curname;
400 if (GELF_ST_TYPE(sym.st_info) != type ||
401 sym.st_shndx == SHN_UNDEF)
404 if (check_sym && ignore_symbol(&sym, si->si_curname))
409 return (&si->si_cursym);
416 symit_name(symit_data_t *si)
418 return (si->si_curname);