stabs.c (15296B)
1 #include <u.h> 2 #include <errno.h> 3 #include <libc.h> 4 #include <bio.h> 5 #include <mach.h> 6 #include <stabs.h> 7 #include <ctype.h> 8 #include "dat.h" 9 10 static jmp_buf kaboom; 11 12 static Type *parsename(char*, char**); 13 static Type *parseinfo(char*, char**); 14 static int parsenum(char*, int*, int*, char**); 15 static int parseattr(char*, char**, char**); 16 static Type *parsedefn(char *p, Type *t, char **pp); 17 static int parsebound(char**); 18 static vlong parsebigint(char**); 19 20 typedef struct Ftypes Ftypes; 21 struct Ftypes 22 { 23 Ftypes *down; 24 Ftypes *next; 25 char *file; 26 TypeList *list; 27 }; 28 29 Ftypes *fstack; 30 Ftypes *allftypes; 31 32 static char* 33 estrndup(char *s, int n) 34 { 35 char *t; 36 37 t = emalloc(n+1); 38 memmove(t, s, n); 39 return t; 40 } 41 42 static char* 43 mkpath(char *dir, char *name) 44 { 45 char *s; 46 if(name[0] == '/' || dir == nil) 47 return estrdup(name); 48 else{ 49 s = emalloc(strlen(dir)+strlen(name)+1); 50 strcpy(s, dir); 51 strcat(s, name); 52 return s; 53 } 54 } 55 56 static Ftypes* 57 mkftypes(char *dir, char *name) 58 { 59 Ftypes *f; 60 61 f = emalloc(sizeof(*f)); 62 f->file = mkpath(dir, name); 63 f->next = allftypes; 64 allftypes = f; 65 return f; 66 } 67 68 static Ftypes* 69 findftypes(char *dir, char *name) 70 { 71 char *s; 72 Ftypes *f, *found; 73 74 found = nil; 75 s = mkpath(dir, name); 76 for(f=allftypes; f; f=f->next) 77 if(strcmp(f->file, s) == 0) 78 found = f; 79 return found; 80 } 81 82 static void 83 oops(void) 84 { 85 longjmp(kaboom, 1); 86 } 87 88 /* find a : but skip over :: */ 89 static char* 90 findcolon(char *p) 91 { 92 while((p = strchr(p, ':')) != nil && *(p+1) == ':') 93 p += 2; 94 if(p == nil) 95 oops(); 96 return p; 97 } 98 99 static void 100 semi(char **p) 101 { 102 if(**p != ';') 103 oops(); 104 (*p)++; 105 } 106 107 static void 108 comma(char **p) 109 { 110 if(**p != ',') 111 oops(); 112 (*p)++; 113 } 114 115 static int 116 parseint(char **pp) 117 { 118 if(!isdigit((uchar)**pp)) 119 oops(); 120 return strtol(*pp, pp, 10); 121 } 122 123 /* 124 name ::= symbol_opt info 125 */ 126 static Type* 127 parsename(char *desc, char **pp) 128 { 129 if(*desc == 'c') 130 return nil; 131 132 if(isdigit((uchar)*desc) || *desc=='-' || *desc=='(') 133 return parseinfo(desc, pp); 134 if(*desc == 0) 135 oops(); 136 return parseinfo(desc+1, pp); 137 } 138 139 /* 140 info ::= num | num '=' attr* defn 141 */ 142 static Type* 143 parseinfo(char *desc, char **pp) 144 { 145 int n1, n2; 146 Type *t; 147 char *attr; 148 149 n1 = n2 = 0; 150 parsenum(desc, &n1, &n2, &desc); 151 t = typebynum(n1, n2); 152 if(*desc != '='){ 153 *pp = desc; 154 return t; 155 } 156 desc++; 157 if(fstack) 158 fstack->list = mktl(t, fstack->list); 159 while(parseattr(desc, &attr, &desc) >= 0){ 160 if(*attr == 's') 161 t->xsizeof = atoi(attr+1)/8; 162 } 163 return parsedefn(desc, t, pp); 164 } 165 166 /* 167 num ::= integer | '(' integer ',' integer ')' 168 */ 169 static int 170 parsenum(char *p, int *n1, int *n2, char **pp) 171 { 172 if(isdigit((uchar)*p)){ 173 *n1 = strtol(p, &p, 10); 174 *n2 = 0; 175 *pp = p; 176 return 0; 177 } 178 if(*p == '('){ 179 *n1 = strtol(p+1, &p, 10); 180 if(*p != ',') 181 oops(); 182 *n2 = strtol(p+1, &p, 10); 183 if(*p != ')') 184 oops(); 185 *pp = p+1; 186 return 0; 187 } 188 oops(); 189 return -1; 190 } 191 192 /* 193 attr ::= '@' text ';' 194 195 text is 196 'a' integer (alignment) 197 'p' integer (pointer class) 198 'P' (packed type) 199 's' integer (size of type in bits) 200 'S' (string instead of array of chars) 201 */ 202 static int 203 parseattr(char *p, char **text, char **pp) 204 { 205 if(*p != '@') 206 return -1; 207 *text = p+1; 208 if((p = strchr(p, ';')) == nil) 209 oops(); 210 *pp = p+1; 211 return 0; 212 } 213 214 215 typedef struct Basic Basic; 216 struct Basic 217 { 218 int size; 219 int fmt; 220 }; 221 222 static Basic baseints[] = 223 { 224 0, 0, 225 /*1*/ 4, 'd', /* int32 */ 226 /*2*/ 1, 'd', /* char8 */ 227 /*3*/ 2, 'd', /* int16 */ 228 /*4*/ 4, 'd', /* long int32 */ 229 /*5*/ 1, 'x', /* uchar8 */ 230 /*6*/ 1, 'd', /* schar8 */ 231 /*7*/ 2, 'x', /* uint16 */ 232 /*8*/ 4, 'x', /* uint32 */ 233 /*9*/ 4, 'x', /* uint32 */ 234 /*10*/ 4, 'x', /* ulong32 */ 235 /*11*/ 0, 0, /* void */ 236 /*12*/ 4, 'f', /* float */ 237 /*13*/ 8, 'f', /* double */ 238 /*14*/ 10, 'f', /* long double */ 239 /*15*/ 4, 'd', /* int32 */ 240 /*16*/ 4, 'd', /* bool32 */ 241 /*17*/ 2, 'f', /* short real */ 242 /*18*/ 4, 'f', /* real */ 243 /*19*/ 4, 'x', /* stringptr */ 244 /*20*/ 1, 'd', /* character8 */ 245 /*21*/ 1, 'x', /* logical*1 */ 246 /*22*/ 2, 'x', /* logical*2 */ 247 /*23*/ 4, 'X', /* logical*4 */ 248 /*24*/ 4, 'X', /* logical32 */ 249 /*25*/ 8, 'F', /* complex (two single) */ 250 /*26*/ 16, 'F', /* complex (two double) */ 251 /*27*/ 1, 'd', /* integer*1 */ 252 /*28*/ 2, 'd', /* integer*2 */ 253 /*29*/ 4, 'd', /* integer*4 */ 254 /*30*/ 2, 'x', /* wide char */ 255 /*31*/ 8, 'd', /* int64 */ 256 /*32*/ 8, 'x', /* uint64 */ 257 /*33*/ 8, 'x', /* logical*8 */ 258 /*34*/ 8, 'd', /* integer*8 */ 259 }; 260 261 static Basic basefloats[] = 262 { 263 0,0, 264 /*1*/ 4, 'f', /* 32-bit */ 265 /*2*/ 8, 'f', /* 64-bit */ 266 /*3*/ 8, 'F', /* complex */ 267 /*4*/ 4, 'F', /* complex16 */ 268 /*5*/ 8, 'F', /* complex32 */ 269 /*6*/ 10, 'f', /* long double */ 270 }; 271 272 /* 273 defn ::= info 274 | 'b' ('u' | 's') 'c'? width; offset; nbits; (builtin, signed/unsigned, char/not, width in bytes, offset & nbits of type) 275 | 'w' (aix wide char type, not used) 276 | 'R' fptype; bytes; (fptype 1=32-bit, 2=64-bit, 3=complex, 4=complex16, 5=complex32, 6=long double) 277 | 'g' typeinfo ';' nbits (aix floating, not used) 278 | 'c' typeinfo ';' nbits (aix complex, not used) 279 | 'b' typeinfo ';' bytes (ibm, no idea) 280 | 'B' typeinfo (volatile typref) 281 | 'd' typeinfo (file of typeref) 282 | 'k' typeinfo (const typeref) 283 | 'M' typeinfo ';' length (multiple instance type, fortran) 284 | 'S' typeinfo (set, typeref must have small number of values) 285 | '*' typeinfo (pointer to typeref) 286 | 'x' ('s'|'u'|'e') name ':' (struct, union, enum reference. name can have '::' in it) 287 | 'r' typeinfo ';' low ';' high ';' (subrange. typeref can be type being defined for base types!) 288 low and high are bounds 289 if bound is octal power of two, it's a big negative number 290 | ('a'|'P') indextypedef arraytypeinfo (array, index should be range type) 291 indextype is type definition not typeinfo (need not say typenum=) 292 P means packed array 293 | 'A' arraytypeinfo (open array (no index bounds)) 294 | 'D' dims ';' typeinfo (dims-dimensional dynamic array) 295 | 'E' dims ';' typeinfo (subarray of N-dimensional array) 296 | 'n' typeinfo ';' bytes (max length string) 297 | 'z' typeinfo ';' bytes (no idea what difference is from 'n') 298 | 'N' (pascal stringptr) 299 | 'e' (name ':' bigint ',')* ';' (enum listing) 300 | ('s'|'u') bytes (name ':' type ',' bitoffset ',' bitsize ';')* ';' (struct/union defn) 301 tag is given as name in stabs entry, with 'T' symbol 302 | 'f' typeinfo ';' (function returning type) 303 | 'f' rettypeinfo ',' paramcount ';' (typeinfo ',' (0|1) ';')* ';' 304 | 'p' paramcount ';' (typeinfo ',' (0|1) ';')* ';' 305 | 'F' rettypeinfo ',' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';' 306 | 'R' paramcount ';' (name ':' typeinfo ',' (0|1) ';')* ';' 307 (the 0 or 1 is pass-by-reference vs pass-by-value) 308 (the 0 or 1 is pass-by-reference vs pass-by-value) 309 */ 310 311 static Type* 312 parsedefn(char *p, Type *t, char **pp) 313 { 314 char c, *name; 315 int ischar, namelen, n, wid, offset, bits, sign; 316 long val; 317 Type *tt; 318 319 if(*p == '(' || isdigit((uchar)*p)){ 320 t->ty = Defer; 321 t->sub = parseinfo(p, pp); 322 return t; 323 } 324 325 switch(c = *p){ 326 case '-': /* builtin */ 327 n = strtol(p+1, &p, 10); 328 if(n >= nelem(baseints) || n < 0) 329 n = 0; 330 t->ty = Base; 331 t->xsizeof = baseints[n].size; 332 t->printfmt = baseints[n].fmt; 333 break; 334 case 'b': /* builtin */ 335 p++; 336 if(*p != 'u' && *p != 's') 337 oops(); 338 sign = (*p == 's'); 339 p++; 340 ischar = 0; 341 if(*p == 'c'){ 342 ischar = 1; 343 p++; 344 } 345 wid = parseint(&p); 346 semi(&p); 347 offset = parseint(&p); 348 semi(&p); 349 bits = parseint(&p); 350 semi(&p); 351 t->ty = Base; 352 t->xsizeof = wid; 353 if(sign == 1) 354 t->printfmt = 'd'; 355 else 356 t->printfmt = 'x'; 357 USED(bits); 358 USED(ischar); 359 break; 360 case 'R': /* fp type */ 361 n = parseint(&p); 362 semi(&p); 363 wid = parseint(&p); 364 semi(&p); 365 t->ty = Base; 366 t->xsizeof = wid; 367 if(n < 0 || n >= nelem(basefloats)) 368 n = 0; 369 t->xsizeof = basefloats[n].size; 370 t->printfmt = basefloats[n].fmt; 371 break; 372 case 'r': /* subrange */ 373 t->ty = Range; 374 t->sub = parseinfo(p+1, &p); 375 if(*(p-1) == ';' && *p != ';') 376 p--; 377 semi(&p); 378 t->lo = parsebound(&p); 379 semi(&p); 380 t->hi = parsebound(&p); 381 semi(&p); 382 break; 383 case 'B': /* volatile */ 384 case 'k': /* const */ 385 t->ty = Defer; 386 t->sub = parseinfo(p+1, &p); 387 break; 388 case '*': /* pointer */ 389 case 'A': /* open array */ 390 case '&': /* reference */ /* guess - C++? (rob) */ 391 t->ty = Pointer; 392 t->sub = parseinfo(p+1, &p); 393 break; 394 case 'a': /* array */ 395 case 'P': /* packed array */ 396 t->ty = Pointer; 397 tt = newtype(); 398 parsedefn(p+1, tt, &p); /* index type */ 399 if(*p == ';') 400 p++; 401 tt = newtype(); 402 t->sub = tt; 403 parsedefn(p, tt, &p); /* element type */ 404 break; 405 case 'e': /* enum listing */ 406 p++; 407 t->sue = 'e'; 408 t->ty = Enum; 409 while(*p != ';'){ 410 name = p; 411 p = findcolon(p)+1; 412 namelen = (p-name)-1; 413 val = parsebigint(&p); 414 comma(&p); 415 if(t->n%32 == 0){ 416 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0])); 417 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0])); 418 } 419 t->tname[t->n] = estrndup(name, namelen); 420 t->val[t->n] = val; 421 t->n++; 422 } 423 semi(&p); 424 break; 425 426 case 's': /* struct */ 427 case 'u': /* union */ 428 p++; 429 t->sue = c; 430 t->ty = Aggr; 431 n = parseint(&p); 432 while(*p != ';'){ 433 name = p; 434 p = findcolon(p)+1; 435 namelen = (p-name)-1; 436 tt = parseinfo(p, &p); 437 comma(&p); 438 offset = parseint(&p); 439 comma(&p); 440 bits = parseint(&p); 441 semi(&p); 442 if(t->n%32 == 0){ 443 t->tname = erealloc(t->tname, (t->n+32)*sizeof(t->tname[0])); 444 t->val = erealloc(t->val, (t->n+32)*sizeof(t->val[0])); 445 t->t = erealloc(t->t, (t->n+32)*sizeof(t->t[0])); 446 } 447 t->tname[t->n] = estrndup(name, namelen); 448 t->val[t->n] = offset; 449 t->t[t->n] = tt; 450 t->n++; 451 } 452 semi(&p); 453 break; 454 455 case 'x': /* struct, union, enum reference */ 456 p++; 457 t->ty = Defer; 458 if(*p != 's' && *p != 'u' && *p != 'e') 459 oops(); 460 c = *p; 461 name = p+1; 462 p = findcolon(p+1); 463 name = estrndup(name, p-name); 464 t->sub = typebysue(c, name); 465 p++; 466 break; 467 468 #if 0 /* AIX */ 469 case 'f': /* function */ 470 case 'p': /* procedure */ 471 case 'F': /* Pascal function */ 472 /* case 'R': /* Pascal procedure */ 473 /* 474 * Even though we don't use the info, we have 475 * to parse it in case it is embedded in other descriptions. 476 */ 477 t->ty = Function; 478 p++; 479 if(c == 'f' || c == 'F'){ 480 t->sub = parseinfo(p, &p); 481 if(*p != ','){ 482 if(*p == ';') 483 p++; 484 break; 485 } 486 comma(&p); 487 } 488 n = parseint(&p); /* number of params */ 489 semi(&p); 490 while(*p != ';'){ 491 if(c == 'F' || c == 'R'){ 492 name = p; /* parameter name */ 493 p = findcolon(p)+1; 494 } 495 parseinfo(p, &p); /* param type */ 496 comma(&p); 497 parseint(&p); /* bool: passed by value? */ 498 semi(&p); 499 } 500 semi(&p); 501 break; 502 #endif 503 504 case 'f': /* static function */ 505 case 'F': /* global function */ 506 t->ty = Function; 507 p++; 508 t->sub = parseinfo(p, &p); 509 break; 510 511 /* 512 * We'll never see any of this stuff. 513 * When we do, we can worry about it. 514 */ 515 case 'D': /* n-dimensional array */ 516 case 'E': /* subarray of n-dimensional array */ 517 case 'M': /* fortran multiple instance type */ 518 case 'N': /* pascal string ptr */ 519 case 'S': /* set */ 520 case 'c': /* aix complex */ 521 case 'd': /* file of */ 522 case 'g': /* aix float */ 523 case 'n': /* max length string */ 524 case 'w': /* aix wide char */ 525 case 'z': /* another max length string */ 526 default: 527 fprint(2, "unsupported type char %c (%d)\n", *p, *p); 528 oops(); 529 } 530 *pp = p; 531 return t; 532 } 533 534 /* 535 bound ::= 536 'A' offset (bound is on stack by ref at offset offset from arg list) 537 | 'T' offset (bound is on stack by val at offset offset from arg list) 538 | 'a' regnum (bound passed by reference in register) 539 | 't' regnum (bound passed by value in register) 540 | 'J' (no bound) 541 | bigint 542 */ 543 static int 544 parsebound(char **pp) 545 { 546 char *p; 547 int n; 548 549 n = 0; 550 p = *pp; 551 switch(*p){ 552 case 'A': /* bound is on stack by reference at offset n from arg list */ 553 case 'T': /* bound is on stack by value at offset n from arg list */ 554 case 'a': /* bound is passed by reference in register n */ 555 case 't': /* bound is passed by value in register n */ 556 p++; 557 parseint(&p); 558 break; 559 case 'J': /* no bound */ 560 p++; 561 break; 562 default: 563 n = parsebigint(&p); 564 break; 565 } 566 *pp = p; 567 return n; 568 } 569 570 /* 571 bigint ::= '-'? decimal 572 | 0 octal 573 | -1 574 */ 575 static vlong 576 parsebigint(char **pp) 577 { 578 char *p; 579 int n, neg; 580 581 p = *pp; 582 if(*p == '0'){ 583 errno = 0; 584 n = strtoll(p, &p, 8); 585 if(errno) 586 n = 0; 587 goto out; 588 } 589 neg = 0; 590 if(*p == '-'){ 591 neg = 1; 592 p++; 593 } 594 if(!isdigit((uchar)*p)) 595 oops(); 596 n = strtol(p, &p, 10); 597 if(neg) 598 n = -n; 599 600 out: 601 *pp = p; 602 return n; 603 } 604 605 int 606 stabs2acid(Stab *stabs, Biobuf *b) 607 { 608 volatile int fno, i; 609 char c, *desc, *p; 610 char *volatile dir, *volatile fn, *volatile name; 611 Ftypes *f; 612 Type *t, *tt; 613 StabSym sym; 614 615 dir = nil; 616 fno = 0; 617 fn = nil; 618 for(i=0; stabsym(stabs, i, &sym)>=0; i++){ 619 if(verbose) 620 print("%d %s\n", sym.type, sym.name); 621 switch(sym.type){ 622 case N_SO: 623 if(sym.name){ 624 if(sym.name[0] && sym.name[strlen(sym.name)-1] == '/') 625 dir = sym.name; 626 } 627 denumber(); 628 fstack = nil; 629 fno = 0; 630 break; 631 case N_BINCL: 632 fno++; 633 f = mkftypes(dir, sym.name); 634 f->down = fstack; 635 fstack = f; 636 break; 637 case N_EINCL: 638 if(fstack) 639 fstack = fstack->down; 640 break; 641 case N_EXCL: 642 fno++; 643 if((f = findftypes(dir, sym.name)) == nil){ 644 static int cannotprint; 645 646 if(cannotprint++ == 0) 647 fprint(2, "cannot find remembered %s\n", sym.name); 648 continue; 649 } 650 renumber(f->list, fno); 651 break; 652 case N_GSYM: 653 case N_FUN: 654 case N_PSYM: 655 case N_LSYM: 656 case N_LCSYM: 657 case N_STSYM: 658 case N_RSYM: 659 name = sym.name; 660 if(name == nil){ 661 if(sym.type==N_FUN) 662 fn = nil; 663 continue; 664 } 665 if((p = findcolon(name)) == nil) 666 continue; 667 name = estrndup(name, p-name); 668 desc = ++p; 669 c = *desc; 670 if(c == 'c'){ 671 fprint(2, "skip constant %s\n", name); 672 continue; 673 } 674 if(setjmp(kaboom)){ 675 static int cannotparse; 676 677 if(cannotparse++ == 0) 678 fprint(2, "cannot parse %s\n", name); 679 continue; 680 } 681 t = parsename(desc, &p); 682 if(t == nil) 683 continue; 684 if(*p != 0){ 685 static int extradesc; 686 687 if(extradesc++ == 0) 688 fprint(2, "extra desc '%s' in '%s'\n", p, desc); 689 } 690 /* void is defined as itself */ 691 if(t->ty==Defer && t->sub==t && strcmp(name, "void")==0){ 692 t->ty = Base; 693 t->xsizeof = 0; 694 t->printfmt = '0'; 695 } 696 if(*name==' ' && *(name+1) == 0) 697 *name = 0; 698 /* attach names to structs, unions, enums */ 699 if(c=='T' && *name && t->sue){ 700 t->suename = name; 701 if(t->name == nil) 702 t->name = name; 703 tt = typebysue(t->sue, name); 704 tt->ty = Defer; 705 tt->sub = t; 706 } 707 if(c=='t'){ 708 tt = newtype(); 709 tt->ty = Typedef; 710 tt->name = name; 711 tt->sub = t; 712 } 713 /* define base c types */ 714 if(t->ty==None || t->ty==Range){ 715 if(strcmp(name, "char") == 0){ 716 t->ty = Base; 717 t->xsizeof = 1; 718 t->printfmt = 'x'; 719 } 720 if(strcmp(name, "int") == 0){ 721 t->ty = Base; 722 t->xsizeof = 4; 723 t->printfmt = 'd'; 724 } 725 } 726 /* record declaration in list for later. */ 727 if(c != 't' && c != 'T') 728 switch(sym.type){ 729 case N_GSYM: 730 addsymx(nil, name, t); 731 break; 732 case N_FUN: 733 fn = name; 734 break; 735 case N_PSYM: 736 case N_LSYM: 737 case N_LCSYM: 738 case N_STSYM: 739 case N_RSYM: 740 addsymx(fn, name, t); 741 break; 742 } 743 break; 744 } 745 if(1) print(""); 746 } 747 748 printtypes(b); 749 dumpsyms(b); 750 freetypes(); 751 752 return 0; 753 }