Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendwarfinfo.c
Go to the documentation of this file.
00001 /* 00002 * Dwarf info parse and search. 00003 */ 00004 00005 #include <precomp.h> 00006 #define NDEBUG 00007 #include <debug.h> 00008 00009 enum 00010 { 00011 DwarfAttrSibling = 0x01, 00012 DwarfAttrLocation = 0x02, 00013 DwarfAttrName = 0x03, 00014 DwarfAttrOrdering = 0x09, 00015 DwarfAttrByteSize = 0x0B, 00016 DwarfAttrBitOffset = 0x0C, 00017 DwarfAttrBitSize = 0x0D, 00018 DwarfAttrStmtList = 0x10, 00019 DwarfAttrLowpc = 0x11, 00020 DwarfAttrHighpc = 0x12, 00021 DwarfAttrLanguage = 0x13, 00022 DwarfAttrDiscr = 0x15, 00023 DwarfAttrDiscrValue = 0x16, 00024 DwarfAttrVisibility = 0x17, 00025 DwarfAttrImport = 0x18, 00026 DwarfAttrStringLength = 0x19, 00027 DwarfAttrCommonRef = 0x1A, 00028 DwarfAttrCompDir = 0x1B, 00029 DwarfAttrConstValue = 0x1C, 00030 DwarfAttrContainingType = 0x1D, 00031 DwarfAttrDefaultValue = 0x1E, 00032 DwarfAttrInline = 0x20, 00033 DwarfAttrIsOptional = 0x21, 00034 DwarfAttrLowerBound = 0x22, 00035 DwarfAttrProducer = 0x25, 00036 DwarfAttrPrototyped = 0x27, 00037 DwarfAttrReturnAddr = 0x2A, 00038 DwarfAttrStartScope = 0x2C, 00039 DwarfAttrStrideSize = 0x2E, 00040 DwarfAttrUpperBound = 0x2F, 00041 DwarfAttrAbstractOrigin = 0x31, 00042 DwarfAttrAccessibility = 0x32, 00043 DwarfAttrAddrClass = 0x33, 00044 DwarfAttrArtificial = 0x34, 00045 DwarfAttrBaseTypes = 0x35, 00046 DwarfAttrCalling = 0x36, 00047 DwarfAttrCount = 0x37, 00048 DwarfAttrDataMemberLoc = 0x38, 00049 DwarfAttrDeclColumn = 0x39, 00050 DwarfAttrDeclFile = 0x3A, 00051 DwarfAttrDeclLine = 0x3B, 00052 DwarfAttrDeclaration = 0x3C, 00053 DwarfAttrDiscrList = 0x3D, 00054 DwarfAttrEncoding = 0x3E, 00055 DwarfAttrExternal = 0x3F, 00056 DwarfAttrFrameBase = 0x40, 00057 DwarfAttrFriend = 0x41, 00058 DwarfAttrIdentifierCase = 0x42, 00059 DwarfAttrMacroInfo = 0x43, 00060 DwarfAttrNamelistItem = 0x44, 00061 DwarfAttrPriority = 0x45, 00062 DwarfAttrSegment = 0x46, 00063 DwarfAttrSpecification = 0x47, 00064 DwarfAttrStaticLink = 0x48, 00065 DwarfAttrType = 0x49, 00066 DwarfAttrUseLocation = 0x4A, 00067 DwarfAttrVarParam = 0x4B, 00068 DwarfAttrVirtuality = 0x4C, 00069 DwarfAttrVtableElemLoc = 0x4D, 00070 DwarfAttrAllocated = 0x4E, 00071 DwarfAttrAssociated = 0x4F, 00072 DwarfAttrDataLocation = 0x50, 00073 DwarfAttrStride = 0x51, 00074 DwarfAttrEntrypc = 0x52, 00075 DwarfAttrUseUTF8 = 0x53, 00076 DwarfAttrExtension = 0x54, 00077 DwarfAttrRanges = 0x55, 00078 DwarfAttrTrampoline = 0x56, 00079 DwarfAttrCallColumn = 0x57, 00080 DwarfAttrCallFile = 0x58, 00081 DwarfAttrCallLine = 0x59, 00082 DwarfAttrDescription = 0x5A, 00083 DwarfAttrMax, 00084 00085 FormAddr = 0x01, 00086 FormDwarfBlock2 = 0x03, 00087 FormDwarfBlock4 = 0x04, 00088 FormData2 = 0x05, 00089 FormData4 = 0x06, 00090 FormData8 = 0x07, 00091 FormString = 0x08, 00092 FormDwarfBlock = 0x09, 00093 FormDwarfBlock1 = 0x0A, 00094 FormData1 = 0x0B, 00095 FormFlag = 0x0C, 00096 FormSdata = 0x0D, 00097 FormStrp = 0x0E, 00098 FormUdata = 0x0F, 00099 FormRefAddr = 0x10, 00100 FormRef1 = 0x11, 00101 FormRef2 = 0x12, 00102 FormRef4 = 0x13, 00103 FormRef8 = 0x14, 00104 FormRefUdata = 0x15, 00105 FormIndirect = 0x16 00106 }; 00107 00108 static int parseattrs(Dwarf *d, DwarfBuf*, ulong, ulong, DwarfAbbrev*, DwarfAttrs*); 00109 static int getulong(DwarfBuf*, int, ulong, ulong*, int*); 00110 static int getuchar(DwarfBuf*, int, uchar*); 00111 static int getstring(Dwarf *d, DwarfBuf*, int, char**); 00112 static int getblock(DwarfBuf*, int, DwarfBlock*); 00113 static int skipform(Dwarf *d, DwarfBuf*, int); 00114 00115 int 00116 dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s) 00117 { 00118 DwarfSym compunit = { }; 00119 if(dwarfenumunit(d, unit, &compunit) < 0) 00120 return -1; 00121 while(dwarfnextsymat(d, &compunit, s) == 0) { 00122 werrstr("got %s looking for %s\n", s->attrs.name, name); 00123 if(s->attrs.name && strcmp(s->attrs.name, name) == 0) 00124 return 0; 00125 } 00126 werrstr("symbol '%s' not found", name); 00127 return -1; 00128 } 00129 00130 int 00131 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s) 00132 { 00133 *s = *parent; 00134 while(dwarfnextsymat(d, parent, s)) 00135 if(s->attrs.name && strcmp(s->attrs.name, name) == 0) 00136 return 0; 00137 werrstr("symbol '%s' not found", name); 00138 return -1; 00139 } 00140 00141 int 00142 dwarflookupchildtag(Dwarf *d, DwarfSym *parent, ulong tag, DwarfSym *s) 00143 { 00144 int rsym = dwarfnextsymat(d, parent, s); 00145 while (rsym == 0 && s->attrs.tag != tag) { 00146 if (s->attrs.haskids) { 00147 DwarfSym p = *s; 00148 int csym = dwarflookupchildtag(d, &p, tag, s); 00149 if (csym == 0) { 00150 return csym; 00151 } 00152 } 00153 rsym = dwarfnextsym(d, s); 00154 } 00155 return rsym; 00156 } 00157 00158 int 00159 dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s) 00160 { 00161 DwarfSym compunit = { }; 00162 if (dwarfenumunit(d, unit, &compunit) < 0) { 00163 return -1; 00164 } 00165 do { 00166 if (compunit.attrs.tag == tag) { 00167 *s = compunit; 00168 return 0; 00169 } 00170 if (dwarflookupchildtag(d, &compunit, tag, s) == 0) 00171 return 0; 00172 } while(dwarfnextsym(d, &compunit) == 0); 00173 werrstr("symbol with tag 0x%lux not found", tag); 00174 return -1; 00175 } 00176 00177 int 00178 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s) 00179 { 00180 DwarfSym compunit = { }; 00181 if(dwarfenumunit(d, unit, &compunit) < 0) 00182 return -1; 00183 werrstr("dwarfseeksym: unit %x off %x\n", unit, off); 00184 s->b.d = d; 00185 s->b.p = d->info.data + unit + off; 00186 s->b.ep = compunit.b.ep; 00187 if(dwarfnextsymat(d, &compunit, s) == -1) 00188 return -1; 00189 werrstr("dwarfseeksym: unit %x off %x, tag %x", unit, off, s->attrs.tag); 00190 return 0; 00191 } 00192 00193 int 00194 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s) 00195 { 00196 DwarfSym compunit = { }; 00197 if(dwarfenumunit(d, unit, &compunit) < 0) 00198 return -1; 00199 while(dwarfnextsymat(d, &compunit, s) == 0){ 00200 if(s->attrs.tag != TagSubprogram) 00201 continue; 00202 if(s->attrs.lowpc <= pc && pc < s->attrs.highpc) 00203 return 0; 00204 } 00205 werrstr("fn containing pc 0x%lux not found", pc); 00206 return -1; 00207 } 00208 00209 int 00210 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s) 00211 { 00212 int i; 00213 ulong aoff, len; 00214 00215 if(unit >= d->info.len){ 00216 werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len); 00217 return -1; 00218 } 00219 memset(s, 0, sizeof *s); 00220 memset(&s->b, 0, sizeof s->b); 00221 00222 s->b.d = d; 00223 s->b.p = d->info.data + unit; 00224 s->b.ep = d->info.data + d->info.len; 00225 len = dwarfget4(&s->b); 00226 s->unit = unit; 00227 s->nextunit = unit + 4 + len; 00228 s->b.ep = d->info.data + s->nextunit; 00229 00230 if(s->b.ep - s->b.p < len){ 00231 badheader: 00232 werrstr("bad dwarf unit header at unit 0x%lux end %x start %x len %x", unit, s->b.ep - d->info.data, s->b.p - d->info.data, len); 00233 return -1; 00234 } 00235 s->b.ep = s->b.p+len; 00236 if((i=dwarfget2(&s->b)) > 4) 00237 goto badheader; 00238 aoff = dwarfget4(&s->b); 00239 s->b.addrsize = dwarfget1(&s->b); 00240 if(d->addrsize == 0) 00241 d->addrsize = s->b.addrsize; 00242 if(s->b.p == nil) 00243 goto badheader; 00244 00245 s->aoff = aoff; 00246 00247 return dwarfnextsym(d, s); 00248 } 00249 00250 int 00251 dwarfnextsym(Dwarf *d, DwarfSym *s) 00252 { 00253 ulong num; 00254 DwarfAbbrev *a; 00255 00256 werrstr("sym at %x (left %x)\n", s->b.p - d->info.data, s->b.ep - s->b.p); 00257 00258 num = dwarfget128(&s->b); 00259 werrstr("abbrev num %x\n", num); 00260 s->num = num; 00261 if(num == 0){ 00262 return -1; 00263 } 00264 00265 a = dwarfgetabbrev(d, s->aoff, num); 00266 werrstr("a %p\n", a); 00267 if(a == nil){ 00268 werrstr("getabbrev %x %x for %x", s->aoff, num, s->unit); 00269 return -1; 00270 } 00271 00272 if(parseattrs(d, &s->b, s->attrs.tag, s->unit, a, &s->attrs) < 0) { 00273 return -1; 00274 } 00275 00276 if (s->attrs.haskids) { 00277 DwarfSym childSkip = { }; 00278 s->childoff = s->b.p - d->info.data; 00279 werrstr("Set childoff at %x\n", s->childoff); 00280 int r = dwarfnextsymat(d, s, &childSkip); 00281 while (r == 0) { 00282 r = dwarfnextsym(d, &childSkip); 00283 } 00284 s->b = childSkip.b; 00285 } else { 00286 s->childoff = 0; 00287 } 00288 return 0; 00289 } 00290 00291 int 00292 dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child) 00293 { 00294 uint sib; 00295 00296 if (!parent->attrs.haskids || !parent->childoff) 00297 return -1; 00298 00299 child->unit = parent->unit; 00300 child->aoff = parent->aoff; 00301 child->depth = parent->depth + 1; 00302 if(child->attrs.have.sibling){ 00303 sib = child->attrs.sibling; 00304 if(sib < d->info.len && d->info.data+sib > child->b.p) 00305 child->b.p = d->info.data+sib; 00306 else if (sib >= d->info.len) { 00307 werrstr("sibling reported as out of bounds %d vs %d", sib, d->info.len); 00308 return -1; 00309 } else if (d->info.data+sib+parent->unit < child->b.p) { 00310 werrstr("subsequent sibling is listed before prev %d vs %d", sib+parent->unit, child->b.p - d->info.data); 00311 return -1; 00312 } 00313 } 00314 00315 // Uninitialized 00316 if (!child->b.d) { 00317 child->b = parent->b; 00318 child->b.p = parent->childoff + parent->b.d->info.data; 00319 werrstr("Rewound to childoff %x\n", parent->childoff); 00320 } 00321 00322 return dwarfnextsym(d, child); 00323 } 00324 00325 typedef struct Parse Parse; 00326 struct Parse { 00327 const char *namestr; 00328 int name; 00329 int off; 00330 int haveoff; 00331 int type; 00332 }; 00333 00334 #define ATTR(x) (#x)+9, x 00335 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x) 00336 00337 static Parse plist[] = { /* Font Tab 4 */ 00338 { ATTR(DwarfAttrAbstractOrigin), OFFSET(abstractorigin), TReference }, 00339 { ATTR(DwarfAttrAccessibility), OFFSET(accessibility), TConstant }, 00340 { ATTR(DwarfAttrAddrClass), OFFSET(addrclass), TConstant }, 00341 { ATTR(DwarfAttrBaseTypes), OFFSET(basetypes), TReference }, 00342 { ATTR(DwarfAttrBitOffset), OFFSET(bitoffset), TConstant }, 00343 { ATTR(DwarfAttrBitSize), OFFSET(bitsize), TConstant }, 00344 { ATTR(DwarfAttrByteSize), OFFSET(bytesize), TConstant }, 00345 { ATTR(DwarfAttrCalling), OFFSET(calling), TConstant }, 00346 { ATTR(DwarfAttrCommonRef), OFFSET(commonref), TReference }, 00347 { ATTR(DwarfAttrCompDir), OFFSET(compdir), TString }, 00348 { ATTR(DwarfAttrConstValue), OFFSET(constvalue), TString|TConstant|TBlock }, 00349 { ATTR(DwarfAttrContainingType), OFFSET(containingtype), TReference }, 00350 { ATTR(DwarfAttrCount), OFFSET(count), TConstant|TReference }, 00351 { ATTR(DwarfAttrDataMemberLoc), OFFSET(datamemberloc), TBlock|TConstant|TReference }, 00352 { ATTR(DwarfAttrDeclColumn), OFFSET(declcolumn), TConstant }, 00353 { ATTR(DwarfAttrDeclFile), OFFSET(declfile), TConstant }, 00354 { ATTR(DwarfAttrDeclLine), OFFSET(declline), TConstant }, 00355 { ATTR(DwarfAttrDefaultValue), OFFSET(defaultvalue), TReference }, 00356 { ATTR(DwarfAttrDiscr), OFFSET(discr), TReference }, 00357 { ATTR(DwarfAttrDiscrList), OFFSET(discrlist), TBlock }, 00358 { ATTR(DwarfAttrDiscrValue), OFFSET(discrvalue), TConstant }, 00359 { ATTR(DwarfAttrEncoding), OFFSET(encoding), TConstant }, 00360 { ATTR(DwarfAttrFrameBase), OFFSET(framebase), TBlock|TConstant }, 00361 { ATTR(DwarfAttrFriend), OFFSET(friend), TReference }, 00362 { ATTR(DwarfAttrHighpc), OFFSET(highpc), TAddress }, 00363 { ATTR(DwarfAttrEntrypc), OFFSET(entrypc), TAddress }, 00364 { ATTR(DwarfAttrIdentifierCase), OFFSET(identifiercase), TConstant }, 00365 { ATTR(DwarfAttrImport), OFFSET(import), TReference }, 00366 { ATTR(DwarfAttrInline), OFFSET(inlined), TConstant }, 00367 { ATTR(DwarfAttrArtificial), OFFSET(isartificial), TFlag }, 00368 { ATTR(DwarfAttrDeclaration), OFFSET(isdeclaration), TFlag }, 00369 { ATTR(DwarfAttrExternal), OFFSET(isexternal), TFlag }, 00370 { ATTR(DwarfAttrIsOptional), OFFSET(isoptional), TFlag }, 00371 { ATTR(DwarfAttrPrototyped), OFFSET(isprototyped), TFlag }, 00372 { ATTR(DwarfAttrVarParam), OFFSET(isvarparam), TFlag }, 00373 { ATTR(DwarfAttrLanguage), OFFSET(language), TConstant }, 00374 { ATTR(DwarfAttrLocation), OFFSET(location), TReference|TBlock }, 00375 { ATTR(DwarfAttrLowerBound), OFFSET(lowerbound), TConstant|TReference }, 00376 { ATTR(DwarfAttrLowpc), OFFSET(lowpc), TAddress }, 00377 { ATTR(DwarfAttrMacroInfo), OFFSET(macroinfo), TConstant }, 00378 { ATTR(DwarfAttrName), OFFSET(name), TString }, 00379 { ATTR(DwarfAttrNamelistItem), OFFSET(namelistitem), TBlock }, 00380 { ATTR(DwarfAttrOrdering), OFFSET(ordering), TConstant }, 00381 { ATTR(DwarfAttrPriority), OFFSET(priority), TReference }, 00382 { ATTR(DwarfAttrProducer), OFFSET(producer), TString }, 00383 { ATTR(DwarfAttrRanges), OFFSET(ranges), TReference }, 00384 { ATTR(DwarfAttrReturnAddr), OFFSET(returnaddr), TBlock|TConstant }, 00385 { ATTR(DwarfAttrSegment), OFFSET(segment), TBlock|TConstant }, 00386 { ATTR(DwarfAttrSibling), OFFSET(sibling), TReference }, 00387 { ATTR(DwarfAttrSpecification), OFFSET(specification), TReference }, 00388 { ATTR(DwarfAttrStartScope), OFFSET(startscope), TConstant }, 00389 { ATTR(DwarfAttrStaticLink), OFFSET(staticlink), TBlock|TConstant }, 00390 { ATTR(DwarfAttrStmtList), OFFSET(stmtlist), TConstant }, 00391 { ATTR(DwarfAttrStrideSize), OFFSET(stridesize), TConstant }, 00392 { ATTR(DwarfAttrStringLength), OFFSET(stringlength), TBlock|TConstant }, 00393 { ATTR(DwarfAttrType), OFFSET(type), TReference }, 00394 { ATTR(DwarfAttrUpperBound), OFFSET(upperbound), TConstant|TReference }, 00395 { ATTR(DwarfAttrUseLocation), OFFSET(uselocation), TBlock|TConstant }, 00396 { ATTR(DwarfAttrVirtuality), OFFSET(virtuality), TConstant }, 00397 { ATTR(DwarfAttrVisibility), OFFSET(visibility), TConstant }, 00398 { ATTR(DwarfAttrVtableElemLoc), OFFSET(vtableelemloc), TBlock|TReference }, 00399 { } 00400 }; 00401 00402 static Parse ptab[DwarfAttrMax]; 00403 00404 static int 00405 parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs) 00406 { 00407 int i, f, n, got; 00408 static int nbad; 00409 void *v; 00410 00411 /* initialize ptab first time through for quick access */ 00412 if(ptab[DwarfAttrName].name != DwarfAttrName) 00413 for(i=0; plist[i].name; i++) 00414 ptab[plist[i].name] = plist[i]; 00415 00416 memset(attrs, 0, sizeof *attrs); 00417 attrs->tag = a->tag; 00418 attrs->haskids = a->haskids; 00419 00420 for(i=0; i<a->nattr; i++){ 00421 n = a->attr[i].name; 00422 f = a->attr[i].form; 00423 werrstr("struct: (@%x) n %x f %x (%d %d)\n", b->p - d->info.data, n, f, ptab[n].haveoff, ptab[n].off); 00424 if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) { 00425 if (skipform(d, b, f) < 0) { 00426 if(++nbad == 1) 00427 werrstr("dwarf parse attrs: cannot skip form %d", f); 00428 return -1; 00429 } 00430 continue; 00431 } 00432 v = (char*)attrs + ptab[n].off; 00433 got = 0; 00434 if(f == FormIndirect) 00435 f = dwarfget128(b); 00436 if((ptab[n].type&(TConstant|TReference|TAddress)) 00437 && getulong(b, f, unit, v, &got) >= 0) 00438 ; 00439 else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0) 00440 got = TFlag; 00441 else if((ptab[n].type&TString) && getstring(d, b, f, v) >= 0) 00442 got = TString; 00443 else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0) { 00444 got = TBlock; 00445 } else { 00446 werrstr("Skipping form %x\n", f); 00447 if(skipform(d, b, f) < 0){ 00448 //if(++nbad == 1) 00449 werrstr("dwarf parse attrs: cannot skip form %d", f); 00450 return -1; 00451 } 00452 } 00453 #if 0 00454 if(got == TBlock && (ptab[n].type&TConstant)) 00455 got = constblock(b->d, v, v); 00456 #endif 00457 *((uchar*)attrs+ptab[n].haveoff) = got; 00458 } 00459 00460 if (attrs->have.name) 00461 werrstr("%s: tag %x kids %d (last %x)\n", attrs->name, attrs->tag, attrs->haskids, b->p - b->d->info.data); 00462 00463 return 0; 00464 } 00465 00466 static int 00467 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type) 00468 { 00469 static int nbad; 00470 uvlong uv; 00471 00472 switch(form){ 00473 default: 00474 return -1; 00475 00476 /* addresses */ 00477 case FormAddr: 00478 *type = TAddress; 00479 *u = dwarfgetaddr(b); 00480 return 0; 00481 00482 /* references */ 00483 case FormRefAddr: 00484 /* absolute ref in .debug_info */ 00485 *type = TReference; 00486 *u = dwarfgetaddr(b); 00487 return 0; 00488 case FormRef1: 00489 *u = dwarfget1(b); 00490 goto relativeref; 00491 case FormRef2: 00492 *u = dwarfget2(b); 00493 goto relativeref; 00494 case FormRef4: 00495 *u = dwarfget4(b); 00496 goto relativeref; 00497 case FormRef8: 00498 *u = dwarfget8(b); 00499 goto relativeref; 00500 case FormRefUdata: 00501 *u = dwarfget128(b); 00502 relativeref: 00503 *u += unit; 00504 *type = TReference; 00505 return 0; 00506 00507 /* constants */ 00508 case FormData1: 00509 *u = dwarfget1(b); 00510 goto constant; 00511 case FormData2: 00512 *u = dwarfget2(b); 00513 goto constant; 00514 case FormData4: 00515 *u = dwarfget4(b); 00516 goto constant; 00517 case FormData8: 00518 uv = dwarfget8(b); 00519 *u = uv; 00520 if(uv != *u && ++nbad == 1) 00521 werrstr("dwarf: truncating 64-bit attribute constants"); 00522 goto constant; 00523 case FormSdata: 00524 *u = dwarfget128s(b); 00525 goto constant; 00526 case FormUdata: 00527 *u = dwarfget128(b); 00528 constant: 00529 *type = TConstant; 00530 return 0; 00531 } 00532 } 00533 00534 static int 00535 getuchar(DwarfBuf *b, int form, uchar *u) 00536 { 00537 switch(form){ 00538 default: 00539 return -1; 00540 00541 case FormFlag: 00542 *u = dwarfget1(b); 00543 return 0; 00544 } 00545 } 00546 00547 static int 00548 getstring(Dwarf *d, DwarfBuf *b, int form, char **s) 00549 { 00550 static int nbad; 00551 ulong u, x; 00552 00553 switch(form){ 00554 default: 00555 return -1; 00556 00557 case FormString: 00558 x = b->p - d->info.data; 00559 *s = dwarfgetstring(b); 00560 for (u = 0; (*s)[u]; u++) { 00561 assert(isprint((*s)[u])); 00562 } 00563 return 0; 00564 00565 case FormStrp: 00566 u = dwarfget4(b); 00567 if(u >= b->d->str.len){ 00568 if(++nbad == 1) 00569 werrstr("dwarf: bad string pointer 0x%lux in attribute", u); 00570 /* don't return error - maybe can proceed */ 00571 *s = nil; 00572 }else 00573 *s = (char*)b->d->str.data + u; 00574 return 0; 00575 00576 } 00577 } 00578 00579 static int 00580 getblock(DwarfBuf *b, int form, DwarfBlock *bl) 00581 { 00582 ulong n; 00583 00584 switch(form){ 00585 default: 00586 return -1; 00587 case FormDwarfBlock: 00588 n = dwarfget128(b); 00589 goto copyn; 00590 case FormDwarfBlock1: 00591 n = dwarfget1(b); 00592 goto copyn; 00593 case FormDwarfBlock2: 00594 n = dwarfget2(b); 00595 goto copyn; 00596 case FormDwarfBlock4: 00597 n = dwarfget4(b); 00598 copyn: 00599 bl->data = dwarfgetnref(b, n); 00600 bl->len = n; 00601 if(bl->data == nil) 00602 return -1; 00603 return 0; 00604 } 00605 } 00606 00607 /* last resort */ 00608 static int 00609 skipform(Dwarf *d, DwarfBuf *b, int form) 00610 { 00611 int type; 00612 DwarfVal val; 00613 00614 if(getulong(b, form, 0, &val.c, &type) < 0 00615 && getuchar(b, form, (uchar*)&val) < 0 00616 && getstring(d, b, form, &val.s) < 0 00617 && getblock(b, form, &val.b) < 0) 00618 return -1; 00619 return 0; 00620 } 00621 00622 void stackinit(DwarfStack *stack) 00623 { 00624 memset(stack, 0, sizeof(*stack)); 00625 stack->data = stack->storage; 00626 stack->length = 0; stack->max = sizeof(stack->storage) / sizeof(stack->storage[0]); 00627 } 00628 00629 void stackpush(DwarfStack *stack, ulong value) 00630 { 00631 if (stack->length == stack->max) { 00632 ulong *newstack = malloc(sizeof(ulong)*stack->max*2); 00633 memcpy(newstack, stack->data, sizeof(ulong)*stack->length); 00634 if (stack->data != stack->storage) 00635 free(stack->data); 00636 stack->data = newstack; 00637 stack->max *= 2; 00638 } 00639 werrstr("stack[%d] = %x", stack->length, value); 00640 stack->data[stack->length++] = value; 00641 } 00642 00643 ulong stackpop(DwarfStack *stack) 00644 { 00645 ASSERT(stack->length > 0); 00646 ulong val = stack->data[--stack->length]; 00647 werrstr("pop stack[%d] -> %x", stack->length, val); 00648 return val; 00649 } 00650 00651 void stackfree(DwarfStack *stack) 00652 { 00653 if (stack->data != stack->storage) 00654 free(stack->data); 00655 } 00656 00657 // Returns -1 on failure 00658 int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *buf, ulong cfa, PROSSYM_REGISTERS registers, ulong *result) 00659 { 00660 int ret = 0; 00661 DwarfStack stack = { }; 00662 stackinit(&stack); 00663 stackpush(&stack, cfa); 00664 while (buf->p < buf->ep) { 00665 int opcode = dwarfget1(buf); 00666 werrstr("opcode %x", opcode); 00667 switch (opcode) { 00668 case 0: 00669 buf->p = buf->ep; 00670 break; 00671 case OpAddr: 00672 if (d->addrsize == 4) { 00673 stackpush(&stack, dwarfget4(buf)); 00674 break; 00675 } else { 00676 werrstr("%s: we only support 4 byte addrs", name); 00677 goto fatal; 00678 } 00679 case OpConst1s: { 00680 signed char c = dwarfget1(buf); 00681 stackpush(&stack, c); 00682 } break; 00683 case OpConst1u: 00684 stackpush(&stack, dwarfget1(buf)); 00685 break; 00686 case OpConst2s: { 00687 signed short s = dwarfget2(buf); 00688 stackpush(&stack, s); 00689 } break; 00690 case OpConst2u: 00691 stackpush(&stack, dwarfget2(buf)); 00692 break; 00693 case OpConst4s: { 00694 signed int i = dwarfget4(buf); 00695 stackpush(&stack, i); 00696 } break; 00697 case OpConst4u: 00698 stackpush(&stack, dwarfget4(buf)); 00699 break; 00700 case OpConst8s: 00701 case OpConst8u: 00702 werrstr("const 8 not yet supported"); 00703 goto fatal; 00704 case OpConsts: 00705 stackpush(&stack, dwarfget128s(buf)); 00706 break; 00707 case OpConstu: 00708 stackpush(&stack, dwarfget128(buf)); 00709 break; 00710 case OpDup: { 00711 ulong popped = stackpop(&stack); 00712 stackpush(&stack, popped); 00713 stackpush(&stack, popped); 00714 } break; 00715 case OpDrop: 00716 stackpop(&stack); 00717 break; 00718 case OpOver: { 00719 if (stack.length < 2) goto fatal; 00720 stackpush(&stack, stack.data[stack.length-2]); 00721 } break; 00722 case OpPick: { 00723 ulong arg = dwarfget1(buf); 00724 if (arg >= stack.length) goto fatal; 00725 arg = stack.data[stack.length-1-arg]; 00726 stackpush(&stack, arg); 00727 } break; 00728 case OpSwap: { 00729 ulong a = stackpop(&stack), b = stackpop(&stack); 00730 stackpush(&stack, b); 00731 stackpush(&stack, a); 00732 } break; 00733 case OpRot: { 00734 ulong a = stackpop(&stack), b = stackpop(&stack), c = stackpop(&stack); 00735 stackpush(&stack, b); 00736 stackpush(&stack, c); 00737 stackpush(&stack, a); 00738 } break; 00739 case OpXderef: 00740 case OpXderefSize: 00741 werrstr("Xderef not yet supported"); 00742 goto fatal; 00743 case OpAbs: { 00744 long a = stackpop(&stack); 00745 stackpush(&stack, a < 0 ? -a : a); 00746 } break; 00747 case OpAnd: 00748 stackpush(&stack, stackpop(&stack) & stackpop(&stack)); 00749 break; 00750 case OpDiv: { 00751 ulong a = stackpop(&stack), b = stackpop(&stack); 00752 stackpush(&stack, b / a); 00753 } break; 00754 case OpMinus: { 00755 ulong a = stackpop(&stack), b = stackpop(&stack); 00756 stackpush(&stack, b - a); 00757 } break; 00758 case OpMod: { 00759 ulong a = stackpop(&stack), b = stackpop(&stack); 00760 stackpush(&stack, b % a); 00761 } break; 00762 case OpMul: 00763 stackpush(&stack, stackpop(&stack) * stackpop(&stack)); 00764 break; 00765 case OpNeg: 00766 stackpush(&stack, -stackpop(&stack)); 00767 break; 00768 case OpNot: 00769 stackpush(&stack, ~stackpop(&stack)); 00770 break; 00771 case OpOr: 00772 stackpush(&stack, stackpop(&stack) | stackpop(&stack)); 00773 break; 00774 case OpPlus: 00775 stackpush(&stack, stackpop(&stack) + stackpop(&stack)); 00776 break; 00777 case OpPlusUconst: 00778 stackpush(&stack, stackpop(&stack) + dwarfget128(buf)); 00779 break; 00780 case OpShl: { 00781 ulong a = stackpop(&stack), b = stackpop(&stack); 00782 stackpush(&stack, b << a); 00783 } break; 00784 case OpShr: { 00785 ulong a = stackpop(&stack), b = stackpop(&stack); 00786 stackpush(&stack, b >> a); 00787 } break; 00788 case OpShra: { 00789 ulong a = stackpop(&stack); 00790 long b = stackpop(&stack); 00791 if (b < 0) 00792 b = -(-b >> a); 00793 else 00794 b = b >> a; 00795 stackpush(&stack, b); 00796 } break; 00797 case OpXor: 00798 stackpush(&stack, stackpop(&stack) ^ stackpop(&stack)); 00799 break; 00800 case OpSkip: 00801 buf->p += dwarfget2(buf); 00802 break; 00803 case OpBra: { 00804 ulong a = dwarfget2(buf); 00805 if (stackpop(&stack)) 00806 buf->p += a; 00807 } break; 00808 case OpEq: 00809 stackpush(&stack, stackpop(&stack) == stackpop(&stack)); 00810 break; 00811 case OpGe: { 00812 ulong a = stackpop(&stack), b = stackpop(&stack); 00813 stackpush(&stack, b >= a); 00814 } break; 00815 case OpGt: { 00816 ulong a = stackpop(&stack), b = stackpop(&stack); 00817 stackpush(&stack, b > a); 00818 } break; 00819 case OpLe: { 00820 ulong a = stackpop(&stack), b = stackpop(&stack); 00821 stackpush(&stack, b <= a); 00822 } break; 00823 case OpLt: { 00824 ulong a = stackpop(&stack), b = stackpop(&stack); 00825 stackpush(&stack, b < a); 00826 } break; 00827 case OpNe: 00828 stackpush(&stack, stackpop(&stack) != stackpop(&stack)); 00829 break; 00830 case OpNop: 00831 break; 00832 case OpDeref: { 00833 ulong val; 00834 void* addr = (void*)stackpop(&stack); 00835 if (!RosSymCallbacks.MemGetProc 00836 (d->pe->fd, 00837 &val, 00838 addr, 00839 d->addrsize)) 00840 goto fatal; 00841 stackpush(&stack, val); 00842 } break; 00843 case OpDerefSize: { 00844 ulong val, size = dwarfget1(buf); 00845 void* addr = (void*)stackpop(&stack); 00846 if (!RosSymCallbacks.MemGetProc 00847 (d->pe->fd, 00848 &val, 00849 addr, 00850 size)) 00851 goto fatal; 00852 stackpush(&stack, val); 00853 } break; 00854 case OpFbreg: { 00855 ulong val, offset = dwarfget128s(buf);; 00856 void* addr = (void*)cfa; 00857 werrstr("FBREG cfa %x offset %x", cfa, offset); 00858 if (!RosSymCallbacks.MemGetProc 00859 (d->pe->fd, 00860 &val, 00861 (PVOID)((ULONG_PTR)addr+offset), 00862 d->addrsize)) 00863 goto fatal; 00864 stackpush(&stack, val); 00865 } break; 00866 case OpPiece: 00867 werrstr("OpPiece not supported"); 00868 goto fatal; 00869 default: 00870 if (opcode >= OpLit0 && opcode < OpReg0) 00871 stackpush(&stack, opcode - OpLit0); 00872 else if (opcode >= OpReg0 && opcode < OpBreg0) { 00873 ulong reg = opcode - OpReg0; 00874 werrstr("REG[%d] value %x", reg, (ulong)registers->Registers[reg]); 00875 stackpush(&stack, registers->Registers[reg]); 00876 } else if (opcode >= OpBreg0 && opcode < OpRegx) { 00877 ulong val, 00878 reg = opcode - OpBreg0, 00879 offset = dwarfget128s(buf); 00880 void* addr = (void*)(ULONG_PTR)registers->Registers[reg]; 00881 werrstr("BREG[%d] reg %x offset %x", reg, addr, offset); 00882 if (!RosSymCallbacks.MemGetProc 00883 ((PVOID)d->pe->fd, 00884 &val, 00885 (PVOID)((ULONG_PTR)addr + offset), 00886 d->addrsize)) 00887 goto fatal; 00888 stackpush(&stack, val); 00889 } else { 00890 werrstr("opcode %x not supported", opcode); 00891 goto fatal; 00892 } 00893 break; 00894 } 00895 } 00896 if (stack.length < 1) goto fatal; 00897 *result = stackpop(&stack); 00898 werrstr("%s: value %x", name, *result); 00899 goto finish; 00900 00901 fatal: 00902 ret = -1; 00903 00904 finish: 00905 stackfree(&stack); 00906 return ret; 00907 } 00908 00909 int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTERS registers, DwarfParam *parameter) 00910 { 00911 int gotarg; 00912 DwarfSym unit = { }; 00913 00914 if (dwarfenumunit(d, proc->unit, &unit) == -1) 00915 return -1; 00916 00917 werrstr("lookup in unit %x-%x, pc %x", unit.attrs.lowpc, unit.attrs.highpc, pc); 00918 pc -= unit.attrs.lowpc; 00919 00920 werrstr("paramblock %s -> unit %x type %x fde %x len %d registers %x", 00921 parameter->name, 00922 parameter->unit, 00923 parameter->type, 00924 parameter->fde, 00925 parameter->len, 00926 registers); 00927 00928 // Seek our range in loc 00929 DwarfBuf locbuf; 00930 DwarfBuf instream = { }; 00931 00932 locbuf.d = d; 00933 locbuf.addrsize = d->addrsize; 00934 00935 if (parameter->loctype == TConstant) { 00936 locbuf.p = d->loc.data + parameter->fde; 00937 locbuf.ep = d->loc.data + d->loc.len; 00938 ulong start, end, len; 00939 do { 00940 len = 0; 00941 start = dwarfget4(&locbuf); 00942 end = dwarfget4(&locbuf); 00943 if (start && end) { 00944 len = dwarfget2(&locbuf); 00945 instream = locbuf; 00946 instream.ep = instream.p + len; 00947 locbuf.p = instream.ep; 00948 } 00949 werrstr("ip %x s %x e %x (%x bytes)", pc, start, end, len); 00950 } while (start && end && (start > pc || end <= pc)); 00951 } else if (parameter->loctype == TBlock) { 00952 instream = locbuf; 00953 instream.p = (void *)parameter->fde; 00954 instream.ep = instream.p + parameter->len; 00955 } else { 00956 werrstr("Wrong block type for parameter %s", parameter->name); 00957 return -1; 00958 } 00959 00960 gotarg = dwarfgetarg(d, parameter->name, &instream, cfa, registers, ¶meter->value); 00961 if (gotarg == -1) 00962 return -1; 00963 00964 return 0; 00965 } 00966 00967 void 00968 dwarfdumpsym(Dwarf *d, DwarfSym *s) 00969 { 00970 int j; 00971 werrstr("tag %x\n", s->attrs.tag); 00972 for (j = 0; plist[j].name; j++) { 00973 char *have = ((char*)&s->attrs) + plist[j].haveoff; 00974 char *attr = ((char*)&s->attrs) + plist[j].off; 00975 if (*have == TString) { 00976 char *str = *((char **)attr); 00977 werrstr("%s: %s\n", plist[j].namestr, str); 00978 } else if (*have == TReference) { 00979 DwarfVal *val = ((DwarfVal*)attr); 00980 werrstr("%s: %x:%x\n", plist[j].namestr, val->b.data, val->b.len); 00981 } else if (*have) 00982 werrstr("%s: (%x)\n", plist[j].namestr, *have); 00983 } 00984 } 00985 00986 int 00987 dwarfgetparams(Dwarf *d, DwarfSym *s, ulong pc, int pnum, DwarfParam *paramblocks) 00988 { 00989 int ip = 0; 00990 DwarfSym param = { }; 00991 int res = dwarfnextsymat(d, s, ¶m); 00992 while (res == 0 && ip < pnum) { 00993 if (param.attrs.tag == TagFormalParameter && 00994 param.attrs.have.name && 00995 param.attrs.have.location) { 00996 paramblocks[ip].name = malloc(strlen(param.attrs.name)+1); 00997 strcpy(paramblocks[ip].name, param.attrs.name); 00998 paramblocks[ip].unit = param.unit; 00999 paramblocks[ip].type = param.attrs.type; 01000 paramblocks[ip].loctype = param.attrs.have.location; 01001 paramblocks[ip].len = param.attrs.location.b.len; 01002 paramblocks[ip].fde = (ulong)param.attrs.location.b.data; 01003 werrstr("param[%d] block %s -> type %x loctype %x fde %x len %x", 01004 ip, 01005 paramblocks[ip].name, 01006 paramblocks[ip].type, 01007 paramblocks[ip].loctype, 01008 paramblocks[ip].fde, 01009 paramblocks[ip].len); 01010 ip++; 01011 } 01012 res = dwarfnextsymat(d, s, ¶m); 01013 } 01014 return ip; 01015 } Generated on Mon May 28 2012 04:36:11 for ReactOS by
1.7.6.1
|