Print this page
10823 should ignore DW_TAG_subprogram with DW_AT_declaration tags
10824 GCC7-derived CTF can double qualifiers on arrays
10825 ctfdump -c drops last type
10826 ctfdump -c goes off the rails with a missing parent
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/common/ctf/ctf_lookup.c
+++ new/usr/src/common/ctf/ctf_lookup.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22
23 23 /*
24 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 */
27 27
28 -#pragma ident "%Z%%M% %I% %E% SMI"
28 +/*
29 + * Copyright 2019, Joyent, Inc.
30 + */
29 31
30 32 #include <sys/sysmacros.h>
31 33 #include <ctf_impl.h>
32 34
33 35 /*
34 36 * Compare the given input string and length against a table of known C storage
35 37 * qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To
36 38 * do this quickly, we use a pre-computed Perfect Hash Function similar to the
37 39 * technique originally described in the classic paper:
38 40 *
39 41 * R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple",
40 42 * Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19.
41 43 *
42 44 * For an input string S of length N, we use hash H = S[N - 1] + N - 105, which
43 45 * for the current set of qualifiers yields a unique H in the range [0 .. 20].
44 46 * The hash can be modified when the keyword set changes as necessary. We also
45 47 * store the length of each keyword and check it prior to the final strcmp().
46 48 */
47 49 static int
48 50 isqualifier(const char *s, size_t len)
49 51 {
50 52 static const struct qual {
51 53 const char *q_name;
52 54 size_t q_len;
53 55 } qhash[] = {
54 56 { "static", 6 }, { "", 0 }, { "", 0 }, { "", 0 },
55 57 { "volatile", 8 }, { "", 0 }, { "", 0 }, { "", 0 }, { "", 0 },
56 58 { "", 0 }, { "auto", 4 }, { "extern", 6 }, { "", 0 }, { "", 0 },
57 59 { "", 0 }, { "", 0 }, { "const", 5 }, { "register", 8 },
58 60 { "", 0 }, { "restrict", 8 }, { "_Restrict", 9 }
59 61 };
60 62
61 63 int h = s[len - 1] + (int)len - 105;
62 64 const struct qual *qp = &qhash[h];
63 65
64 66 return (h >= 0 && h < sizeof (qhash) / sizeof (qhash[0]) &&
65 67 len == qp->q_len && strncmp(qp->q_name, s, qp->q_len) == 0);
66 68 }
67 69
68 70 /*
69 71 * Attempt to convert the given C type name into the corresponding CTF type ID.
70 72 * It is not possible to do complete and proper conversion of type names
71 73 * without implementing a more full-fledged parser, which is necessary to
72 74 * handle things like types that are function pointers to functions that
73 75 * have arguments that are function pointers, and fun stuff like that.
74 76 * Instead, this function implements a very simple conversion algorithm that
75 77 * finds the things that we actually care about: structs, unions, enums,
76 78 * integers, floats, typedefs, and pointers to any of these named types.
77 79 */
78 80 ctf_id_t
79 81 ctf_lookup_by_name(ctf_file_t *fp, const char *name)
80 82 {
81 83 static const char delimiters[] = " \t\n\r\v\f*";
82 84
83 85 const ctf_lookup_t *lp;
84 86 const ctf_helem_t *hp;
85 87 const char *p, *q, *end;
86 88 ctf_id_t type = 0;
87 89 ctf_id_t ntype, ptype;
88 90
89 91 if (name == NULL)
90 92 return (ctf_set_errno(fp, EINVAL));
91 93
92 94 for (p = name, end = name + strlen(name); *p != '\0'; p = q) {
93 95 while (isspace(*p))
94 96 p++; /* skip leading ws */
95 97
96 98 if (p == end)
97 99 break;
98 100
99 101 if ((q = strpbrk(p + 1, delimiters)) == NULL)
100 102 q = end; /* compare until end */
101 103
102 104 if (*p == '*') {
103 105 /*
104 106 * Find a pointer to type by looking in fp->ctf_ptrtab.
105 107 * If we can't find a pointer to the given type, see if
106 108 * we can compute a pointer to the type resulting from
107 109 * resolving the type down to its base type and use
108 110 * that instead. This helps with cases where the CTF
109 111 * data includes "struct foo *" but not "foo_t *" and
110 112 * the user tries to access "foo_t *" in the debugger.
111 113 */
112 114 ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)];
113 115 if (ntype == 0) {
114 116 ntype = ctf_type_resolve(fp, type);
115 117 if (ntype == CTF_ERR || (ntype = fp->ctf_ptrtab[
116 118 CTF_TYPE_TO_INDEX(ntype)]) == 0) {
117 119 (void) ctf_set_errno(fp, ECTF_NOTYPE);
118 120 goto err;
119 121 }
120 122 }
121 123
122 124 type = CTF_INDEX_TO_TYPE(ntype,
123 125 (fp->ctf_flags & LCTF_CHILD));
124 126
125 127 q = p + 1;
126 128 continue;
127 129 }
128 130
129 131 if (isqualifier(p, (size_t)(q - p)))
130 132 continue; /* skip qualifier keyword */
131 133
132 134 for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++) {
133 135 if (lp->ctl_prefix[0] == '\0' ||
134 136 strncmp(p, lp->ctl_prefix, (size_t)(q - p)) == 0) {
135 137 for (p += lp->ctl_len; isspace(*p); p++)
136 138 continue; /* skip prefix and next ws */
137 139
138 140 if ((q = strchr(p, '*')) == NULL)
139 141 q = end; /* compare until end */
140 142
141 143 while (isspace(q[-1]))
142 144 q--; /* exclude trailing ws */
143 145
144 146 if ((hp = ctf_hash_lookup(lp->ctl_hash, fp, p,
145 147 (size_t)(q - p))) == NULL) {
146 148 (void) ctf_set_errno(fp, ECTF_NOTYPE);
147 149 goto err;
148 150 }
149 151
150 152 type = hp->h_type;
151 153 break;
152 154 }
153 155 }
154 156
155 157 if (lp->ctl_prefix == NULL) {
156 158 (void) ctf_set_errno(fp, ECTF_NOTYPE);
157 159 goto err;
158 160 }
159 161 }
160 162
161 163 if (*p != '\0' || type == 0)
162 164 return (ctf_set_errno(fp, ECTF_SYNTAX));
163 165
164 166 return (type);
165 167
166 168 err:
167 169 if (fp->ctf_parent != NULL &&
168 170 (ptype = ctf_lookup_by_name(fp->ctf_parent, name)) != CTF_ERR)
169 171 return (ptype);
170 172
171 173 return (CTF_ERR);
172 174 }
173 175
174 176 /*
175 177 * Given a symbol table index, return the type of the data object described
176 178 * by the corresponding entry in the symbol table.
177 179 */
178 180 ctf_id_t
179 181 ctf_lookup_by_symbol(ctf_file_t *fp, ulong_t symidx)
180 182 {
181 183 const ctf_sect_t *sp = &fp->ctf_symtab;
182 184 ctf_id_t type;
183 185
184 186 if (sp->cts_data == NULL)
185 187 return (ctf_set_errno(fp, ECTF_NOSYMTAB));
186 188
187 189 if (symidx >= fp->ctf_nsyms)
188 190 return (ctf_set_errno(fp, EINVAL));
189 191
190 192 if (sp->cts_entsize == sizeof (Elf32_Sym)) {
191 193 const Elf32_Sym *symp = (Elf32_Sym *)sp->cts_data + symidx;
192 194 if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT)
193 195 return (ctf_set_errno(fp, ECTF_NOTDATA));
194 196 } else {
195 197 const Elf64_Sym *symp = (Elf64_Sym *)sp->cts_data + symidx;
196 198 if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT)
197 199 return (ctf_set_errno(fp, ECTF_NOTDATA));
198 200 }
199 201
200 202 if (fp->ctf_sxlate[symidx] == -1u)
201 203 return (ctf_set_errno(fp, ECTF_NOTYPEDAT));
202 204
203 205 type = *(ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
204 206 if (type == 0)
205 207 return (ctf_set_errno(fp, ECTF_NOTYPEDAT));
206 208
207 209 return (type);
208 210 }
209 211
210 212 /*
211 213 * Return the pointer to the internal CTF type data corresponding to the
212 214 * given type ID. If the ID is invalid, the function returns NULL.
213 215 * This function is not exported outside of the library.
214 216 */
215 217 const ctf_type_t *
216 218 ctf_lookup_by_id(ctf_file_t **fpp, ctf_id_t type)
217 219 {
218 220 ctf_file_t *fp = *fpp; /* caller passes in starting CTF container */
219 221
220 222 if ((fp->ctf_flags & LCTF_CHILD) && CTF_TYPE_ISPARENT(type) &&
221 223 (fp = fp->ctf_parent) == NULL) {
222 224 (void) ctf_set_errno(*fpp, ECTF_NOPARENT);
223 225 return (NULL);
224 226 }
225 227
226 228 type = CTF_TYPE_TO_INDEX(type);
227 229 if (type > 0 && type <= fp->ctf_typemax) {
228 230 *fpp = fp; /* function returns ending CTF container */
229 231 return (LCTF_INDEX_TO_TYPEPTR(fp, type));
230 232 }
231 233
232 234 (void) ctf_set_errno(fp, ECTF_BADID);
233 235 return (NULL);
234 236 }
235 237
236 238 /*
237 239 * Given a symbol table index, return the info for the function described
238 240 * by the corresponding entry in the symbol table.
239 241 */
240 242 int
241 243 ctf_func_info(ctf_file_t *fp, ulong_t symidx, ctf_funcinfo_t *fip)
242 244 {
243 245 const ctf_sect_t *sp = &fp->ctf_symtab;
244 246 const ushort_t *dp;
245 247 ushort_t info, kind, n;
246 248
247 249 if (sp->cts_data == NULL)
248 250 return (ctf_set_errno(fp, ECTF_NOSYMTAB));
249 251
250 252 if (symidx >= fp->ctf_nsyms)
251 253 return (ctf_set_errno(fp, EINVAL));
252 254
253 255 if (sp->cts_entsize == sizeof (Elf32_Sym)) {
254 256 const Elf32_Sym *symp = (Elf32_Sym *)sp->cts_data + symidx;
255 257 if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
256 258 return (ctf_set_errno(fp, ECTF_NOTFUNC));
257 259 } else {
258 260 const Elf64_Sym *symp = (Elf64_Sym *)sp->cts_data + symidx;
259 261 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
260 262 return (ctf_set_errno(fp, ECTF_NOTFUNC));
261 263 }
262 264
263 265 if (fp->ctf_sxlate[symidx] == -1u)
264 266 return (ctf_set_errno(fp, ECTF_NOFUNCDAT));
265 267
266 268 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
267 269
268 270 info = *dp++;
269 271 kind = LCTF_INFO_KIND(fp, info);
270 272 n = LCTF_INFO_VLEN(fp, info);
271 273
272 274 if (kind == CTF_K_UNKNOWN && n == 0)
273 275 return (ctf_set_errno(fp, ECTF_NOFUNCDAT));
274 276
275 277 if (kind != CTF_K_FUNCTION)
276 278 return (ctf_set_errno(fp, ECTF_CORRUPT));
277 279
278 280 fip->ctc_return = *dp++;
279 281 fip->ctc_argc = n;
280 282 fip->ctc_flags = 0;
281 283
282 284 if (n != 0 && dp[n - 1] == 0) {
283 285 fip->ctc_flags |= CTF_FUNC_VARARG;
284 286 fip->ctc_argc--;
285 287 }
286 288
287 289 return (0);
288 290 }
289 291
290 292 /*
291 293 * Given a symbol table index, return the arguments for the function described
292 294 * by the corresponding entry in the symbol table.
293 295 */
294 296 int
295 297 ctf_func_args(ctf_file_t *fp, ulong_t symidx, uint_t argc, ctf_id_t *argv)
296 298 {
297 299 const ushort_t *dp;
298 300 ctf_funcinfo_t f;
299 301
300 302 if (ctf_func_info(fp, symidx, &f) == CTF_ERR)
301 303 return (CTF_ERR); /* errno is set for us */
302 304
303 305 /*
↓ open down ↓ |
265 lines elided |
↑ open up ↑ |
304 306 * The argument data is two ushort_t's past the translation table
305 307 * offset: one for the function info, and one for the return type.
306 308 */
307 309 dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;
308 310
309 311 for (argc = MIN(argc, f.ctc_argc); argc != 0; argc--)
310 312 *argv++ = *dp++;
311 313
312 314 return (0);
313 315 }
316 +
317 +/*
318 + * Unlike the normal lookup routines, ctf_dyn_*() variants consult both the
319 + * processed CTF contents of a ctf_file_t as well as the dynamic types in the
320 + * dtdef list.
321 + */
322 +
323 +const ctf_type_t *
324 +ctf_dyn_lookup_by_id(ctf_file_t *fp, ctf_id_t id)
325 +{
326 + ctf_file_t **fpp = &fp;
327 + const ctf_type_t *t;
328 + ctf_dtdef_t *dtd;
329 +
330 + if ((t = ctf_lookup_by_id(fpp, id)) != NULL)
331 + return (t);
332 +
333 + if ((dtd = ctf_dtd_lookup(fp, id)) == NULL)
334 + return (NULL);
335 +
336 + return (&dtd->dtd_data);
337 +}
338 +
339 +int
340 +ctf_dyn_array_info(ctf_file_t *infp, ctf_id_t id, ctf_arinfo_t *arinfop)
341 +{
342 + ctf_file_t *fp = infp;
343 + const ctf_type_t *t;
344 + ctf_dtdef_t *dtd;
345 +
346 + if ((t = ctf_lookup_by_id(&fp, id)) != NULL) {
347 +
348 + if (LCTF_INFO_KIND(fp, t->ctt_info) != CTF_K_ARRAY)
349 + return (ctf_set_errno(infp, ECTF_NOTARRAY));
350 +
351 + return (ctf_array_info(fp, id, arinfop));
352 + }
353 +
354 + if ((dtd = ctf_dtd_lookup(fp, id)) == NULL)
355 + return (ctf_set_errno(infp, ENOENT));
356 +
357 + if (LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
358 + return (ctf_set_errno(infp, ECTF_NOTARRAY));
359 +
360 + bcopy(&dtd->dtd_u.dtu_arr, arinfop, sizeof (*arinfop));
361 + return (0);
362 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX