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