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