00001 #include "dwarfWalker.h"
00002 #include "common/h/headers.h"
00003 #include "Module.h"
00004 #include "Symtab.h"
00005 #include "Collections.h"
00006 #include "dwarf.h"
00007 #include "Object.h"
00008 #include "Object-elf.h"
00009 #include "Function.h"
00010 #include "dwarf/h/dwarfExprParser.h"
00011 #include "common/h/pathName.h"
00012 #include "common/h/debug_common.h"
00013
00014 using namespace Dyninst;
00015 using namespace SymtabAPI;
00016 using namespace Dwarf;
00017 using namespace std;
00018
00019 #define DWARF_FAIL_RET(x) { \
00020 int status = (x); \
00021 if (status != DW_DLV_OK) { \
00022 fprintf(stderr, "[%s:%d]: libdwarf returned %d, ret false\n", FILE__, __LINE__, status); \
00023 return false; \
00024 } \
00025 }
00026
00027 #define DWARF_ERROR_RET(x) { \
00028 int status = (x); \
00029 if (status == DW_DLV_ERROR) { \
00030 fprintf(stderr, "[%s:%d]: parsing failure, ret false\n", FILE__, __LINE__); \
00031 return false; \
00032 } \
00033 }
00034
00035 #define DWARF_CHECK_RET(x) { \
00036 if (x) { \
00037 fprintf(stderr, "[%s:%d]: parsing failure, ret false\n", FILE__, __LINE__); \
00038 return false; \
00039 } \
00040 }
00041
00042 DwarfWalker::DwarfWalker(Symtab *symtab, Dwarf_Debug &dbg)
00043 :
00044 dbg_(dbg),
00045 mod_(NULL),
00046 symtab_(symtab),
00047 tc_(NULL),
00048 modLow(0),
00049 modHigh(0) {
00050 }
00051
00052 DwarfWalker::~DwarfWalker() {}
00053
00054 bool DwarfWalker::parse() {
00055 dwarf_printf("Parsing DWARF for %s\n", symtab_->file().c_str());
00056
00057
00058 Module *fixUnknownMod = NULL;
00059 mod_ = NULL;
00060
00061
00062 while (dwarf_next_cu_header_c(dbg(),
00063 (Dwarf_Bool) 1,
00064 &cu_header_length,
00065 &version,
00066 &abbrev_offset,
00067 &addr_size,
00068 &offset_size,
00069 &extension_size,
00070 &signature,
00071 &typeoffset,
00072 &next_cu_header, NULL) == DW_DLV_OK ) {
00073 contexts_.push();
00074 bool ret = parseModule(fixUnknownMod);
00075 contexts_.pop();
00076 if (!ret) return false;
00077 }
00078
00079 if (!fixUnknownMod)
00080 return true;
00081
00082 dwarf_printf("Fixing types for final module %s\n", fixUnknownMod->fileName().c_str());
00083
00084
00085 typeCollection *moduleTypes = typeCollection::getModTypeCollection(fixUnknownMod);
00086 assert(moduleTypes);
00087 dyn_hash_map< int, Type * >::iterator typeIter = moduleTypes->typesByID.begin();
00088 for (;typeIter!=moduleTypes->typesByID.end();typeIter++)
00089 {
00090 typeIter->second->fixupUnknowns(fixUnknownMod);
00091 }
00092
00093
00094 std::string variableName;
00095 dyn_hash_map< std::string, Type * >::iterator variableIter = moduleTypes->globalVarsByName.begin();
00096 for (;variableIter!=moduleTypes->globalVarsByName.end();variableIter++)
00097 {
00098 if (variableIter->second->getDataClass() == dataUnknownType &&
00099 moduleTypes->findType( variableIter->second->getID() ) != NULL )
00100 {
00101 moduleTypes->globalVarsByName[ variableIter->first ]
00102 = moduleTypes->findType( variableIter->second->getID() );
00103 }
00104 }
00105
00106 moduleTypes->setDwarfParsed();
00107 return true;
00108 }
00109
00110 bool DwarfWalker::parseModule(Module *&fixUnknownMod) {
00111
00112 Dwarf_Die moduleDIE;
00113 DWARF_FAIL_RET(dwarf_siblingof( dbg(), NULL, &moduleDIE, NULL ));
00114
00115
00116 Dwarf_Half moduleTag;
00117 DWARF_FAIL_RET(dwarf_tag( moduleDIE, & moduleTag, NULL ));
00118
00119
00120 Dwarf_Off dieOffset;
00121 DWARF_FAIL_RET(dwarf_dieoffset( moduleDIE, &dieOffset, NULL));
00122
00123
00124 compile_offset = (dieOffset - 0xb);
00125
00126 if (moduleTag != DW_TAG_compile_unit) return false;
00127
00128
00129 std::string moduleName;
00130 char *tmp;
00131 int status = dwarf_diename( moduleDIE, &tmp, NULL );
00132 DWARF_CHECK_RET(status == DW_DLV_ERROR);
00133
00134 if ( status == DW_DLV_NO_ENTRY ) {
00135 moduleName = "{ANONYMOUS}";
00136 }
00137 else {
00138 moduleName = tmp;
00139 dwarf_dealloc( dbg(), tmp, DW_DLA_STRING );
00140 }
00141
00142 dwarf_printf("Next DWARF module: %s with DIE %p and tag %d\n", moduleName.c_str(), moduleDIE, moduleTag);
00143
00144
00145 Dwarf_Attribute languageAttribute;
00146 DWARF_ERROR_RET(dwarf_attr( moduleDIE, DW_AT_language, & languageAttribute, NULL ));
00147
00148
00149 setEntry(moduleDIE);
00150
00151
00152 Address tempModLow, tempModHigh;
00153 modLow = modHigh = 0;
00154 if (findConstant(DW_AT_low_pc, tempModLow)) {
00155 obj()->convertDebugOffset(tempModLow, modLow);
00156 }
00157 if (findConstant(DW_AT_high_pc, tempModHigh)) {
00158 obj()->convertDebugOffset(tempModHigh, modHigh);
00159 }
00160
00161 if (!symtab()->findModuleByName(mod_, moduleName))
00162 {
00163 std::string fName = extract_pathname_tail(moduleName);
00164 if (!symtab()->findModuleByName(mod_, fName)) {
00165 moduleName = symtab()->file();
00166 if (!symtab()->findModuleByName(mod_, moduleName)) {
00167 mod_ = symtab()->getDefaultModule();
00168 }
00169 }
00170 }
00171
00172 dwarf_printf("Mapped to Symtab module %s\n", mod_->fileName().c_str());
00173
00174 if (!fixUnknownMod)
00175 fixUnknownMod = mod_;
00176
00177 if (!buildSrcFiles(moduleDIE)) return false;
00178
00179 tc_ = typeCollection::getModTypeCollection(mod_);
00180
00181 if (!parse_int(moduleDIE, true)) return false;
00182
00183 enclosureMap.clear();
00184
00185 return true;
00186
00187 }
00188
00189
00190 bool DwarfWalker::buildSrcFiles(Dwarf_Die entry) {
00191 srcFiles_.clear();
00192
00193 Dwarf_Signed cnt = 0;
00194 char **srcfiletmp = NULL;
00195 DWARF_ERROR_RET(dwarf_srcfiles(entry, &srcfiletmp, &cnt, NULL));
00196
00197 for (unsigned i = 0; i < cnt; ++i) {
00198 srcFiles_.push_back(srcfiletmp[i]);
00199 dwarf_dealloc(dbg(), srcfiletmp[i], DW_DLA_STRING);
00200 }
00201 dwarf_dealloc(dbg(), srcfiletmp, DW_DLA_LIST);
00202 return true;
00203 }
00204
00205 Object *DwarfWalker::obj() {
00206 return symtab_->getObject();
00207 }
00208
00209
00210
00211
00212
00213 bool DwarfWalker::parse_int(Dwarf_Die e, bool p) {
00214 dwarf_printf("PARSE_INT entry, context size %d\n", (int) contexts_.c.size());
00215
00216
00217 while(1) {
00218 contexts_.push();
00219
00220 setEntry(e);
00221 setParseSibling(p);
00222
00223 if (!findTag()) return false;
00224 if (!findOffset()) return false;
00225 curName() = std::string();
00226
00227 dwarf_printf("(0x%lx) Parsing entry %p with context size %d, func %p (%s), encl %p\n",
00228 id(),
00229 e,
00230 (int) contexts_.c.size(),
00231 curFunc(),
00232 (curFunc() ? curFunc()->getAllMangledNames()[0].c_str() : "<null>"),
00233 curEnclosure());
00234
00235
00236 enclosureMap.insert(std::make_pair(offset(), curEnclosure()));
00237
00238 bool ret = false;
00239
00240
00241 #if defined(os_bg)
00242 if (tag() == DW_TAG_base_type ||
00243 tag() == DW_TAG_const_type ||
00244 tag() == DW_TAG_pointer_type) {
00245
00246
00247
00248 clearFunc();
00249 }
00250 #endif
00251
00252
00253
00254 switch(tag()) {
00255 case DW_TAG_subprogram:
00256 case DW_TAG_entry_point:
00257 ret = parseSubprogram();
00258 break;
00259 case DW_TAG_lexical_block:
00260 ret = parseLexicalBlock();
00261 break;
00262 case DW_TAG_common_block:
00263 ret = parseCommonBlock();
00264 break;
00265 case DW_TAG_constant:
00266 ret = parseConstant();
00267 break;
00268 case DW_TAG_variable:
00269 ret = parseVariable();
00270 break;
00271 case DW_TAG_formal_parameter:
00272 ret = parseFormalParam();
00273 break;
00274 case DW_TAG_base_type:
00275 ret = parseBaseType();
00276 break;
00277 case DW_TAG_typedef:
00278 ret = parseTypedef();
00279 break;
00280 case DW_TAG_array_type:
00281 ret = parseArray();
00282 break;
00283 case DW_TAG_subrange_type:
00284 ret = parseSubrange();
00285 break;
00286 case DW_TAG_enumeration_type:
00287 ret = parseEnum();
00288 break;
00289 case DW_TAG_inheritance:
00290 ret = parseInheritance();
00291 break;
00292 case DW_TAG_structure_type:
00293 case DW_TAG_union_type:
00294 case DW_TAG_class_type:
00295 ret = parseStructUnionClass();
00296 break;
00297 case DW_TAG_enumerator:
00298 ret = parseEnumEntry();
00299 break;
00300 case DW_TAG_member:
00301 ret = parseMember();
00302 break;
00303 case DW_TAG_const_type:
00304 case DW_TAG_packed_type:
00305 case DW_TAG_volatile_type:
00306 ret = parseConstPackedVolatile();
00307 break;
00308 case DW_TAG_subroutine_type:
00309
00310
00311 case DW_TAG_ptr_to_member_type:
00312 case DW_TAG_pointer_type:
00313 case DW_TAG_reference_type:
00314 ret = parseTypeReferences();
00315 break;
00316 case DW_TAG_compile_unit:
00317 dwarf_printf("(0x%lx) Compilation unit, parsing children\n", id());
00318
00319 ret = parseChild();
00320 break;
00321 default:
00322 dwarf_printf("(0x%lx) Warning: unparsed entry with tag %x\n",
00323 id(), tag());
00324 ret = true;
00325 break;
00326 }
00327
00328 dwarf_printf("Finished parsing 0x%lx, ret %d, parseChild %d, parseSibling %d\n",
00329 id(), ret, parseChild(), parseSibling());
00330
00331 if (ret && parseChild() ) {
00332
00333 Dwarf_Die childDwarf;
00334 int status = dwarf_child( entry(), & childDwarf, NULL );
00335 DWARF_CHECK_RET(status == DW_DLV_ERROR);
00336 if (status == DW_DLV_OK) {
00337 if (!parse_int(childDwarf, true)) return false;
00338 }
00339 }
00340
00341 if (!parseSibling()) {
00342 dwarf_printf("(0x%lx) Skipping sibling parse\n", id());
00343 contexts_.pop();
00344 break;
00345 }
00346
00347 dwarf_printf("(0x%lx) Asking for sibling\n", id());
00348 Dwarf_Die siblingDwarf;
00349 int status = dwarf_siblingof( dbg(), entry(), & siblingDwarf, NULL );
00350
00351 DWARF_CHECK_RET(status == DW_DLV_ERROR);
00352
00353
00354 dwarf_dealloc( dbg(), entry(), DW_DLA_DIE );
00355
00356 contexts_.pop();
00357
00358 if (status != DW_DLV_OK) {
00359 break;
00360 }
00361
00362 e = siblingDwarf;
00363 }
00364 dwarf_printf("PARSE_INT exit, context size %d\n", (int) contexts_.c.size());
00365 return true;
00366 }
00367
00368 bool DwarfWalker::parseSubprogram() {
00369 dwarf_printf("(0x%lx) parseSubprogram entry\n", id());
00370
00371
00372 if (!findFuncName()) return false;
00373
00374
00375
00376 Type *returnType;
00377 if (!getReturnType(false, returnType)) return false;
00378
00379 if (curEnclosure() && !curFunc()) {
00380
00381
00382
00383 addFuncToContainer(returnType);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 bool foundFunc = false;
00395 if (!findFunction(foundFunc)) return false;
00396
00397 if (foundFunc) {
00398 if (parsedFuncs.find(curFunc()) != parsedFuncs.end()) {
00399 setParseChild(false);
00400 return true;
00401 }
00402 parsedFuncs.insert(curFunc());
00403 }
00404 else if (!curFunc()) {
00405
00406 setParseChild(false);
00407 return true;
00408 }
00409
00410 dwarf_printf("(0x%lx) Identified function name as %s\n", id(), curName().c_str());
00411
00412
00413 if (!getFrameBase()) return false;
00414
00415
00416
00417 parseLexicalBlock();
00418
00419
00420 bool isAbstractOrigin = false;
00421 if (!handleAbstractOrigin(isAbstractOrigin)) return false;
00422 if ( isAbstractOrigin ) {
00423 dwarf_printf("(0x%lx) Parsing abstract parent\n", id());
00424 if (!parse_int(abstractEntry(), false)) return false;
00425
00426 dwarf_dealloc(dbg(), abstractEntry(), DW_DLA_DIE);
00427 }
00428 else {
00429
00430
00431 bool hasSpecification = false;
00432 if (!handleSpecification(hasSpecification)) return false;
00433 if ( hasSpecification ) {
00434 dwarf_printf("(0x%lx) Parsing specification entry\n", id());
00435 if (!parse_int(specEntry(), false)) return false;
00436 }
00437 }
00438 return true;
00439 }
00440
00441 bool DwarfWalker::parseLexicalBlock() {
00442
00443
00444
00445
00446 dwarf_printf("(0x%lx) Parsing lexical block\n", id());
00447
00448 clearRanges();
00449 Dwarf_Bool hasLow = false;
00450 DWARF_FAIL_RET(dwarf_hasattr(entry(), DW_AT_low_pc, &hasLow, NULL));
00451
00452 Dwarf_Bool hasHigh = false;
00453 DWARF_FAIL_RET(dwarf_hasattr(entry(), DW_AT_high_pc, &hasHigh, NULL));
00454
00455 if (hasLow && hasHigh) {
00456 Address low, high;
00457 Address tempLow, tempHigh;
00458 if (!findConstant(DW_AT_low_pc, tempLow)) return false;
00459 if (!findConstant(DW_AT_high_pc, tempHigh)) return false;
00460 obj()->convertDebugOffset(tempLow, low);
00461 obj()->convertDebugOffset(tempHigh, high);
00462 dwarf_printf("(0x%lx) Lexical block from 0x%lx to 0x%lx\n", id(), low, high);
00463 setRange(make_pair(low, high));
00464 }
00465
00466 Dwarf_Bool hasRanges = false;
00467 DWARF_FAIL_RET(dwarf_hasattr(entry(), DW_AT_ranges, &hasRanges, NULL));
00468 if (hasRanges) {
00469 Address range_offset;
00470 if (!findConstant(DW_AT_ranges, range_offset)) return false;
00471
00472 Dwarf_Ranges *ranges = NULL;
00473 Dwarf_Signed ranges_length = 0;
00474 DWARF_FAIL_RET(dwarf_get_ranges_a(dbg(), (Dwarf_Off) range_offset, entry(),
00475 &ranges, &ranges_length, NULL, NULL));
00476
00477 bool done = false;
00478 for (unsigned i = 0; i < ranges_length && !done; i++) {
00479 Dwarf_Ranges *cur = ranges + i;
00480 Address cur_base = 0;
00481 switch (cur->dwr_type) {
00482 case DW_RANGES_ENTRY: {
00483 Address low = cur->dwr_addr1 + cur_base;
00484 Address high = cur->dwr_addr2 + cur_base;
00485 dwarf_printf("(0x%lx) Lexical block from 0x%lx to 0x%lx\n", id(), low, high);
00486 setRange(make_pair(low, high));
00487 break;
00488 }
00489 case DW_RANGES_ADDRESS_SELECTION:
00490 cur_base = cur->dwr_addr2;
00491 break;
00492 case DW_RANGES_END:
00493 done = true;
00494 break;
00495 }
00496 }
00497 }
00498
00499 return true;
00500 }
00501
00502 bool DwarfWalker::parseCommonBlock() {
00503 dwarf_printf("(0x%lx) Parsing common block\n", id());
00504
00505 char * commonBlockName_ptr;
00506 DWARF_FAIL_RET(dwarf_diename( entry(), & commonBlockName_ptr, NULL ));
00507 std::string commonBlockName = commonBlockName_ptr;
00508
00509 std::vector<Symbol *> commonBlockVars;
00510 if (!symtab()->findSymbol(commonBlockVars,
00511 commonBlockName,
00512 Symbol::ST_OBJECT,
00513 SymtabAPI::anyName)) {
00514
00515 std::string cbvname = commonBlockName + std::string("_");
00516 symtab()->findSymbol(commonBlockVars,
00517 cbvname,
00518 Symbol::ST_OBJECT,
00519 SymtabAPI::anyName);
00520 }
00521 if (commonBlockVars.empty()) {
00522 dwarf_printf("(0x%lx) Couldn't find variable for common block %s\n", id(), commonBlockName.c_str());
00523 return false;
00524 }
00525
00526 Symbol *commonBlockVar = commonBlockVars[0];
00527 assert(commonBlockVar);
00528
00529 typeCommon *commonBlockType = NULL;
00530
00531 commonBlockType = dynamic_cast<typeCommon *>(tc()->findVariableType(commonBlockName));
00532 if (commonBlockType == NULL) {
00533 commonBlockType = new typeCommon( (typeId_t) offset(), commonBlockName );
00534 assert( commonBlockType != NULL );
00535 tc()->addGlobalVariable( commonBlockName, commonBlockType );
00536 }
00537
00538 setCommon(commonBlockType);
00539
00540 return true;
00541 }
00542
00543 bool DwarfWalker::parseConstant() {
00544
00545 dwarf_printf("(0x%lx) Skipping named constant/variable with constant value\n", id());
00546 return true;
00547 }
00548
00549 bool DwarfWalker::parseVariable() {
00550 dwarf_printf("(0x%lx) ParseVariable entry\n", id());
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 bool hasSpecification = false;
00567 if (!handleSpecification(hasSpecification)) return false;
00568
00569 if (!findName(curName())) return false;
00570
00571 removeFortranUnderscore(curName());
00572
00573
00574
00575
00576 std::vector<VariableLocation> locs;
00577 if (!decodeLocationList(DW_AT_location, NULL, locs)) return false;
00578 if (locs.empty()) return true;
00579
00580 for (unsigned i=0; i<locs.size(); i++) {
00581
00582
00583 if (locs[i].lowPC) {
00584 Offset newlowpc = locs[i].lowPC;
00585 bool result = obj()->convertDebugOffset(locs[i].lowPC, newlowpc);
00586 if (result)
00587 locs[i].lowPC = newlowpc;
00588 }
00589 if (locs[i].hiPC) {
00590 Offset newhipc = locs[i].hiPC;
00591 bool result = obj()->convertDebugOffset(locs[i].hiPC, newhipc);
00592 if (result)
00593 locs[i].hiPC = newhipc;
00594 }
00595 }
00596
00597 Type *type = NULL;
00598 if (!findType(type, false)) return false;
00599
00600 Dwarf_Unsigned variableLineNo;
00601 bool hasLineNumber = false;
00602 std::string fileName;
00603
00604 if (curFunc() || curEnclosure()) {
00605 if (!getLineInformation(variableLineNo, hasLineNumber, fileName)) return false;
00606 }
00607
00608 if (!curFunc() && !curEnclosure()) {
00609
00610
00611 dwarf_printf("(0x%lx) Adding global variable\n", id());
00612
00613 Dyninst::Offset addr = 0;
00614 if (locs.size() && locs[0].stClass == storageAddr)
00615 addr = locs[0].frameOffset;
00616 Variable *var;
00617 bool result = symtab()->findVariableByOffset(var, addr);
00618 if (result) {
00619 var->setType(type);
00620 }
00621 tc()->addGlobalVariable( curName(), type);
00622 }
00623 else if (curFunc()) {
00624
00625
00626 if (!nameDefined()) return true;
00627
00628 localVar * newVariable = new localVar(curName(),
00629 type,
00630 fileName,
00631 (int) variableLineNo,
00632 curFunc());
00633 dwarf_printf("(0x%lx) localVariable '%s' (%p), currentFunction %p\n",
00634 id(), curName().c_str(), newVariable, curFunc());
00635
00636 for (unsigned int i = 0; i < locs.size(); ++i) {
00637 dwarf_printf("(0x%lx) (%s) Adding location %d of %d: (0x%lx - 0x%lx): %s, %s, %s, %ld\n",
00638 id(), newVariable->getName().c_str(), i+1, (int) locs.size(), locs[i].lowPC, locs[i].hiPC,
00639 storageClass2Str(locs[i].stClass),
00640 storageRefClass2Str(locs[i].refClass),
00641 locs[i].mr_reg.name().c_str(),
00642 locs[i].frameOffset);
00643 newVariable->addLocation(locs[i]);
00644 }
00645 curFunc()->addLocalVar(newVariable);
00646 }
00647 else if (curEnclosure()) {
00648 if (!nameDefined()) return true;
00649 assert( locs[0].stClass != storageRegOffset );
00650 dwarf_printf("(0x%lx) Adding variable to an enclosure\n", id());
00651
00652 curEnclosure()->addField( curName(), type, locs[0].frameOffset);
00653 }
00654 return true;
00655 }
00656
00657 bool DwarfWalker::parseFormalParam() {
00658 dwarf_printf("(0x%lx) Parsing formal parameter\n", id());
00659
00660
00661
00662
00663
00664
00665
00666 if (!curFunc()) {
00667 dwarf_printf("(0x%lx) No function defined, returning\n", id());
00668 return true;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 std::vector<VariableLocation> locs;
00684 if (!decodeLocationList(DW_AT_location, NULL, locs)) return false;
00685 if (locs.empty()) {
00686 dwarf_printf("(0x%lx) No locations associated with formal, returning\n", id());
00687 return true;
00688 }
00689
00690
00691
00692 bool hasAbstractOrigin;
00693 if (!handleAbstractOrigin(hasAbstractOrigin)) return false;
00694 if (hasAbstractOrigin) {
00695
00696 setSpecEntry(abstractEntry());
00697 }
00698
00699 if (!findName(curName())) return false;
00700
00701 if (!nameDefined()) {
00702 dwarf_printf("(0x%lx) No name associated with formal, returning\n", id());
00703 return true;
00704 }
00705
00706
00707 Type *paramType = NULL;
00708 if (!findType(paramType, false)) return false;
00709
00710 Dwarf_Unsigned lineNo = 0;
00711 bool hasLineNumber = false;
00712 std::string fileName;
00713 if (!getLineInformation(lineNo, hasLineNumber, fileName)) return false;
00714 localVar * newParameter = new localVar(curName(),
00715 paramType,
00716 fileName, (int) lineNo,
00717 curFunc());
00718 dwarf_printf("(0x%lx) Creating new formal parameter %s/%p (%s)/%s (%p)\n",
00719 id(),
00720 curName().c_str(),
00721 paramType, paramType->getName().c_str(),
00722 curFunc()->getAllMangledNames()[0].c_str(), curFunc());
00723
00724 assert( newParameter != NULL );
00725 for (unsigned int i = 0; i < locs.size(); ++i)
00726 {
00727 newParameter->addLocation(locs[i]);
00728 }
00729
00730
00731
00732 curFunc()->addParam(newParameter);
00733 return true;
00734 }
00735
00736 bool DwarfWalker::parseBaseType() {
00737 dwarf_printf("(0x%lx) parseBaseType entry\n", id());
00738
00739 if (!findName(curName())) return false;
00740 if (!nameDefined()) {
00741 dwarf_printf("(0x%lx) No name for type, returning early\n", id());
00742 return true;
00743 }
00744
00745 unsigned size = 0;
00746 if (!findSize(size)) return false;
00747
00748
00749
00750
00751 typeScalar * baseType = new typeScalar( (typeId_t) offset(), (unsigned int) size, curName());
00752 assert( baseType != NULL );
00753
00754
00755 typeScalar *debug = baseType;
00756 baseType = tc()->addOrUpdateType( baseType );
00757 dwarf_printf("(0x%lx) Created type %p / %s (pre add %p / %s) for id %d, size %d, in TC %p\n", id(),
00758 baseType, baseType->getName().c_str(),
00759 debug, debug->getName().c_str(),
00760 (int) offset(), size,
00761 tc());
00762
00763 return true;
00764 }
00765
00766 bool DwarfWalker::parseTypedef() {
00767 dwarf_printf("(0x%lx) parseTypedef entry\n", id());
00768
00769 if (!findName(curName())) return false;
00770
00771 Type *referencedType = NULL;
00772 if (!findType(referencedType, true)) return false;
00773
00774 if (!nameDefined()) {
00775 if (!fixName(curName(), referencedType)) return false;
00776 }
00777
00778 typeTypedef * typedefType = new typeTypedef( (typeId_t) offset(), referencedType, curName());
00779 typedefType = tc()->addOrUpdateType( typedefType );
00780
00781 return true;
00782 }
00783
00784 bool DwarfWalker::parseArray() {
00785 dwarf_printf("(0x%lx) Parsing array\n", id());
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 if (!findName(curName())) return false;
00800
00801
00802
00803 std::string nameToUse = curName();
00804
00805 Type *elementType = NULL;
00806 if (!findType(elementType, false)) return false;
00807 if (!elementType) return false;
00808
00809
00810 Dwarf_Die firstRange;
00811
00812 DWARF_FAIL_RET(dwarf_child( entry(), & firstRange, NULL ));
00813
00814 contexts_.push();
00815
00816 typeArray * baseArrayType = parseMultiDimensionalArray(firstRange,
00817 elementType);
00818
00819 contexts_.pop();
00820
00821 if (!baseArrayType) return false;
00822
00823 dwarf_dealloc( dbg(), firstRange, DW_DLA_DIE );
00824
00825
00826
00827
00828 dwarf_printf("(0x%lx) Creating array with base type %s, low bound %ld, high bound %ld, named %s\n",
00829 id(), baseArrayType->getBaseType()->getName().c_str(),
00830 baseArrayType->getLow(),
00831 baseArrayType->getHigh(),
00832 curName().c_str());
00833 typeArray *arrayType = new typeArray( (typeId_t) offset(),
00834 baseArrayType->getBaseType(),
00835 baseArrayType->getLow(),
00836 baseArrayType->getHigh(),
00837 nameToUse);
00838 assert( arrayType != NULL );
00839
00840 arrayType = tc()->addOrUpdateType( arrayType );
00841
00842
00843 setParseChild(false);
00844
00845 return true;
00846 }
00847
00848 bool DwarfWalker::parseSubrange() {
00849 dwarf_printf("(0x%lx) parseSubrange entry\n", id());
00850
00851 std::string loBound;
00852 std::string hiBound;
00853 parseSubrangeAUX(entry(), loBound, hiBound);
00854
00855 return true;
00856 }
00857
00858 bool DwarfWalker::parseEnum() {
00859 dwarf_printf("(0x%lx) parseEnum entry\n", id());
00860 if (!findName(curName())) return false;
00861
00862 typeEnum* enumerationType = new typeEnum( (typeId_t) offset(), curName());
00863 assert( enumerationType != NULL );
00864 enumerationType = dynamic_cast<typeEnum *>(tc()->addOrUpdateType( enumerationType ));
00865
00866 setEnum(enumerationType);
00867 return true;
00868 }
00869
00870 bool DwarfWalker::parseInheritance() {
00871 dwarf_printf("(0x%lx) parseInheritance entry\n", id());
00872
00873
00874 Type *superClass = NULL;
00875 if (!findType(superClass, false)) return false;
00876 if (!superClass) return false;
00877
00878 dwarf_printf("(0x%lx) Found %p as superclass\n", id(), superClass);
00879
00880 visibility_t visibility;
00881 if (!findVisibility(visibility)) return false;
00882
00883
00884
00885 std::string fName = "{superclass}";
00886 curEnclosure()->addField( fName, superClass, -1, visibility );
00887 dwarf_printf("(0x%lx) Added type %p as %s to %p\n", id(), superClass, fName.c_str(), curEnclosure());
00888 return true;
00889 }
00890
00891 bool DwarfWalker::parseStructUnionClass() {
00892 dwarf_printf("(0x%lx) parseStructUnionClass entry\n", id());
00893
00894 assert(tag() == DW_TAG_structure_type ||
00895 tag() == DW_TAG_union_type ||
00896 tag() == DW_TAG_class_type);
00897
00898 if (!findName(curName())) return false;
00899
00900 bool isDeclaration = false;
00901 if (!hasDeclaration(isDeclaration)) return false;
00902
00903 unsigned size;
00904 if (!findSize(size)) {
00905 if (isDeclaration) return true;
00906 else return false;
00907 }
00908
00909 fieldListType * containingType = NULL;
00910
00911 switch ( tag() ) {
00912 case DW_TAG_structure_type:
00913 case DW_TAG_class_type: {
00914 typeStruct *ts = new typeStruct( (typeId_t) offset(), curName());
00915 containingType = dynamic_cast<fieldListType *>(tc()->addOrUpdateType(ts));
00916 break;
00917 }
00918 case DW_TAG_union_type:
00919 {
00920 typeUnion *tu = new typeUnion( (typeId_t) offset(), curName());
00921 containingType = dynamic_cast<fieldListType *>(tc()->addOrUpdateType(tu));
00922 break;
00923 }
00924 }
00925 setEnclosure(containingType);
00926 dwarf_printf("(0x%lx) Started class, union, or struct: %p\n",
00927 id(), containingType);
00928 return true;
00929 }
00930
00931 bool DwarfWalker::parseEnumEntry() {
00932 dwarf_printf("(0x%lx) parseEnumEntry entry\n", id());
00933
00934 if (!findName(curName())) return false;
00935
00936 long value;
00937 bool valid;
00938 if (!findValue(value, valid)) return false;
00939
00940 curEnum()->addConstant(curName(), value);
00941 return true;
00942 }
00943
00944 bool DwarfWalker::parseMember() {
00945 dwarf_printf("(0x%lx) parseMember entry\n", id());
00946 if (!curEnclosure()) return false;
00947
00948 if (!findName(curName())) return false;
00949
00950 Type *memberType = NULL;
00951 if (!findType(memberType, false)) return false;
00952 if (!memberType) return false;
00953
00954 std::vector<VariableLocation> locs;
00955 Address initialStackValue = 0;
00956 if (!decodeLocationList(DW_AT_data_member_location, &initialStackValue, locs)) return false;
00957
00958
00959
00960
00961
00962
00963 long int memberSize = memberType->getSize();
00964
00965
00966 if (!fixBitFields(locs, memberSize)) return false;
00967
00968 int offset_to_use = locs.size() ? locs[0].frameOffset : -1;
00969
00970 dwarf_printf("(0x%lx) Using offset of 0x%lx\n", id(), offset_to_use);
00971
00972 if (nameDefined()) {
00973 curEnclosure()->addField( curName(), memberType, offset_to_use);
00974 }
00975 else {
00976 curEnclosure()->addField("[anonymous union]", memberType, offset_to_use);
00977 }
00978 return true;
00979 }
00980
00981
00982 bool DwarfWalker::parseConstPackedVolatile() {
00983 dwarf_printf("(0x%lx) parseConstPackedVolatile entry\n", id());
00984
00985 if (!findName(curName())) return false;
00986
00987 Type *type = NULL;
00988 if (!findType(type, true)) return false;
00989
00990 if (!nameDefined()) {
00991 if (!fixName(curName(), type)) return false;
00992 }
00993
00994 typeTypedef * modifierType = new typeTypedef((typeId_t) offset(), type, curName());
00995 assert( modifierType != NULL );
00996 modifierType = tc()->addOrUpdateType( modifierType );
00997 return true;
00998 }
00999
01000 bool DwarfWalker::parseTypeReferences() {
01001 dwarf_printf("(0x%lx) parseTypeReferences entry\n", id());
01002
01003 if (!findName(curName())) return false;
01004
01005 Type *typePointedTo = NULL;
01006 if (!findType(typePointedTo, true)) return false;
01007
01008 Type * indirectType = NULL;
01009 switch ( tag() ) {
01010 case DW_TAG_subroutine_type:
01011 indirectType = new typeFunction((typeId_t) offset(), typePointedTo, curName());
01012 indirectType = tc()->addOrUpdateType((typeFunction *) indirectType );
01013 break;
01014 case DW_TAG_ptr_to_member_type:
01015 case DW_TAG_pointer_type:
01016 indirectType = new typePointer((typeId_t) offset(), typePointedTo, curName());
01017 indirectType = tc()->addOrUpdateType((typePointer *) indirectType );
01018 break;
01019 case DW_TAG_reference_type:
01020 indirectType = new typeRef((typeId_t) offset(), typePointedTo, curName());
01021 indirectType = tc()->addOrUpdateType((typeRef *) indirectType );
01022 break;
01023 default:
01024 return false;
01025 }
01026
01027 assert( indirectType != NULL );
01028 return true;
01029 }
01030
01031 bool DwarfWalker::hasDeclaration(bool &isDecl) {
01032 Dwarf_Bool tmp;
01033 DWARF_FAIL_RET(dwarf_hasattr(entry(),
01034 DW_AT_declaration,
01035 &tmp, NULL ));
01036 isDecl = tmp;
01037 return true;
01038 }
01039
01040 bool DwarfWalker::findTag() {
01041 Dwarf_Half dieTag;
01042 DWARF_FAIL_RET(dwarf_tag( entry(), & dieTag, NULL ));
01043 setTag(dieTag);
01044 return true;
01045 }
01046
01047
01048 bool DwarfWalker::findOffset() {
01049 Dwarf_Off dieOffset;
01050 DWARF_FAIL_RET(dwarf_dieoffset( entry(), & dieOffset, NULL ));
01051
01052 setOffset(dieOffset);
01053 return true;
01054 }
01055
01056 bool DwarfWalker::findEntryToUse(Dwarf_Half attr, bool &found, Dwarf_Die &e) {
01057 Dwarf_Bool hasAttr;
01058 DWARF_FAIL_RET(dwarf_hasattr(entry(),
01059 attr,
01060 &hasAttr, NULL ));
01061 if (hasAttr) {
01062 e = entry();
01063 found = true;
01064 return true;
01065 }
01066
01067 DWARF_FAIL_RET(dwarf_hasattr(specEntry(),
01068 attr,
01069 &hasAttr, NULL ));
01070 if (hasAttr) {
01071 e = specEntry();
01072 found = true;
01073 return true;
01074 }
01075
01076 DWARF_FAIL_RET(dwarf_hasattr(abstractEntry(),
01077 attr,
01078 &hasAttr, NULL ));
01079 if (hasAttr) {
01080 e = abstractEntry();
01081 found = true;
01082 return true;
01083 }
01084 found = false;
01085 return true;
01086 }
01087
01088 bool DwarfWalker::handleAbstractOrigin(bool &isAbstract) {
01089 Dwarf_Die absE;
01090
01091 dwarf_printf("(0x%lx) Checking for abstract origin\n", id());
01092
01093 isAbstract = false;
01094 Dwarf_Bool isAbstractOrigin;
01095
01096 DWARF_FAIL_RET(dwarf_hasattr(entry(),
01097 DW_AT_abstract_origin,
01098 &isAbstractOrigin, NULL ));
01099
01100 if (!isAbstractOrigin) return true;
01101
01102 isAbstract = true;
01103 dwarf_printf("(0x%lx) abstract_origin is true, looking up reference\n", id());
01104
01105 Dwarf_Attribute abstractAttribute;
01106 DWARF_FAIL_RET(dwarf_attr( entry(), DW_AT_abstract_origin, & abstractAttribute, NULL ));
01107
01108 Dwarf_Off abstractOffset;
01109 DWARF_FAIL_RET(dwarf_global_formref( abstractAttribute, & abstractOffset, NULL ));
01110
01111 DWARF_FAIL_RET(dwarf_offdie( dbg(), abstractOffset, & absE, NULL));
01112
01113 dwarf_dealloc( dbg() , abstractAttribute, DW_DLA_ATTR );
01114
01115 setAbstractEntry(absE);
01116
01117 return true;
01118 }
01119
01120 bool DwarfWalker::handleSpecification(bool &hasSpec) {
01121 Dwarf_Die specE;
01122
01123 dwarf_printf("(0x%lx) Checking for separate specification\n", id());
01124 hasSpec = false;
01125
01126 Dwarf_Bool hasSpecification;
01127 DWARF_FAIL_RET(dwarf_hasattr( entry(), DW_AT_specification, & hasSpecification, NULL ));
01128
01129 if (!hasSpecification) return true;
01130
01131 hasSpec = true;
01132
01133 dwarf_printf("(0x%lx) Entry has separate specification, retrieving\n", id());
01134
01135 Dwarf_Attribute specAttribute;
01136 DWARF_FAIL_RET(dwarf_attr( entry(), DW_AT_specification, & specAttribute, NULL ));
01137
01138 Dwarf_Off specOffset;
01139 DWARF_FAIL_RET(dwarf_global_formref( specAttribute, & specOffset, NULL ));
01140
01141 DWARF_FAIL_RET(dwarf_offdie( dbg(), specOffset, & specE, NULL ));
01142
01143 dwarf_dealloc( dbg(), specAttribute, DW_DLA_ATTR );
01144
01145 setSpecEntry(specE);
01146
01147 return true;
01148 }
01149
01150 bool DwarfWalker::findName(std::string &name) {
01151 char *cname = NULL;
01152
01153 int status = dwarf_diename( specEntry(), &cname, NULL );
01154 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01155 if (status != DW_DLV_OK) {
01156 name = std::string();
01157 return true;
01158 }
01159
01160 name = cname;
01161 dwarf_printf("(0x%lx) Found name %s\n", id(), name.c_str());
01162 return true;
01163 }
01164
01165
01166 bool DwarfWalker::findFuncName() {
01167 dwarf_printf("(0x%lx) Checking for function name\n", id());
01168
01169 char *dwarfName = NULL;
01170
01171 Dwarf_Attribute linkageNameAttr;
01172
01173 int status = dwarf_attr( specEntry(), DW_AT_MIPS_linkage_name, & linkageNameAttr, NULL );
01174 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01175 if ( status == DW_DLV_OK ) {
01176 DWARF_FAIL_RET(dwarf_formstring( linkageNameAttr, &dwarfName, NULL ));
01177 curName() = dwarfName;
01178 dwarf_printf("(0x%lx) Found mangled name of %s, using\n", id(), curName().c_str());
01179 dwarf_dealloc( dbg(), linkageNameAttr, DW_DLA_ATTR );
01180 }
01181 else
01182 {
01183 if (!findName(curName())) return false;
01184 }
01185
01186 return true;
01187 }
01188
01189 bool DwarfWalker::findFunction(bool &found) {
01190 dwarf_printf("(0x%lx) Looking up function object matching %s\n", id(), curName().c_str());
01191
01192
01193 Dwarf_Addr entryAddr;
01194 Offset lowpc;
01195 int status = dwarf_lowpc(entry(), &entryAddr, NULL);
01196 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01197
01198 if (status == DW_DLV_OK
01199 && obj()->convertDebugOffset(entryAddr, lowpc)) {
01200 Function *tmp = NULL;
01201 if (symtab()->findFuncByEntryOffset(tmp, lowpc)) {
01202 setFunc(tmp);
01203 dwarf_printf("(0x%lx) Lookup by offset 0x%lx identifies %p\n",
01204 id(), lowpc, curFunc());
01205 found = true;
01206 return true;
01207 }
01208 }
01209 #if 0
01210 if (nameDefined()) {
01211 std::vector<Function *> ret_funcs;
01212 if (symtab()->findFunctionsByName(ret_funcs, curName())) {
01213 setFunc(ret_funcs[0]);
01214 dwarf_printf("(0x%lx) Found %ld possible matches, picking first: %p\n",
01215 id(), ret_funcs.size(), curFunc());
01216 return true;
01217 }
01218 }
01219 #endif
01220 dwarf_printf("(0x%lx) Failed to lookup by both name and address\n", id());
01221 return false;
01222 }
01223
01224 bool DwarfWalker::getFrameBase() {
01225 dwarf_printf("(0x%lx) Checking for frame pointer information\n", id());
01226
01227 std::vector<VariableLocation> &funlocs = curFunc()->getFramePtrRefForInit();
01228 if (!funlocs.empty()) {
01229 DWARF_CHECK_RET(false);
01230 }
01231
01232 if (!decodeLocationList(DW_AT_frame_base, NULL, funlocs)) return false;
01233 dwarf_printf("(0x%lx) After frame base decode, %d entries\n", id(), (int) funlocs.size());
01234
01235 return true;
01236 }
01237
01238 bool DwarfWalker::getReturnType(bool hasSpecification, Type *&returnType) {
01239 Dwarf_Attribute typeAttribute;
01240 int status = DW_DLV_OK;
01241
01242 if (hasSpecification) {
01243 status = dwarf_attr( specEntry(), DW_AT_type, & typeAttribute, NULL );
01244 }
01245 if (!hasSpecification || (status == DW_DLV_NO_ENTRY)) {
01246 status = dwarf_attr( entry(), DW_AT_type, & typeAttribute, NULL );
01247 }
01248
01249 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01250
01251 Type *voidType = tc()->findType("void");
01252
01253 if ( status == DW_DLV_NO_ENTRY ) {
01254 returnType = voidType;
01255 }
01256 else {
01257
01258 dwarf_printf("(0x%lx) Return type is not void\n", id());
01259 Dwarf_Off typeOffset;
01260
01261 DWARF_FAIL_RET(dwarf_global_formref( typeAttribute, & typeOffset, NULL ));
01262
01263
01264
01265
01266 returnType = tc()->findOrCreateType( (int) typeOffset );
01267
01268 dwarf_dealloc( dbg(), typeAttribute, DW_DLA_ATTR );
01269 }
01270 return true;
01271 }
01272
01273
01274
01275 bool DwarfWalker::addFuncToContainer(Type *returnType) {
01276
01277
01278
01279
01280 char * demangledName = P_cplus_demangle( curName().c_str(), symtab()->isNativeCompiler() );
01281 std::string toUse;
01282
01283 if (!demangledName) {
01284 dwarf_printf("(0x%lx) Unable to demangle %s, using it as mangled\n", id(), curName().c_str());
01285 toUse = curName();
01286 }
01287 else {
01288
01289 toUse = demangledName;
01290
01291 size_t offset = toUse.rfind(':');
01292 if (offset != toUse.npos) {
01293 toUse = toUse.substr(offset+1);
01294 }
01295 }
01296
01297 typeFunction *funcType = new typeFunction( (typeId_t) offset(), returnType, toUse);
01298 curEnclosure()->addField( toUse, funcType);
01299 free( demangledName );
01300 return true;
01301 }
01302
01303 bool DwarfWalker::findType(Type *&type, bool defaultToVoid) {
01304 int status;
01305
01306
01307 Dwarf_Attribute typeAttribute;
01308 status = dwarf_attr( specEntry(), DW_AT_type, & typeAttribute, NULL );
01309 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01310
01311 if (status == DW_DLV_NO_ENTRY) {
01312 if (defaultToVoid) {
01313 type = tc()->findType("void");
01314 }
01315 return true;
01316 }
01317
01318 Dwarf_Off typeOffset;
01319 DWARF_FAIL_RET(dwarf_global_formref( typeAttribute, & typeOffset, NULL ));
01320 dwarf_printf("(0x%lx) Returned type offset 0x%x\n", id(), (int) typeOffset);
01321
01322
01323 type = tc()->findOrCreateType( (int) typeOffset );
01324 dwarf_printf("(0x%lx) Returning type %p / %s for id 0x%lx\n",
01325 id(),
01326 type, type->getName().c_str(),
01327 (long) typeOffset);
01328 dwarf_dealloc( dbg(), typeAttribute, DW_DLA_ATTR );
01329 return true;
01330 }
01331
01332 bool DwarfWalker::getLineInformation(Dwarf_Unsigned &variableLineNo,
01333 bool &hasLineNumber,
01334 std::string &fileName) {
01335 Dwarf_Attribute fileDeclAttribute;
01336 int status = dwarf_attr( specEntry(), DW_AT_decl_file, & fileDeclAttribute, NULL );
01337 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01338
01339 if (status == DW_DLV_NO_ENTRY) {
01340 fileName = "";
01341 }
01342 else if (status == DW_DLV_OK) {
01343 Dwarf_Unsigned fileNameDeclVal;
01344 DWARF_FAIL_RET(dwarf_formudata(fileDeclAttribute, &fileNameDeclVal, NULL));
01345 dwarf_dealloc( dbg(), fileDeclAttribute, DW_DLA_ATTR );
01346 fileName = srcFiles()[fileNameDeclVal-1];
01347 }
01348 else {
01349 return true;
01350 }
01351
01352 Dwarf_Attribute lineNoAttribute;
01353 status = dwarf_attr( specEntry(), DW_AT_decl_line, & lineNoAttribute, NULL );
01354 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01355 if (status != DW_DLV_OK) return true;
01356
01357
01358
01359 hasLineNumber = true;
01360 DWARF_FAIL_RET(dwarf_formudata( lineNoAttribute, & variableLineNo, NULL ));
01361 dwarf_dealloc( dbg(), lineNoAttribute, DW_DLA_ATTR );
01362
01363 return true;
01364 }
01365
01366 bool DwarfWalker::decodeLocationList(Dwarf_Half attr,
01367 Address *initialStackValue,
01368 std::vector<VariableLocation> &locs) {
01369 dwarf_printf("(0x%lx) decodeLocationList for attr %d\n", id(), attr);
01370
01371 Dwarf_Bool hasAttr = false;
01372 DWARF_FAIL_RET(dwarf_hasattr(entry(), attr, &hasAttr, NULL));
01373
01374 if (!hasAttr) {
01375 dwarf_printf("(0x%lx): no such attribute\n", id());
01376 return true;
01377 }
01378
01379 locs.clear();
01380
01381
01382 Dwarf_Attribute locationAttribute;
01383 DWARF_FAIL_RET(dwarf_attr( entry(), attr, & locationAttribute, NULL ));
01384
01385 bool isExpr = false;
01386 bool isConstant = false;
01387 Dwarf_Half form;
01388 if (!checkForConstantOrExpr(attr, locationAttribute, isConstant, isExpr, form))
01389 return false;
01390 dwarf_printf("(0x%lx) After checkForConstantOrExpr, form class is 0x%x\n",id(), form);
01391 if (isConstant) {
01392 dwarf_printf("(0x%lx) Decoding constant location\n", id());
01393 if (!decodeConstantLocation(locationAttribute, form, locs)) return false;
01394 }
01395 else if (isExpr) {
01396 dwarf_printf("(0x%lx) Decoding expression without location list\n", id());
01397 if (!decodeExpression(locationAttribute, locs)) return false;
01398 }
01399 else {
01400 dwarf_printf("(0x%lx) Decoding loclist location\n", id());
01401 Dwarf_Locdesc **locationList;
01402 Dwarf_Signed listLength;
01403 int status = dwarf_loclist_n( locationAttribute, & locationList, & listLength, NULL );
01404
01405 dwarf_dealloc( dbg(), locationAttribute, DW_DLA_ATTR );
01406
01407 if (status != DW_DLV_OK) {
01408
01409
01410 dwarf_printf("(0x%lx) Failed loclist decode: %d\n", id(), status);
01411 return true;
01412 }
01413
01414 dwarf_printf("(0x%lx) location list with %d entries found\n", id(), (int) listLength);
01415
01416 if (!decodeLocationListForStaticOffsetOrAddress( locationList,
01417 listLength,
01418 locs,
01419 initialStackValue)) return false;
01420
01421 deallocateLocationList( locationList, listLength );
01422 }
01423
01424 return true;
01425 }
01426
01427 bool DwarfWalker::checkForConstantOrExpr(Dwarf_Half attr,
01428 Dwarf_Attribute &locationAttribute,
01429 bool &constant,
01430 bool &expr,
01431 Dwarf_Half &form) {
01432 constant = false;
01433
01434 DWARF_FAIL_RET(dwarf_whatform(locationAttribute, &form, NULL));
01435
01436
01437 Dwarf_Form_Class formtype = dwarf_get_form_class(version, attr, offset_size, form);
01438 dwarf_printf("(0x%lx) Checking for constant, formtype is 0x%x looking for 0x%x\n", id(), formtype, DW_FORM_CLASS_CONSTANT);
01439
01440 if (formtype == DW_FORM_CLASS_CONSTANT) {
01441 constant = true;
01442 }
01443 else if (formtype == DW_FORM_CLASS_EXPRLOC) {
01444 expr = true;
01445 }
01446 return true;
01447 }
01448
01449 bool DwarfWalker::findConstant(Dwarf_Half attr,
01450 Address &value) {
01451 Dwarf_Bool has = false;
01452 DWARF_FAIL_RET(dwarf_hasattr(entry(), attr, &has, NULL));
01453 if (!has) return false;
01454
01455
01456 Dwarf_Attribute d_attr;
01457 DWARF_FAIL_RET(dwarf_attr(entry(), attr, &d_attr, NULL));
01458
01459 Dwarf_Half form;
01460
01461 DWARF_FAIL_RET(dwarf_whatform(d_attr, &form, NULL));
01462
01463 return findConstantWithForm(d_attr, form, value);
01464 }
01465
01466 bool DwarfWalker::findConstantWithForm(Dwarf_Attribute &locationAttribute,
01467 Dwarf_Half form,
01468 Address &value) {
01469 value = 0;
01470
01471 switch(form) {
01472 case DW_FORM_addr:
01473 Dwarf_Addr addr;
01474 DWARF_FAIL_RET(dwarf_formaddr(locationAttribute, &addr, NULL));
01475 value = (Address) addr;
01476 return true;
01477 case DW_FORM_sdata:
01478 Dwarf_Signed s_tmp;
01479 DWARF_FAIL_RET(dwarf_formsdata(locationAttribute, &s_tmp, NULL));
01480 value = (Address) s_tmp;
01481 dwarf_printf("(0x%lx) Decoded data of form %x to 0x%lx\n",
01482 id(), form, value);
01483 return true;
01484 case DW_FORM_data1:
01485 case DW_FORM_data2:
01486 case DW_FORM_data4:
01487 case DW_FORM_data8:
01488 case DW_FORM_udata:
01489 Dwarf_Unsigned u_tmp;
01490 DWARF_FAIL_RET(dwarf_formudata(locationAttribute, &u_tmp, NULL));
01491 value = (Address) u_tmp;
01492 return true;
01493 default:
01494 dwarf_printf("(0x%lx) Unhandled form 0x%x for constant decode\n", id(), (unsigned) form);
01495 return false;
01496 }
01497 }
01498
01499 bool DwarfWalker::decodeConstantLocation(Dwarf_Attribute &attr, Dwarf_Half form,
01500 std::vector<VariableLocation> &locs) {
01501 Address value;
01502 if (!findConstantWithForm(attr, form, value)) return false;
01503 if (!constructConstantVariableLocation(value, locs)) return false;
01504 return true;
01505 }
01506
01507 bool DwarfWalker::constructConstantVariableLocation(Address value,
01508 std::vector<VariableLocation> &locs) {
01509
01510 VariableLocation loc;
01511 loc.stClass = storageAddr;
01512 loc.refClass = storageNoRef;
01513 loc.frameOffset = value;
01514
01515
01516 if (hasRanges()) {
01517 for (range_set_t::iterator i = ranges_begin(); i != ranges_end(); i++) {
01518 pair<Address, Address> range = *i;
01519 loc.lowPC = range.first;
01520 loc.hiPC = range.second;
01521 locs.push_back(loc);
01522 }
01523 }
01524 else {
01525 loc.lowPC = (Address) 0;
01526 loc.hiPC = (Address) -1;
01527 locs.push_back(loc);
01528 }
01529
01530 return true;
01531 }
01532
01533 bool DwarfWalker::findSize(unsigned &size) {
01534 Dwarf_Bool hasSize;
01535 DWARF_FAIL_RET(dwarf_hasattr(entry(), DW_AT_byte_size, &hasSize, NULL));
01536 if (!hasSize) return false;
01537
01538 Dwarf_Attribute byteSizeAttr;
01539 Dwarf_Unsigned byteSize;
01540 DWARF_FAIL_RET(dwarf_attr( specEntry(), DW_AT_byte_size, & byteSizeAttr, NULL ));
01541
01542 DWARF_FAIL_RET(dwarf_formudata( byteSizeAttr, & byteSize, NULL ));
01543
01544 dwarf_dealloc( dbg(), byteSizeAttr, DW_DLA_ATTR );
01545 size = (unsigned) byteSize;
01546 return true;
01547 }
01548
01549 bool DwarfWalker::findVisibility(visibility_t &visibility) {
01550
01551
01552 Dwarf_Attribute visAttr;
01553 int status = dwarf_attr( entry(), DW_AT_accessibility, & visAttr, NULL );
01554 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01555 if (status != DW_DLV_OK) {
01556 visibility = visPrivate;
01557 return true;
01558 }
01559
01560 Dwarf_Unsigned visValue;
01561 DWARF_FAIL_RET(dwarf_formudata( visAttr, & visValue, NULL ));
01562
01563 switch( visValue ) {
01564 case DW_ACCESS_public: visibility = visPublic; break;
01565 case DW_ACCESS_protected: visibility = visProtected; break;
01566 case DW_ACCESS_private: visibility = visPrivate; break;
01567 default:
01568
01569 break;
01570 }
01571
01572 dwarf_dealloc( dbg(), visAttr, DW_DLA_ATTR );
01573
01574 return true;
01575 }
01576
01577 bool DwarfWalker::findValue(long &value, bool &valid) {
01578 Dwarf_Attribute valueAttr;
01579 int status = dwarf_attr( entry(), DW_AT_const_value, & valueAttr, NULL );
01580 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01581
01582 if (status != DW_DLV_OK) {
01583 valid = false;
01584 return true;
01585 }
01586
01587 Dwarf_Signed enumValue;
01588
01589 DWARF_FAIL_RET(dwarf_formsdata(valueAttr, &enumValue, NULL));
01590
01591 value = enumValue;
01592 valid = true;
01593
01594 dwarf_dealloc( dbg(), valueAttr, DW_DLA_ATTR );
01595 return true;
01596 }
01597
01598 bool DwarfWalker::fixBitFields(std::vector<VariableLocation> &locs,
01599 long &size) {
01600 Dwarf_Attribute bitOffset;
01601 int status = dwarf_attr( entry(), DW_AT_bit_offset, & bitOffset, NULL );
01602 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01603
01604 if ( status == DW_DLV_OK && locs.size() )
01605 {
01606 Dwarf_Unsigned memberOffset_du = locs[0].frameOffset;
01607
01608 DWARF_FAIL_RET(dwarf_formudata( bitOffset, &memberOffset_du, NULL ));
01609
01610 dwarf_dealloc( dbg(), bitOffset, DW_DLA_ATTR );
01611
01612 Dwarf_Attribute bitSize;
01613 DWARF_FAIL_RET(dwarf_attr( entry(), DW_AT_bit_size, & bitSize, NULL ));
01614
01615 Dwarf_Unsigned memberSize_du = size;
01616 DWARF_FAIL_RET(dwarf_formudata( bitSize, &memberSize_du, NULL ));
01617
01618 dwarf_dealloc( dbg(), bitSize, DW_DLA_ATTR );
01619
01620
01621
01622
01623 }
01624 else
01625 {
01626 if (locs.size())
01627 locs[0].frameOffset *= 8;
01628 size *= 8;
01629 }
01630 return true;
01631 }
01632
01633 bool DwarfWalker::fixName(std::string &name, Type *type) {
01634 switch(tag()){
01635 case DW_TAG_const_type:
01636 name = std::string("const ") + type->getName();
01637 break;
01638 case DW_TAG_packed_type:
01639 name = std::string("packed ") + type->getName();
01640 break;
01641 case DW_TAG_volatile_type:
01642 name = std::string("volatile ") + type->getName();
01643 break;
01644 default:
01645 return false;
01646 }
01647 return true;
01648 }
01649
01650 void DwarfWalker::removeFortranUnderscore(std::string &name) {
01651
01652 if (!curFunc() && !curEnclosure()) return;
01653
01654 supportedLanguages lang = mod()->language();
01655 if ((lang != lang_Fortran) &&
01656 (lang != lang_CMFortran) &&
01657 (lang != lang_Fortran_with_pretty_debug)) return;
01658
01659 if (name[name.length()-1] == '_') {
01660 name = name.substr(0, name.length()-1);
01661 }
01662 }
01663
01664 bool DwarfWalker::parseSubrangeAUX(Dwarf_Die entry,
01665 std::string &loBound,
01666 std::string &hiBound) {
01667 dwarf_printf("(0x%lx) Parsing subrange /w/ auxiliary function\n", id());
01668 loBound = "{unknown or default}";
01669 hiBound = "{unknown or default}";
01670
01671
01672 switch ( mod()->language() ) {
01673 case lang_Fortran:
01674 case lang_Fortran_with_pretty_debug:
01675 case lang_CMFortran:
01676 loBound = "1";
01677 break;
01678 case lang_C:
01679 case lang_CPlusPlus:
01680 loBound = "0";
01681 break;
01682 default:
01683 break;
01684 }
01685
01686
01687 Dwarf_Attribute lowerBoundAttribute;
01688 int status = dwarf_attr( entry, DW_AT_lower_bound, & lowerBoundAttribute, NULL );
01689 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01690
01691 if ( status == DW_DLV_OK ) {
01692 if (!decipherBound(lowerBoundAttribute, loBound )) return false;
01693 dwarf_dealloc( dbg(), lowerBoundAttribute, DW_DLA_ATTR );
01694 }
01695
01696
01697 Dwarf_Attribute upperBoundAttribute;
01698 status = dwarf_attr( entry, DW_AT_upper_bound, & upperBoundAttribute, NULL );
01699 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01700
01701 if ( status == DW_DLV_NO_ENTRY ) {
01702 status = dwarf_attr( entry, DW_AT_count, & upperBoundAttribute, NULL );
01703 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01704 }
01705
01706 if ( status == DW_DLV_OK ) {
01707 if (!decipherBound(upperBoundAttribute, hiBound )) return false;
01708 dwarf_dealloc( dbg(), upperBoundAttribute, DW_DLA_ATTR );
01709 }
01710
01711
01712 if (!findName(curName())) return false;
01713 if (!nameDefined()) {
01714 curName() = "{anonymousRange}";
01715 }
01716
01717 Dwarf_Off subrangeOffset;
01718 DWARF_ERROR_RET(dwarf_dieoffset( entry, & subrangeOffset, NULL ));
01719
01720 errno = 0;
01721 unsigned long low_conv = strtoul(loBound.c_str(), NULL, 10);
01722 if (errno) {
01723 low_conv = LONG_MIN;
01724 }
01725
01726 errno = 0;
01727 unsigned long hi_conv = strtoul(hiBound.c_str(), NULL, 10);
01728 if (errno) {
01729 hi_conv = LONG_MAX;
01730 }
01731 dwarf_printf("(0x%lx) Adding subrange type: id %d, low %ld, high %ld, named %s\n",
01732 id(), (int) subrangeOffset,
01733 low_conv, hi_conv, curName().c_str());
01734 typeSubrange * rangeType = new typeSubrange( (int) subrangeOffset,
01735 0, low_conv, hi_conv, curName() );
01736 assert( rangeType != NULL );
01737 rangeType = tc()->addOrUpdateType( rangeType );
01738 dwarf_printf("(0x%lx) Subrange has pointer %p (tc %p)\n", id(), rangeType, tc());
01739 return true;
01740 }
01741
01742 typeArray *DwarfWalker::parseMultiDimensionalArray(Dwarf_Die range,
01743 Type * elementType)
01744 {
01745 char buf[32];
01746
01747 Dwarf_Off dieOffset;
01748 DWARF_FAIL_RET(dwarf_dieoffset( range, & dieOffset, NULL ));
01749
01750
01751 std::string loBound;
01752 std::string hiBound;
01753 parseSubrangeAUX(range, loBound, hiBound);
01754
01755
01756 Dwarf_Die nextSibling;
01757 int status = dwarf_siblingof( dbg(), range, & nextSibling, NULL );
01758 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01759
01760 snprintf(buf, 31, "__array%d", (int) offset());
01761
01762 if ( status == DW_DLV_NO_ENTRY ) {
01763
01764
01765
01766
01767 std::string aName = buf;
01768 typeArray* innermostType = new typeArray( elementType,
01769 atoi( loBound.c_str() ),
01770 atoi( hiBound.c_str() ),
01771 aName );
01772 assert( innermostType != NULL );
01773 Type * typ = tc()->addOrUpdateType( innermostType );
01774 innermostType = dynamic_cast<typeArray *>(typ);
01775 return innermostType;
01776 }
01777
01778
01779 typeArray * innerType = parseMultiDimensionalArray( nextSibling, elementType);
01780 assert( innerType != NULL );
01781
01782 std::string aName = buf;
01783 typeArray * outerType = new typeArray( innerType, atoi(loBound.c_str()), atoi(hiBound.c_str()), aName);
01784 assert( outerType != NULL );
01785 Type *typ = tc()->addOrUpdateType( outerType );
01786 outerType = static_cast<typeArray *>(typ);
01787
01788 dwarf_dealloc( dbg(), nextSibling, DW_DLA_DIE );
01789 return outerType;
01790 }
01791
01792 bool DwarfWalker::decipherBound(Dwarf_Attribute boundAttribute, std::string &boundString ) {
01793 Dwarf_Half boundForm;
01794 DWARF_FAIL_RET(dwarf_whatform( boundAttribute, & boundForm, NULL ));
01795
01796 switch( boundForm ) {
01797 case DW_FORM_data1:
01798 case DW_FORM_data2:
01799 case DW_FORM_data4:
01800 case DW_FORM_data8:
01801 case DW_FORM_udata:
01802 {
01803 dwarf_printf("(0x%lx) Decoding form %d with formudata\n",
01804 id(), boundForm);
01805
01806 Dwarf_Unsigned constantBound;
01807 DWARF_FAIL_RET(dwarf_formudata( boundAttribute, & constantBound, NULL ));
01808 char bString[40];
01809 sprintf(bString, "%llu", (unsigned long long)constantBound);
01810 boundString = bString;
01811 return true;
01812 } break;
01813
01814 case DW_FORM_sdata:
01815 {
01816 dwarf_printf("(0x%lx) Decoding form %d with formsdata\n",
01817 id(), boundForm);
01818
01819 Dwarf_Signed constantBound;
01820 DWARF_FAIL_RET(dwarf_formsdata( boundAttribute, & constantBound, NULL ));
01821 char bString[40];
01822 sprintf(bString, "%lld", (long long)constantBound);
01823 boundString = bString;
01824 return true;
01825 } break;
01826
01827 case DW_FORM_ref_addr:
01828 case DW_FORM_ref1:
01829 case DW_FORM_ref2:
01830 case DW_FORM_ref4:
01831 case DW_FORM_ref8:
01832 case DW_FORM_ref_udata:
01833 {
01834
01835 Dwarf_Off boundOffset;
01836 DWARF_FAIL_RET(dwarf_global_formref( boundAttribute, & boundOffset, NULL ));
01837
01838 Dwarf_Die boundEntry;
01839 DWARF_FAIL_RET(dwarf_offdie( dbg(), boundOffset, & boundEntry, NULL ));
01840
01841
01842 char * boundName = NULL;
01843 int status = dwarf_diename( boundEntry, & boundName, NULL );
01844 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01845
01846 if ( status == DW_DLV_OK ) {
01847 boundString = boundName;
01848
01849 dwarf_dealloc( dbg(), boundName, DW_DLA_STRING );
01850 return true;
01851 }
01852
01853
01854 Dwarf_Attribute constBoundAttribute;
01855 status = dwarf_attr( boundEntry, DW_AT_const_value, & constBoundAttribute, NULL );
01856 DWARF_CHECK_RET(status == DW_DLV_ERROR);
01857
01858 if ( status == DW_DLV_OK ) {
01859 Dwarf_Unsigned constBoundValue;
01860 DWARF_FAIL_RET(dwarf_formudata( constBoundAttribute, & constBoundValue, NULL ));
01861
01862 char bString[40];
01863 sprintf(bString, "%lu", (unsigned long)constBoundValue);
01864 boundString = bString;
01865
01866 dwarf_dealloc( dbg(), boundEntry, DW_DLA_DIE );
01867 dwarf_dealloc( dbg(), constBoundAttribute, DW_DLA_ATTR );
01868 return true;
01869 }
01870
01871 return false;
01872 } break;
01873 case DW_FORM_block:
01874 case DW_FORM_block1:
01875 {
01876
01877
01878
01879
01880
01881 boundString = "{PGI extension}";
01882 return false;
01883 } break;
01884
01885 default:
01886
01887 boundString = "{invalid bound form}";
01888 return false;
01889 break;
01890 }
01891 return true;
01892 }
01893
01894 bool DwarfWalker::decodeExpression(Dwarf_Attribute &attr,
01895 std::vector<VariableLocation> &locs) {
01896 Dwarf_Unsigned expr_len;
01897 Dwarf_Ptr expr_ptr;
01898 DWARF_FAIL_RET(dwarf_formexprloc(attr, &expr_len, &expr_ptr, NULL));
01899 unsigned char *bitstream = (unsigned char *) expr_ptr;
01900
01901
01902
01903
01904 dwarf_printf("(0x%lx) bitstream for expr has len %d\n", id(), expr_len);
01905 for (unsigned i = 0; i < expr_len; ++i) {
01906 dwarf_printf("(0x%lx) \t %#hhx\n", id(), bitstream[i]);
01907 }
01908
01909 Dwarf_Signed cnt;
01910 Dwarf_Locdesc *descs;
01911
01912 DWARF_FAIL_RET(dwarf_loclist_from_expr_a(dbg(), expr_ptr, expr_len, addr_size,
01913 &descs, &cnt, NULL));
01914
01915 bool ret = decodeLocationListForStaticOffsetOrAddress(&descs, cnt, locs, NULL);
01916
01917 return ret;
01918 }
01919
01920 bool DwarfWalker::decodeLocationListForStaticOffsetOrAddress( Dwarf_Locdesc **locationList,
01921 Dwarf_Signed listLength,
01922 std::vector<VariableLocation>& locs,
01923 Address * initialStackValue)
01924 {
01925 locs.clear();
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952 for (unsigned locIndex = 0 ; locIndex < listLength; locIndex++) {
01953
01954
01955 Dwarf_Locdesc *location = locationList[locIndex];
01956
01957 VariableLocation loc;
01958
01959 loc.stClass = storageAddr;
01960 loc.refClass = storageNoRef;
01961
01962
01963
01964
01965 dwarf_printf("(0x%lx) Decoding entry %d of %d over range 0x%lx - 0x%lx, mod 0x%lx - 0x%lx\n",
01966 id(), locIndex+1, (int) listLength,
01967 (long) location->ld_lopc,
01968 (long) location->ld_hipc,
01969 modLow, modHigh);
01970
01971 long int *tmp = (long int *)initialStackValue;
01972 bool result = decodeDwarfExpression(location, tmp, loc,
01973 symtab()->getArchitecture());
01974 if (!result) {
01975 dwarf_printf("(0x%lx): decodeDwarfExpr failed\n", id());
01976 return false;
01977 }
01978
01979 if (location->ld_lopc == 0 &&
01980 location->ld_hipc == (Dwarf_Addr) ~0) {
01981
01982
01983 if (hasRanges()) {
01984 dwarf_printf("(0x%lx) Using lexical range\n", id());
01985 for (range_set_t::iterator i = ranges_begin(); i != ranges_end(); i++) {
01986 pair<Address, Address> range = *i;
01987 loc.lowPC = range.first;
01988 loc.hiPC = range.second;
01989
01990 dwarf_printf("(0x%lx) Variable valid over range 0x%lx to 0x%lx\n",
01991 id(), loc.lowPC, loc.hiPC);
01992 locs.push_back(loc);
01993 }
01994 }
01995 else {
01996 dwarf_printf("(0x%lx) Using open location range\n", id());
01997 loc.lowPC = location->ld_lopc;
01998 loc.hiPC = location->ld_hipc;
01999
02000 dwarf_printf("(0x%lx) Variable valid over range 0x%lx to 0x%lx\n",
02001 id(), loc.lowPC, loc.hiPC);
02002 locs.push_back(loc);
02003 }
02004 }
02005 else {
02006 dwarf_printf("(0x%lx) Using lexical range, shifted by module low\n", id());
02007 loc.lowPC = location->ld_lopc + modLow;
02008 loc.hiPC = location->ld_hipc + modLow;
02009
02010 dwarf_printf("(0x%lx) Variable valid over range 0x%lx to 0x%lx\n",
02011 id(), loc.lowPC, loc.hiPC);
02012 locs.push_back(loc);
02013 }
02014 }
02015
02016
02017 return true;
02018 }
02019
02020 void DwarfWalker::deallocateLocationList( Dwarf_Locdesc * locationList,
02021 Dwarf_Signed listLength )
02022 {
02023 for( int i = 0; i < listLength; i++ ) {
02024 dwarf_dealloc( dbg(), locationList[i].ld_s, DW_DLA_LOC_BLOCK );
02025 }
02026 dwarf_dealloc( dbg(), locationList, DW_DLA_LOCDESC );
02027 }
02028
02029 void DwarfWalker::deallocateLocationList( Dwarf_Locdesc ** locationList,
02030 Dwarf_Signed listLength )
02031 {
02032 for( int i = 0; i < listLength; i++ ) {
02033 dwarf_dealloc( dbg(), locationList[i]->ld_s, DW_DLA_LOC_BLOCK );
02034 dwarf_dealloc( dbg(), locationList[i], DW_DLA_LOCDESC );
02035 }
02036 dwarf_dealloc( dbg(), locationList, DW_DLA_LIST );
02037 }
02038
02039 void DwarfWalker::setEntry(Dwarf_Die entry) {
02040 contexts_.setEntry(entry);
02041 contexts_.setSpecEntry(entry);
02042 contexts_.setAbstractEntry(entry);
02043 }
02044 void DwarfWalker::Contexts::push() {
02045 if (c.empty()) {
02046 c.push(Context());
02047 }
02048 else {
02049 c.push(Context(c.top()));
02050 }
02051 }
02052
02053 void DwarfWalker::Contexts::pop() {
02054 assert(!c.empty());
02055 c.pop();
02056 }
02057
02058 void DwarfWalker::Contexts::setFunc(Function *f) {
02059
02060
02061
02062 c.top().func = f;
02063 clearRanges();
02064 }
02065
02066 void DwarfWalker::Contexts::clearFunc() {
02067
02068
02069 std::stack<Context> repl;
02070 while (!c.empty()) {
02071 repl.push(c.top());
02072 c.pop();
02073 }
02074
02075 while (!repl.empty()) {
02076 c.push(repl.top());
02077 c.top().func = NULL;
02078 repl.pop();
02079 }
02080 }