dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libctf / common / ctf_convert.c
blob1a433d17dbf0269605af7c40b3377377ec1e7b28
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2015 Joyent, Inc.
17 * Main conversion entry points. This has been designed such that there can be
18 * any number of different conversion backends. Currently we only have one that
19 * understands DWARFv2 (and bits of DWARFv4). Each backend should be placed in
20 * the ctf_converters list and each will be tried in turn.
23 #include <libctf_impl.h>
24 #include <gelf.h>
26 ctf_convert_f ctf_converters[] = {
27 ctf_dwarf_convert
30 #define NCONVERTS (sizeof (ctf_converters) / sizeof (ctf_convert_f))
32 typedef enum ctf_convert_source {
33 CTFCONV_SOURCE_NONE = 0x0,
34 CTFCONV_SOURCE_UNKNOWN = 0x01,
35 CTFCONV_SOURCE_C = 0x02,
36 CTFCONV_SOURCE_S = 0x04
37 } ctf_convert_source_t;
39 static void
40 ctf_convert_ftypes(Elf *elf, ctf_convert_source_t *types)
42 int i;
43 Elf_Scn *scn = NULL, *strscn;
44 *types = CTFCONV_SOURCE_NONE;
45 GElf_Shdr shdr;
46 Elf_Data *data, *strdata;
48 while ((scn = elf_nextscn(elf, scn)) != NULL) {
50 if (gelf_getshdr(scn, &shdr) == NULL)
51 return;
53 if (shdr.sh_type == SHT_SYMTAB)
54 break;
57 if (scn == NULL)
58 return;
60 if ((strscn = elf_getscn(elf, shdr.sh_link)) == NULL)
61 return;
63 if ((data = elf_getdata(scn, NULL)) == NULL)
64 return;
66 if ((strdata = elf_getdata(strscn, NULL)) == NULL)
67 return;
69 for (i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
70 GElf_Sym sym;
71 const char *file;
72 size_t len;
74 if (gelf_getsym(data, i, &sym) == NULL)
75 return;
77 if (GELF_ST_TYPE(sym.st_info) != STT_FILE)
78 continue;
80 file = (const char *)((uintptr_t)strdata->d_buf + sym.st_name);
81 len = strlen(file);
82 if (len < 2 || file[len - 2] != '.') {
83 *types |= CTFCONV_SOURCE_UNKNOWN;
84 continue;
87 switch (file[len - 1]) {
88 case 'c':
89 *types |= CTFCONV_SOURCE_C;
90 break;
91 case 'h':
92 /* We traditionally ignore header files... */
93 break;
94 case 's':
95 *types |= CTFCONV_SOURCE_S;
96 break;
97 default:
98 *types |= CTFCONV_SOURCE_UNKNOWN;
99 break;
104 ctf_file_t *
105 ctf_elfconvert(int fd, Elf *elf, const char *label, uint_t nthrs, uint_t flags,
106 int *errp, char *errbuf, size_t errlen)
108 int err, i;
109 ctf_file_t *fp = NULL;
110 boolean_t notsup = B_TRUE;
111 ctf_convert_source_t type;
113 if (errp == NULL)
114 errp = &err;
116 if (elf == NULL) {
117 *errp = EINVAL;
118 return (NULL);
121 if (flags & ~CTF_CONVERT_F_IGNNONC) {
122 *errp = EINVAL;
123 return (NULL);
126 if (elf_kind(elf) != ELF_K_ELF) {
127 *errp = ECTF_FMT;
128 return (NULL);
131 ctf_convert_ftypes(elf, &type);
132 ctf_dprintf("got types: %d\n", type);
133 if (flags & CTF_CONVERT_F_IGNNONC) {
134 if (type == CTFCONV_SOURCE_NONE ||
135 (type & CTFCONV_SOURCE_UNKNOWN)) {
136 *errp = ECTF_CONVNOCSRC;
137 return (NULL);
141 for (i = 0; i < NCONVERTS; i++) {
142 ctf_conv_status_t cs;
144 fp = NULL;
145 cs = ctf_converters[i](fd, elf, nthrs, errp, &fp, errbuf,
146 errlen);
147 if (cs == CTF_CONV_SUCCESS) {
148 notsup = B_FALSE;
149 break;
151 if (cs == CTF_CONV_ERROR) {
152 fp = NULL;
153 notsup = B_FALSE;
154 break;
158 if (notsup == B_TRUE) {
159 if ((flags & CTF_CONVERT_F_IGNNONC) != 0 &&
160 (type & CTFCONV_SOURCE_C) == 0) {
161 *errp = ECTF_CONVNOCSRC;
162 return (NULL);
164 *errp = ECTF_NOCONVBKEND;
165 return (NULL);
169 * Succsesful conversion.
171 if (fp != NULL) {
172 if (label == NULL)
173 label = "";
174 if (ctf_add_label(fp, label, fp->ctf_typemax, 0) == CTF_ERR) {
175 *errp = ctf_errno(fp);
176 ctf_close(fp);
177 return (NULL);
179 if (ctf_update(fp) == CTF_ERR) {
180 *errp = ctf_errno(fp);
181 ctf_close(fp);
182 return (NULL);
186 return (fp);
189 ctf_file_t *
190 ctf_fdconvert(int fd, const char *label, uint_t nthrs, uint_t flags, int *errp,
191 char *errbuf, size_t errlen)
193 int err;
194 Elf *elf;
195 ctf_file_t *fp;
197 if (errp == NULL)
198 errp = &err;
200 elf = elf_begin(fd, ELF_C_READ, NULL);
201 if (elf == NULL) {
202 *errp = ECTF_FMT;
203 return (NULL);
206 fp = ctf_elfconvert(fd, elf, label, nthrs, flags, errp, errbuf, errlen);
208 (void) elf_end(elf);
209 return (fp);