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