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 debug(1, "NO stabs: .stab=%d, .stabstr=%d\n", stabidx, 202 stabstridx); 203 errno = ENOENT; 204 return (-1); 205 } 206 207 file_stack = stack_new(free); 208 209 stack_push(file_stack, file); 210 curhdr = file; 211 212 debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx); 213 214 scn = elf_getscn(elf, stabidx); 215 data = elf_rawdata(scn, NULL); 216 nstabs = data->d_size / sizeof (stab_t); 217 218 parse_init(td); 219 for (i = 0; i < nstabs; i++) { 220 stab = &((stab_t *)data->d_buf)[i]; 221 222 /* We don't want any local definitions */ 223 if (stab->n_type == N_LBRAC) { 224 scope++; 225 debug(3, "stab %d: opening scope (%d)\n", i + 1, scope); 226 continue; 227 } else if (stab->n_type == N_RBRAC) { 228 scope--; 229 debug(3, "stab %d: closing scope (%d)\n", i + 1, scope); 230 continue; 231 } else if (stab->n_type == N_EINCL) { 232 /* 233 * There's a bug in the 5.2 (Taz) compilers that causes 234 * them to emit an extra N_EINCL if there's no actual 235 * text in the file being compiled. To work around this 236 * bug, we explicitly check to make sure we're not 237 * trying to pop a stack that only has the outer scope 238 * on it. 239 */ 240 if (stack_level(file_stack) != 1) { 241 str = (char *)stack_pop(file_stack); 242 free(str); 243 curhdr = (char *)stack_peek(file_stack); 244 } 245 } 246 247 /* We only care about a subset of the stabs */ 248 if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM || 249 stab->n_type == N_LCSYM || stab->n_type == N_LSYM || 250 stab->n_type == N_PSYM || stab->n_type == N_ROSYM || 251 stab->n_type == N_RSYM || 252 stab->n_type == N_STSYM || stab->n_type == N_BINCL || 253 stab->n_type == N_SO || stab->n_type == N_OPT)) 254 continue; 255 256 if ((str = elf_strptr(elf, stabstridx, 257 (size_t)stab->n_strx)) == NULL) { 258 terminate("%s: Can't find string at %u for stab %d\n", 259 file, stab->n_strx, i); 260 } 261 262 if (stab->n_type == N_BINCL) { 263 curhdr = xstrdup(str); 264 stack_push(file_stack, curhdr); 265 continue; 266 } else if (stab->n_type == N_SO) { 267 if (str[strlen(str) - 1] != '/') { 268 strcpy(curpath, str); 269 curfile = basename(curpath); 270 } 271 continue; 272 } else if (stab->n_type == N_OPT) { 273 if (strcmp(str, "gcc2_compiled.") == 0) { 274 terminate("%s: GCC-generated stabs are " 275 "unsupported. Use DWARF instead.\n", file); 276 } 277 continue; 278 } 279 280 if (str[strlen(str) - 1] == '\\') { 281 int offset = 1; 282 /* 283 * There's a bug in the compilers that causes them to 284 * generate \ for continuations with just -g (this is 285 * ok), and \\ for continuations with -g -O (this is 286 * broken). This bug is "fixed" in the 6.2 compilers 287 * via the elimination of continuation stabs. 288 */ 289 if (str[strlen(str) - 2] == '\\') 290 offset = 2; 291 fstr = concat(fstr, str, offset); 292 continue; 293 } else 294 fstr = concat(fstr, str, 0); 295 296 debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i, 297 fstr, stab->n_type, 0, stab->n_desc, 298 stab->n_value, curhdr); 299 300 if (debug_level >= 3) 301 check_hash(); 302 303 /* 304 * Sometimes the compiler stutters, and emits the same stab 305 * twice. This is bad for the parser, which will attempt to 306 * redefine the type IDs indicated in the stabs. This is 307 * compiler bug 4433511. 308 */ 309 if (ofstr && strcmp(fstr, ofstr) == 0) { 310 debug(3, "Stutter stab\n"); 311 free(fstr); 312 fstr = NULL; 313 continue; 314 } 315 316 if (ofstr) 317 free(ofstr); 318 ofstr = fstr; 319 320 iidescp = NULL; 321 322 if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) { 323 terminate("%s: Couldn't parse stab \"%s\" " 324 "(source file %s)\n", file, str, curhdr); 325 } 326 327 if (rc == 0) 328 goto parse_loop_end; 329 330 /* Make sure the scope tracking is working correctly */ 331 assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN && 332 iidescp->ii_type != II_SFUN) || scope == 0); 333 334 /* 335 * The only things we care about that are in local scope are 336 * the N_PSYM stabs. 337 */ 338 if (scope && stab->n_type != N_PSYM) { 339 if (iidescp) 340 iidesc_free(iidescp, NULL); 341 goto parse_loop_end; 342 } 343 344 switch (iidescp->ii_type) { 345 case II_SFUN: 346 iidescp->ii_owner = xstrdup(curfile); 347 /*FALLTHROUGH*/ 348 case II_GFUN: 349 curfun = iidescp; 350 fnarg_free(iidescp); 351 iidesc_add(td->td_iihash, iidescp); 352 break; 353 354 case II_SVAR: 355 iidescp->ii_owner = xstrdup(curfile); 356 /*FALLTHROUGH*/ 357 case II_GVAR: 358 case II_TYPE: 359 case II_SOU: 360 iidesc_add(td->td_iihash, iidescp); 361 break; 362 363 case II_PSYM: 364 fnarg_add(curfun, iidescp); 365 iidesc_free(iidescp, NULL); 366 break; 367 default: 368 aborterr("invalid ii_type %d for stab type %d", 369 iidescp->ii_type, stab->n_type); 370 } 371 372 parse_loop_end: 373 fstr = NULL; 374 } 375 376 if (ofstr) 377 free(ofstr); 378 379 resolve_nodes(td); 380 resolve_typed_bitfields(); 381 parse_finish(td); 382 383 cvt_fixstabs(td); 384 cvt_fixups(td, elf_ptrsz(elf)); 385 386 return (0); 387 } 388