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