1 /* 2 * Dwarf info parse and search. 3 */ 4 5 #include <ntifs.h> 6 #include <ndk/ntndk.h> 7 #include <reactos/rossym.h> 8 #include "rossympriv.h" 9 #include <ntimage.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 #include "dwarf.h" 15 #include <windef.h> 16 17 enum 18 { 19 DwarfAttrSibling = 0x01, 20 DwarfAttrLocation = 0x02, 21 DwarfAttrName = 0x03, 22 DwarfAttrOrdering = 0x09, 23 DwarfAttrByteSize = 0x0B, 24 DwarfAttrBitOffset = 0x0C, 25 DwarfAttrBitSize = 0x0D, 26 DwarfAttrStmtList = 0x10, 27 DwarfAttrLowpc = 0x11, 28 DwarfAttrHighpc = 0x12, 29 DwarfAttrLanguage = 0x13, 30 DwarfAttrDiscr = 0x15, 31 DwarfAttrDiscrValue = 0x16, 32 DwarfAttrVisibility = 0x17, 33 DwarfAttrImport = 0x18, 34 DwarfAttrStringLength = 0x19, 35 DwarfAttrCommonRef = 0x1A, 36 DwarfAttrCompDir = 0x1B, 37 DwarfAttrConstValue = 0x1C, 38 DwarfAttrContainingType = 0x1D, 39 DwarfAttrDefaultValue = 0x1E, 40 DwarfAttrInline = 0x20, 41 DwarfAttrIsOptional = 0x21, 42 DwarfAttrLowerBound = 0x22, 43 DwarfAttrProducer = 0x25, 44 DwarfAttrPrototyped = 0x27, 45 DwarfAttrReturnAddr = 0x2A, 46 DwarfAttrStartScope = 0x2C, 47 DwarfAttrStrideSize = 0x2E, 48 DwarfAttrUpperBound = 0x2F, 49 DwarfAttrAbstractOrigin = 0x31, 50 DwarfAttrAccessibility = 0x32, 51 DwarfAttrAddrClass = 0x33, 52 DwarfAttrArtificial = 0x34, 53 DwarfAttrBaseTypes = 0x35, 54 DwarfAttrCalling = 0x36, 55 DwarfAttrCount = 0x37, 56 DwarfAttrDataMemberLoc = 0x38, 57 DwarfAttrDeclColumn = 0x39, 58 DwarfAttrDeclFile = 0x3A, 59 DwarfAttrDeclLine = 0x3B, 60 DwarfAttrDeclaration = 0x3C, 61 DwarfAttrDiscrList = 0x3D, 62 DwarfAttrEncoding = 0x3E, 63 DwarfAttrExternal = 0x3F, 64 DwarfAttrFrameBase = 0x40, 65 DwarfAttrFriend = 0x41, 66 DwarfAttrIdentifierCase = 0x42, 67 DwarfAttrMacroInfo = 0x43, 68 DwarfAttrNamelistItem = 0x44, 69 DwarfAttrPriority = 0x45, 70 DwarfAttrSegment = 0x46, 71 DwarfAttrSpecification = 0x47, 72 DwarfAttrStaticLink = 0x48, 73 DwarfAttrType = 0x49, 74 DwarfAttrUseLocation = 0x4A, 75 DwarfAttrVarParam = 0x4B, 76 DwarfAttrVirtuality = 0x4C, 77 DwarfAttrVtableElemLoc = 0x4D, 78 DwarfAttrAllocated = 0x4E, 79 DwarfAttrAssociated = 0x4F, 80 DwarfAttrDataLocation = 0x50, 81 DwarfAttrStride = 0x51, 82 DwarfAttrEntrypc = 0x52, 83 DwarfAttrUseUTF8 = 0x53, 84 DwarfAttrExtension = 0x54, 85 DwarfAttrRanges = 0x55, 86 DwarfAttrTrampoline = 0x56, 87 DwarfAttrCallColumn = 0x57, 88 DwarfAttrCallFile = 0x58, 89 DwarfAttrCallLine = 0x59, 90 DwarfAttrDescription = 0x5A, 91 DwarfAttrMax, 92 93 FormAddr = 0x01, 94 FormDwarfBlock2 = 0x03, 95 FormDwarfBlock4 = 0x04, 96 FormData2 = 0x05, 97 FormData4 = 0x06, 98 FormData8 = 0x07, 99 FormString = 0x08, 100 FormDwarfBlock = 0x09, 101 FormDwarfBlock1 = 0x0A, 102 FormData1 = 0x0B, 103 FormFlag = 0x0C, 104 FormSdata = 0x0D, 105 FormStrp = 0x0E, 106 FormUdata = 0x0F, 107 FormRefAddr = 0x10, 108 FormRef1 = 0x11, 109 FormRef2 = 0x12, 110 FormRef4 = 0x13, 111 FormRef8 = 0x14, 112 FormRefUdata = 0x15, 113 FormIndirect = 0x16 114 }; 115 116 static int parseattrs(DwarfBuf*, ulong, DwarfAbbrev*, DwarfAttrs*); 117 static int getulong(DwarfBuf*, int, ulong, ulong*, int*); 118 static int getuchar(DwarfBuf*, int, uchar*); 119 static int getstring(DwarfBuf*, int, char**); 120 static int getblock(DwarfBuf*, int, DwarfBlock*); 121 static int skipform(DwarfBuf*, int); 122 static int constblock(Dwarf*, DwarfBlock*, ulong*); 123 124 int 125 dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s) 126 { 127 if(dwarfenumunit(d, unit, s) < 0) 128 return -1; 129 130 dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */ 131 while(dwarfnextsymat(d, s, 1) == 1) 132 if(s->attrs.name && strcmp(s->attrs.name, name) == 0) 133 return 0; 134 werrstr("symbol '%s' not found", name); 135 return -1; 136 } 137 138 139 int 140 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s) 141 { 142 *s = *parent; 143 while(dwarfnextsymat(d, s, parent->depth+1)) 144 if(s->attrs.name && strcmp(s->attrs.name, name) == 0) 145 return 0; 146 werrstr("symbol '%s' not found", name); 147 return -1; 148 } 149 150 int 151 dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s) 152 { 153 if(dwarfenumunit(d, unit, s) < 0) { 154 return -1; 155 } 156 157 dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */ 158 if(s->attrs.tag == tag) { 159 return 0; 160 } 161 while(dwarfnextsymat(d, s, 1) == 1) 162 if(s->attrs.tag == tag) { 163 return 0; 164 } 165 werrstr("symbol with tag 0x%lux not found", tag); 166 return -1; 167 } 168 169 int 170 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s) 171 { 172 if(dwarfenumunit(d, unit, s) < 0) 173 return -1; 174 s->b.p = d->info.data + unit + off; 175 if(dwarfnextsymat(d, s, 0) != 1) 176 return -1; 177 return 0; 178 } 179 180 int 181 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s) 182 { 183 if(dwarfenumunit(d, unit, s) < 0) 184 return -1; 185 186 if(dwarfnextsymat(d, s, 0) != 1) 187 return -1; 188 /* s is now the CompileUnit */ 189 190 while(dwarfnextsymat(d, s, 1) == 1){ 191 if(s->attrs.tag != TagSubprogram) 192 continue; 193 if(s->attrs.lowpc <= pc && pc < s->attrs.highpc) 194 return 0; 195 } 196 werrstr("fn containing pc 0x%lux not found", pc); 197 return -1; 198 } 199 200 int 201 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s) 202 { 203 int i; 204 ulong aoff, len; 205 206 if(unit >= d->info.len){ 207 werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len); 208 return -1; 209 } 210 memset(s, 0, sizeof *s); 211 memset(&s->b, 0, sizeof s->b); 212 213 s->b.d = d; 214 s->b.p = d->info.data + unit; 215 s->b.ep = d->info.data + d->info.len; 216 len = dwarfget4(&s->b); 217 s->nextunit = unit + 4 + len; 218 219 if(s->b.ep - s->b.p < len){ 220 badheader: 221 werrstr("bad dwarf unit header at unit 0x%lux", unit); 222 return -1; 223 } 224 s->b.ep = s->b.p+len; 225 if((i=dwarfget2(&s->b)) != 2) 226 goto badheader; 227 aoff = dwarfget4(&s->b); 228 s->b.addrsize = dwarfget1(&s->b); 229 if(d->addrsize == 0) 230 d->addrsize = s->b.addrsize; 231 if(s->b.p == nil) 232 goto badheader; 233 234 s->aoff = aoff; 235 s->unit = unit; 236 s->depth = 0; 237 return 0; 238 } 239 240 int 241 dwarfenum(Dwarf *d, DwarfSym *s) 242 { 243 if(dwarfenumunit(d, 0, s) < 0) 244 return -1; 245 s->allunits = 1; 246 return 0; 247 } 248 249 int 250 dwarfnextsym(Dwarf *d, DwarfSym *s) 251 { 252 ulong num; 253 DwarfAbbrev *a; 254 255 if(s->attrs.haskids) 256 s->depth++; 257 top: 258 if(s->b.p >= s->b.ep){ 259 if(s->allunits && s->nextunit < d->info.len){ 260 if(dwarfenumunit(d, s->nextunit, s) < 0) { 261 return -1; 262 } 263 s->allunits = 1; 264 goto top; 265 } 266 return 0; 267 } 268 269 s->uoff = s->b.p - (d->info.data+s->unit); 270 num = dwarfget128(&s->b); 271 if(num == 0){ 272 if(s->depth == 0) { 273 return 0; 274 } 275 if(s->depth > 0) 276 s->depth--; 277 goto top; 278 } 279 280 a = dwarfgetabbrev(d, s->aoff, num); 281 if(a == nil){ 282 werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff); 283 return -1; 284 } 285 if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) { 286 return -1; 287 } 288 return 1; 289 } 290 291 int 292 dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth) 293 { 294 int r; 295 DwarfSym t; 296 uint sib; 297 298 if(s->depth == depth && s->attrs.have.sibling){ 299 sib = s->attrs.sibling; 300 if(sib < d->info.len && d->info.data+sib >= s->b.p) 301 s->b.p = d->info.data+sib; 302 s->attrs.haskids = 0; 303 } 304 305 /* 306 * The funny game with t and s make sure that 307 * if we get to the end of a run of a particular 308 * depth, we leave s so that a call to nextsymat with depth-1 309 * will actually produce the desired guy. We could change 310 * the interface to dwarfnextsym instead, but I'm scared 311 * to touch it. 312 */ 313 t = *s; 314 for(;;){ 315 if((r = dwarfnextsym(d, &t)) != 1) { 316 return r; 317 } 318 if(t.depth < depth){ 319 /* went too far - nothing to see */ 320 return 0; 321 } 322 *s = t; 323 if(t.depth == depth) { 324 return 1; 325 } 326 } 327 } 328 329 typedef struct Parse Parse; 330 struct Parse { 331 int name; 332 int off; 333 int haveoff; 334 int type; 335 }; 336 337 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x) 338 339 static Parse plist[] = { /* Font Tab 4 */ 340 { DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference }, 341 { DwarfAttrAccessibility, OFFSET(accessibility), TConstant }, 342 { DwarfAttrAddrClass, OFFSET(addrclass), TConstant }, 343 { DwarfAttrArtificial, OFFSET(isartificial), TFlag }, 344 { DwarfAttrBaseTypes, OFFSET(basetypes), TReference }, 345 { DwarfAttrBitOffset, OFFSET(bitoffset), TConstant }, 346 { DwarfAttrBitSize, OFFSET(bitsize), TConstant }, 347 { DwarfAttrByteSize, OFFSET(bytesize), TConstant }, 348 { DwarfAttrCalling, OFFSET(calling), TConstant }, 349 { DwarfAttrCommonRef, OFFSET(commonref), TReference }, 350 { DwarfAttrCompDir, OFFSET(compdir), TString }, 351 { DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock }, 352 { DwarfAttrContainingType, OFFSET(containingtype), TReference }, 353 { DwarfAttrCount, OFFSET(count), TConstant|TReference }, 354 { DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference }, 355 { DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant }, 356 { DwarfAttrDeclFile, OFFSET(declfile), TConstant }, 357 { DwarfAttrDeclLine, OFFSET(declline), TConstant }, 358 { DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag }, 359 { DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference }, 360 { DwarfAttrDiscr, OFFSET(discr), TReference }, 361 { DwarfAttrDiscrList, OFFSET(discrlist), TBlock }, 362 { DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant }, 363 { DwarfAttrEncoding, OFFSET(encoding), TConstant }, 364 { DwarfAttrExternal, OFFSET(isexternal), TFlag }, 365 { DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant }, 366 { DwarfAttrFriend, OFFSET(friend), TReference }, 367 { DwarfAttrHighpc, OFFSET(highpc), TAddress }, 368 { DwarfAttrEntrypc, OFFSET(entrypc), TAddress }, 369 { DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant }, 370 { DwarfAttrImport, OFFSET(import), TReference }, 371 { DwarfAttrInline, OFFSET(inlined), TConstant }, 372 { DwarfAttrIsOptional, OFFSET(isoptional), TFlag }, 373 { DwarfAttrLanguage, OFFSET(language), TConstant }, 374 { DwarfAttrLocation, OFFSET(location), TBlock|TConstant }, 375 { DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference }, 376 { DwarfAttrLowpc, OFFSET(lowpc), TAddress }, 377 { DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant }, 378 { DwarfAttrName, OFFSET(name), TString }, 379 { DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock }, 380 { DwarfAttrOrdering, OFFSET(ordering), TConstant }, 381 { DwarfAttrPriority, OFFSET(priority), TReference }, 382 { DwarfAttrProducer, OFFSET(producer), TString }, 383 { DwarfAttrPrototyped, OFFSET(isprototyped), TFlag }, 384 { DwarfAttrRanges, OFFSET(ranges), TReference }, 385 { DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant }, 386 { DwarfAttrSegment, OFFSET(segment), TBlock|TConstant }, 387 { DwarfAttrSibling, OFFSET(sibling), TReference }, 388 { DwarfAttrSpecification, OFFSET(specification), TReference }, 389 { DwarfAttrStartScope, OFFSET(startscope), TConstant }, 390 { DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant }, 391 { DwarfAttrStmtList, OFFSET(stmtlist), TConstant }, 392 { DwarfAttrStrideSize, OFFSET(stridesize), TConstant }, 393 { DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant }, 394 { DwarfAttrType, OFFSET(type), TReference }, 395 { DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference }, 396 { DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant }, 397 { DwarfAttrVarParam, OFFSET(isvarparam), TFlag }, 398 { DwarfAttrVirtuality, OFFSET(virtuality), TConstant }, 399 { DwarfAttrVisibility, OFFSET(visibility), TConstant }, 400 { DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference }, 401 { } 402 }; 403 404 static Parse ptab[DwarfAttrMax]; 405 406 static int 407 parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs) 408 { 409 int i, f, n, got; 410 static int nbad; 411 void *v; 412 413 /* initialize ptab first time through for quick access */ 414 if(ptab[DwarfAttrName].name != DwarfAttrName) 415 for(i=0; plist[i].name; i++) 416 ptab[plist[i].name] = plist[i]; 417 418 memset(attrs, 0, sizeof *attrs); 419 attrs->tag = a->tag; 420 attrs->haskids = a->haskids; 421 422 for(i=0; i<a->nattr; i++){ 423 n = a->attr[i].name; 424 f = a->attr[i].form; 425 if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){ 426 if(++nbad == 1) 427 werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n); 428 continue; //return -1; 429 } 430 v = (char*)attrs + ptab[n].off; 431 got = 0; 432 if(f == FormIndirect) 433 f = dwarfget128(b); 434 if((ptab[n].type&(TConstant|TReference|TAddress)) 435 && getulong(b, f, unit, v, &got) >= 0) 436 ; 437 else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0) 438 got = TFlag; 439 else if((ptab[n].type&TString) && getstring(b, f, v) >= 0) 440 got = TString; 441 else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0) 442 got = TBlock; 443 else{ 444 if(skipform(b, f) < 0){ 445 if(++nbad == 1) 446 werrstr("dwarf parse attrs: cannot skip form %d", f); 447 return -1; 448 } 449 } 450 if(got == TBlock && (ptab[n].type&TConstant)) 451 got = constblock(b->d, v, v); 452 *((uchar*)attrs+ptab[n].haveoff) = got; 453 } 454 return 0; 455 } 456 457 static int 458 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type) 459 { 460 static int nbad; 461 uvlong uv; 462 463 switch(form){ 464 default: 465 return -1; 466 467 /* addresses */ 468 case FormAddr: 469 *type = TAddress; 470 *u = dwarfgetaddr(b); 471 return 0; 472 473 /* references */ 474 case FormRefAddr: 475 /* absolute ref in .debug_info */ 476 *type = TReference; 477 *u = dwarfgetaddr(b); 478 return 0; 479 case FormRef1: 480 *u = dwarfget1(b); 481 goto relativeref; 482 case FormRef2: 483 *u = dwarfget2(b); 484 goto relativeref; 485 case FormRef4: 486 *u = dwarfget4(b); 487 goto relativeref; 488 case FormRef8: 489 *u = dwarfget8(b); 490 goto relativeref; 491 case FormRefUdata: 492 *u = dwarfget128(b); 493 relativeref: 494 *u += unit; 495 *type = TReference; 496 return 0; 497 498 /* constants */ 499 case FormData1: 500 *u = dwarfget1(b); 501 goto constant; 502 case FormData2: 503 *u = dwarfget2(b); 504 goto constant; 505 case FormData4: 506 *u = dwarfget4(b); 507 goto constant; 508 case FormData8: 509 uv = dwarfget8(b); 510 *u = uv; 511 if(uv != *u && ++nbad == 1) 512 werrstr("dwarf: truncating 64-bit attribute constants"); 513 goto constant; 514 case FormSdata: 515 *u = dwarfget128s(b); 516 goto constant; 517 case FormUdata: 518 *u = dwarfget128(b); 519 constant: 520 *type = TConstant; 521 return 0; 522 } 523 } 524 525 static int 526 getuchar(DwarfBuf *b, int form, uchar *u) 527 { 528 switch(form){ 529 default: 530 return -1; 531 532 case FormFlag: 533 *u = dwarfget1(b); 534 return 0; 535 } 536 } 537 538 static int 539 getstring(DwarfBuf *b, int form, char **s) 540 { 541 static int nbad; 542 ulong u; 543 544 switch(form){ 545 default: 546 return -1; 547 548 case FormString: 549 *s = dwarfgetstring(b); 550 return 0; 551 552 case FormStrp: 553 u = dwarfget4(b); 554 if(u >= b->d->str.len){ 555 if(++nbad == 1) 556 werrstr("dwarf: bad string pointer 0x%lux in attribute", u); 557 /* don't return error - maybe can proceed */ 558 *s = nil; 559 }else 560 *s = (char*)b->d->str.data + u; 561 return 0; 562 563 } 564 } 565 566 static int 567 getblock(DwarfBuf *b, int form, DwarfBlock *bl) 568 { 569 ulong n; 570 571 switch(form){ 572 default: 573 return -1; 574 case FormDwarfBlock: 575 n = dwarfget128(b); 576 goto copyn; 577 case FormDwarfBlock1: 578 n = dwarfget1(b); 579 goto copyn; 580 case FormDwarfBlock2: 581 n = dwarfget2(b); 582 goto copyn; 583 case FormDwarfBlock4: 584 n = dwarfget4(b); 585 copyn: 586 bl->data = dwarfgetnref(b, n); 587 bl->len = n; 588 if(bl->data == nil) 589 return -1; 590 return 0; 591 } 592 } 593 594 static int 595 constblock(Dwarf *d, DwarfBlock *bl, ulong *pval) 596 { 597 DwarfBuf b; 598 599 memset(&b, 0, sizeof b); 600 b.p = bl->data; 601 b.ep = bl->data+bl->len; 602 b.d = d; 603 604 switch(dwarfget1(&b)){ 605 case OpAddr: 606 *pval = dwarfgetaddr(&b); 607 return TConstant; 608 case OpConst1u: 609 *pval = dwarfget1(&b); 610 return TConstant; 611 case OpConst1s: 612 *pval = (schar)dwarfget1(&b); 613 return TConstant; 614 case OpConst2u: 615 *pval = dwarfget2(&b); 616 return TConstant; 617 case OpConst2s: 618 *pval = (s16int)dwarfget2(&b); 619 return TConstant; 620 case OpConst4u: 621 *pval = dwarfget4(&b); 622 return TConstant; 623 case OpConst4s: 624 *pval = (s32int)dwarfget4(&b); 625 return TConstant; 626 case OpConst8u: 627 *pval = (u64int)dwarfget8(&b); 628 return TConstant; 629 case OpConst8s: 630 *pval = (s64int)dwarfget8(&b); 631 return TConstant; 632 case OpConstu: 633 *pval = dwarfget128(&b); 634 return TConstant; 635 case OpConsts: 636 *pval = dwarfget128s(&b); 637 return TConstant; 638 case OpPlusUconst: 639 *pval = dwarfget128(&b); 640 return TConstant; 641 default: 642 return TBlock; 643 } 644 } 645 646 /* last resort */ 647 static int 648 skipform(DwarfBuf *b, int form) 649 { 650 int type; 651 DwarfVal val; 652 653 if(getulong(b, form, 0, &val.c, &type) < 0 654 && getuchar(b, form, (uchar*)&val) < 0 655 && getstring(b, form, &val.s) < 0 656 && getblock(b, form, &val.b) < 0) 657 return -1; 658 return 0; 659 } 660 661