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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Routines used to read stabs data from a file, and to build a tdata structure 30 * based on the interesting parts of that data. 31 */ 32 33 #if HAVE_NBTOOL_CONFIG_H 34 # include "nbtool_config.h" 35 #endif 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <fcntl.h> 40 #include <unistd.h> 41 #include <assert.h> 42 #include <string.h> 43 #include <libgen.h> 44 #include <errno.h> 45 #include <sys/types.h> 46 #include <sys/param.h> 47 48 #include "ctftools.h" 49 #include "list.h" 50 #include "stack.h" 51 #include "memory.h" 52 #include "traverse.h" 53 54 char *curhdr; 55 56 /* 57 * The stabs generator will sometimes reference types before they've been 58 * defined. If this is the case, a TYPEDEF_UNRES tdesc will be generated. 59 * Note that this is different from a forward declaration, in which the 60 * stab is defined, but is defined as something that doesn't exist yet. 61 * When we have read all of the stabs from the file, we can go back and 62 * fix up all of the unresolved types. We should be able to fix all of them. 63 */ 64 /*ARGSUSED2*/ 65 static int 66 resolve_tou_node(tdesc_t *node, tdesc_t **nodep, void *private __unused) 67 { 68 tdesc_t *new; 69 70 debug(3, "Trying to resolve %s (%d)\n", tdesc_name(node), node->t_id); 71 new = lookup(node->t_id); 72 73 if (new == NULL) { 74 terminate("Couldn't resolve type %d\n", node->t_id); 75 } 76 77 debug(3, " Resolving to %d\n", new->t_id); 78 79 *nodep = new; 80 81 return (1); 82 } 83 84 /*ARGSUSED*/ 85 static int 86 resolve_fwd_node(tdesc_t *node, tdesc_t **nodep, void *private __unused) 87 { 88 tdesc_t *new = lookupname(node->t_name); 89 90 debug(3, "Trying to unforward %s (%d)\n", tdesc_name(node), node->t_id); 91 92 if (!new || (new->t_type != STRUCT && new->t_type != UNION)) 93 return (0); 94 95 debug(3, " Unforwarded to %d\n", new->t_id); 96 97 *nodep = new; 98 99 return (1); 100 } 101 102 static tdtrav_cb_f resolve_cbs[] = { 103 NULL, 104 NULL, /* intrinsic */ 105 NULL, /* pointer */ 106 NULL, /* array */ 107 NULL, /* function */ 108 NULL, /* struct */ 109 NULL, /* union */ 110 NULL, /* enum */ 111 resolve_fwd_node, /* forward */ 112 NULL, /* typedef */ 113 resolve_tou_node, /* typedef unres */ 114 NULL, /* volatile */ 115 NULL, /* const */ 116 NULL, /* restrict */ 117 }; 118 119 static void 120 resolve_nodes(tdata_t *td) 121 { 122 debug(2, "Resolving unresolved stabs\n"); 123 124 (void) iitraverse_hash(td->td_iihash, &td->td_curvgen, resolve_cbs, 125 NULL, NULL, td); 126 } 127 128 static char * 129 concat(char *s1, char *s2, int s2strip) 130 { 131 int savelen = strlen(s2) - s2strip; 132 int newlen = (s1 ? strlen(s1) : 0) + savelen + 1; 133 char *out; 134 135 out = xrealloc(s1, newlen); 136 if (s1) 137 strncpy(out + strlen(out), s2, savelen); 138 else 139 strncpy(out, s2, savelen); 140 141 out[newlen - 1] = '\0'; 142 143 return (out); 144 } 145 146 /* 147 * N_FUN stabs come with their arguments in promoted form. In order to get the 148 * actual arguments, we need to wait for the N_PSYM stabs that will come towards 149 * the end of the function. These routines free the arguments (fnarg_free) we 150 * got from the N_FUN stab and add (fnarg_add) the ones from the N_PSYM stabs. 151 */ 152 static void 153 fnarg_add(iidesc_t *curfun, iidesc_t *arg) 154 { 155 curfun->ii_nargs++; 156 157 if (curfun->ii_nargs == 1) 158 curfun->ii_args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF); 159 else if (curfun->ii_nargs > FUNCARG_DEF) { 160 curfun->ii_args = xrealloc(curfun->ii_args, 161 sizeof (tdesc_t *) * curfun->ii_nargs); 162 } 163 164 curfun->ii_args[curfun->ii_nargs - 1] = arg->ii_dtype; 165 arg->ii_dtype = NULL; 166 } 167 168 static void 169 fnarg_free(iidesc_t *ii) 170 { 171 ii->ii_nargs = 0; 172 free(ii->ii_args); 173 ii->ii_args = NULL; 174 } 175 176 /* 177 * Read the stabs from the stab ELF section, and turn them into a tdesc tree, 178 * assembled under an iidesc list. 179 */ 180 int 181 stabs_read(tdata_t *td, Elf *elf, char *file) 182 { 183 Elf_Scn *scn; 184 Elf_Data *data; 185 stab_t *stab; 186 stk_t *file_stack; 187 iidesc_t *iidescp; 188 iidesc_t *curfun = NULL; 189 char curpath[MAXPATHLEN]; 190 char *curfile = NULL; 191 char *str; 192 char *fstr = NULL, *ofstr = NULL; 193 int stabidx, stabstridx; 194 int nstabs, rc, i; 195 int scope = 0; 196 197 if (!((stabidx = findelfsecidx(elf, file, ".stab.excl")) >= 0 && 198 (stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) && 199 !((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 && 200 (stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) { 201 errno = ENOENT; 202 return (-1); 203 } 204 205 file_stack = stack_new(free); 206 207 stack_push(file_stack, file); 208 curhdr = file; 209 210 debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx); 211 212 scn = elf_getscn(elf, stabidx); 213 data = elf_rawdata(scn, NULL); 214 nstabs = data->d_size / sizeof (stab_t); 215 216 parse_init(td); 217 for (i = 0; i < nstabs; i++) { 218 stab = &((stab_t *)data->d_buf)[i]; 219 220 /* We don't want any local definitions */ 221 if (stab->n_type == N_LBRAC) { 222 scope++; 223 debug(3, "stab %d: opening scope (%d)\n", i + 1, scope); 224 continue; 225 } else if (stab->n_type == N_RBRAC) { 226 scope--; 227 debug(3, "stab %d: closing scope (%d)\n", i + 1, scope); 228 continue; 229 } else if (stab->n_type == N_EINCL) { 230 /* 231 * There's a bug in the 5.2 (Taz) compilers that causes 232 * them to emit an extra N_EINCL if there's no actual 233 * text in the file being compiled. To work around this 234 * bug, we explicitly check to make sure we're not 235 * trying to pop a stack that only has the outer scope 236 * on it. 237 */ 238 if (stack_level(file_stack) != 1) { 239 str = (char *)stack_pop(file_stack); 240 free(str); 241 curhdr = (char *)stack_peek(file_stack); 242 } 243 } 244 245 /* We only care about a subset of the stabs */ 246 if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM || 247 stab->n_type == N_LCSYM || stab->n_type == N_LSYM || 248 stab->n_type == N_PSYM || stab->n_type == N_ROSYM || 249 stab->n_type == N_RSYM || 250 stab->n_type == N_STSYM || stab->n_type == N_BINCL || 251 stab->n_type == N_SO || stab->n_type == N_OPT)) 252 continue; 253 254 if ((str = elf_strptr(elf, stabstridx, 255 (size_t)stab->n_strx)) == NULL) { 256 terminate("%s: Can't find string at %u for stab %d\n", 257 file, stab->n_strx, i); 258 } 259 260 if (stab->n_type == N_BINCL) { 261 curhdr = xstrdup(str); 262 stack_push(file_stack, curhdr); 263 continue; 264 } else if (stab->n_type == N_SO) { 265 if (str[strlen(str) - 1] != '/') { 266 strcpy(curpath, str); 267 curfile = basename(curpath); 268 } 269 continue; 270 } else if (stab->n_type == N_OPT) { 271 if (strcmp(str, "gcc2_compiled.") == 0) { 272 terminate("%s: GCC-generated stabs are " 273 "unsupported. Use DWARF instead.\n", file); 274 } 275 continue; 276 } 277 278 if (str[strlen(str) - 1] == '\\') { 279 int offset = 1; 280 /* 281 * There's a bug in the compilers that causes them to 282 * generate \ for continuations with just -g (this is 283 * ok), and \\ for continuations with -g -O (this is 284 * broken). This bug is "fixed" in the 6.2 compilers 285 * via the elimination of continuation stabs. 286 */ 287 if (str[strlen(str) - 2] == '\\') 288 offset = 2; 289 fstr = concat(fstr, str, offset); 290 continue; 291 } else 292 fstr = concat(fstr, str, 0); 293 294 debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i, 295 fstr, stab->n_type, 0, stab->n_desc, 296 stab->n_value, curhdr); 297 298 if (debug_level >= 3) 299 check_hash(); 300 301 /* 302 * Sometimes the compiler stutters, and emits the same stab 303 * twice. This is bad for the parser, which will attempt to 304 * redefine the type IDs indicated in the stabs. This is 305 * compiler bug 4433511. 306 */ 307 if (ofstr && strcmp(fstr, ofstr) == 0) { 308 debug(3, "Stutter stab\n"); 309 free(fstr); 310 fstr = NULL; 311 continue; 312 } 313 314 if (ofstr) 315 free(ofstr); 316 ofstr = fstr; 317 318 iidescp = NULL; 319 320 if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) { 321 terminate("%s: Couldn't parse stab \"%s\" " 322 "(source file %s)\n", file, str, curhdr); 323 } 324 325 if (rc == 0) 326 goto parse_loop_end; 327 328 /* Make sure the scope tracking is working correctly */ 329 assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN && 330 iidescp->ii_type != II_SFUN) || scope == 0); 331 332 /* 333 * The only things we care about that are in local scope are 334 * the N_PSYM stabs. 335 */ 336 if (scope && stab->n_type != N_PSYM) { 337 if (iidescp) 338 iidesc_free(iidescp, NULL); 339 goto parse_loop_end; 340 } 341 342 switch (iidescp->ii_type) { 343 case II_SFUN: 344 iidescp->ii_owner = xstrdup(curfile); 345 /*FALLTHROUGH*/ 346 case II_GFUN: 347 curfun = iidescp; 348 fnarg_free(iidescp); 349 iidesc_add(td->td_iihash, iidescp); 350 break; 351 352 case II_SVAR: 353 iidescp->ii_owner = xstrdup(curfile); 354 /*FALLTHROUGH*/ 355 case II_GVAR: 356 case II_TYPE: 357 case II_SOU: 358 iidesc_add(td->td_iihash, iidescp); 359 break; 360 361 case II_PSYM: 362 fnarg_add(curfun, iidescp); 363 iidesc_free(iidescp, NULL); 364 break; 365 default: 366 aborterr("invalid ii_type %d for stab type %d", 367 iidescp->ii_type, stab->n_type); 368 } 369 370 parse_loop_end: 371 fstr = NULL; 372 } 373 374 if (ofstr) 375 free(ofstr); 376 377 resolve_nodes(td); 378 resolve_typed_bitfields(); 379 parse_finish(td); 380 381 cvt_fixstabs(td); 382 cvt_fixups(td, elf_ptrsz(elf)); 383 384 return (0); 385 } 386