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