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]) {
77 types
|= SOURCE_UNKNOWN
;
86 read_file(Elf
*elf
, char *file
, char *label
, read_cb_f
*func
, void *arg
,
91 symit_data_t
*si
= NULL
;
95 if ((ctfscnidx
= findelfsecidx(elf
, file
, ".SUNW_ctf")) < 0) {
97 (built_source_types(elf
, file
) & SOURCE_C
)) {
98 terminate("Input file %s was partially built from "
99 "C sources, but no CTF data was present\n", file
);
104 if ((ctfscn
= elf_getscn(elf
, ctfscnidx
)) == NULL
||
105 (ctfdata
= elf_getdata(ctfscn
, NULL
)) == NULL
)
106 elfterminate(file
, "Cannot read CTF section");
108 /* Reconstruction of type tree */
109 if ((si
= symit_new(elf
, file
)) == NULL
) {
110 warning("%s has no symbol table - skipping", file
);
114 td
= ctf_load(file
, ctfdata
->d_buf
, ctfdata
->d_size
, si
, label
);
115 tdata_build_hashes(td
);
120 if (func(td
, file
, arg
) < 0)
129 read_archive(int fd
, Elf
*elf
, char *file
, char *label
, read_cb_f
*func
,
130 void *arg
, int require_ctf
)
133 Elf_Cmd cmd
= ELF_C_READ
;
135 int secnum
= 1, found
= 0;
137 while ((melf
= elf_begin(fd
, cmd
, elf
)) != NULL
) {
140 if ((arh
= elf_getarhdr(melf
)) == NULL
) {
141 elfterminate(file
, "Can't get archive header for "
142 "member %d", secnum
);
145 /* skip special sections - their names begin with "/" */
146 if (*arh
->ar_name
!= '/') {
147 size_t memlen
= strlen(file
) + 1 +
148 strlen(arh
->ar_name
) + 1 + 1;
149 char *memname
= xmalloc(memlen
);
151 snprintf(memname
, memlen
, "%s(%s)", file
, arh
->ar_name
);
153 switch (elf_kind(melf
)) {
155 rc
= read_archive(fd
, melf
, memname
, label
,
156 func
, arg
, require_ctf
);
159 rc
= read_file(melf
, memname
, label
,
160 func
, arg
, require_ctf
);
163 terminate("%s: Unknown elf kind %d\n",
164 memname
, elf_kind(melf
));
170 cmd
= elf_next(melf
);
171 (void) elf_end(melf
);
184 read_ctf_common(char *file
, char *label
, read_cb_f
*func
, void *arg
,
191 debug(3, "Reading %s (label %s)\n", file
, (label
? label
: "NONE"));
193 (void) elf_version(EV_CURRENT
);
195 if ((fd
= open(file
, O_RDONLY
)) < 0)
196 terminate("%s: Cannot open for reading", file
);
197 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
)
198 elfterminate(file
, "Cannot read");
200 switch (elf_kind(elf
)) {
202 found
= read_archive(fd
, elf
, file
, label
,
203 func
, arg
, require_ctf
);
207 found
= read_file(elf
, file
, label
,
208 func
, arg
, require_ctf
);
212 terminate("%s: Unknown elf kind %d\n", file
, elf_kind(elf
));
223 read_ctf_save_cb(tdata_t
*td
, char *name
, void *retp
)
225 tdata_t
**tdp
= retp
;
233 read_ctf(char **files
, int n
, char *label
, read_cb_f
*func
, void *private,
239 for (i
= 0, found
= 0; i
< n
; i
++) {
240 if ((rc
= read_ctf_common(files
[i
], label
, func
,
241 private, require_ctf
)) < 0)
250 count_archive(int fd
, Elf
*elf
, char *file
)
253 Elf_Cmd cmd
= ELF_C_READ
;
255 int nfiles
= 0, err
= 0;
257 while ((melf
= elf_begin(fd
, cmd
, elf
)) != NULL
) {
258 if ((arh
= elf_getarhdr(melf
)) == NULL
) {
259 warning("Can't process input archive %s\n",
264 if (*arh
->ar_name
!= '/')
267 cmd
= elf_next(melf
);
268 (void) elf_end(melf
);
278 count_files(char **files
, int n
)
280 int nfiles
= 0, err
= 0;
284 (void) elf_version(EV_CURRENT
);
286 for (i
= 0; i
< n
; i
++) {
287 char *file
= files
[i
];
289 if ((fd
= open(file
, O_RDONLY
)) < 0) {
290 warning("Can't read input file %s", file
);
295 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
) {
296 warning("Can't open input file %s: %s\n", file
,
303 switch (elf_kind(elf
)) {
305 if ((rc
= count_archive(fd
, elf
, file
)) < 0)
314 warning("Input file %s is corrupt\n", file
);
325 debug(2, "Found %d files in %d input files\n", nfiles
, n
);
342 symit_new(Elf
*elf
, const char *file
)
348 if ((symtabidx
= findelfsecidx(elf
, file
, ".symtab")) < 0)
351 si
= xcalloc(sizeof (symit_data_t
));
353 if ((scn
= elf_getscn(elf
, symtabidx
)) == NULL
||
354 gelf_getshdr(scn
, &si
->si_shdr
) == NULL
||
355 (si
->si_symd
= elf_getdata(scn
, NULL
)) == NULL
)
356 elfterminate(file
, "Cannot read .symtab");
358 if ((scn
= elf_getscn(elf
, si
->si_shdr
.sh_link
)) == NULL
||
359 (si
->si_strd
= elf_getdata(scn
, NULL
)) == NULL
)
360 elfterminate(file
, "Cannot read strings for .symtab");
362 si
->si_nument
= si
->si_shdr
.sh_size
/ si
->si_shdr
.sh_entsize
;
368 symit_free(symit_data_t
*si
)
374 symit_reset(symit_data_t
*si
)
380 symit_curfile(symit_data_t
*si
)
382 return (si
->si_curfile
);
386 symit_next(symit_data_t
*si
, int type
)
389 int check_sym
= (type
== STT_OBJECT
|| type
== STT_FUNC
);
391 for (; si
->si_next
< si
->si_nument
; si
->si_next
++) {
392 gelf_getsym(si
->si_symd
, si
->si_next
, &si
->si_cursym
);
393 gelf_getsym(si
->si_symd
, si
->si_next
, &sym
);
394 si
->si_curname
= (caddr_t
)si
->si_strd
->d_buf
+ sym
.st_name
;
396 if (GELF_ST_TYPE(sym
.st_info
) == STT_FILE
)
397 si
->si_curfile
= si
->si_curname
;
399 if (GELF_ST_TYPE(sym
.st_info
) != type
||
400 sym
.st_shndx
== SHN_UNDEF
)
403 if (check_sym
&& ignore_symbol(&sym
, si
->si_curname
))
408 return (&si
->si_cursym
);
415 symit_name(symit_data_t
*si
)
417 return (si
->si_curname
);