dwarfWalker.C

Go to the documentation of this file.
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    /* Start the dwarven debugging. */
00058    Module *fixUnknownMod = NULL;
00059    mod_ = NULL;
00060    
00061    /* Iterate over the compilation-unit headers. */
00062    while (dwarf_next_cu_header_c(dbg(),
00063                                  (Dwarf_Bool) 1, // Operate on .debug_info, not .debug_types
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    /* Fix type list. */
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    } /* end iteration over types. */
00092    
00093    /* Fix the types of variables. */   
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       } /* end if data class is unknown but the type exists. */
00104    } /* end iteration over variables. */
00105       
00106    moduleTypes->setDwarfParsed();
00107    return true;
00108 }
00109 
00110 bool DwarfWalker::parseModule(Module *&fixUnknownMod) {
00111    /* Obtain the module DIE. */
00112    Dwarf_Die moduleDIE;
00113    DWARF_FAIL_RET(dwarf_siblingof( dbg(), NULL, &moduleDIE, NULL ));
00114    
00115    /* Make sure we've got the right one. */
00116    Dwarf_Half moduleTag;
00117    DWARF_FAIL_RET(dwarf_tag( moduleDIE, & moduleTag, NULL ));
00118 
00119    /* Get its offset */
00120    Dwarf_Off dieOffset;
00121    DWARF_FAIL_RET(dwarf_dieoffset( moduleDIE, &dieOffset, NULL));
00122    // By observation, the module always starts 0xb into the header.
00123    // Someday we should dig out a direct way of doing this. 
00124    compile_offset = (dieOffset - 0xb);
00125 
00126    if (moduleTag != DW_TAG_compile_unit) return false;
00127    
00128    /* Extract the name of this module. */
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    /* Set the language, if any. */
00145    Dwarf_Attribute languageAttribute;
00146    DWARF_ERROR_RET(dwarf_attr( moduleDIE, DW_AT_language, & languageAttribute, NULL ));
00147    
00148    // Set low and high ranges; this can fail, so don't check return addr.
00149    setEntry(moduleDIE);
00150 
00151    // These may not be set.
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 // As mentioned in the header, this is separate from parse()
00210 // so we can have a non-Context-creating parse method that reuses
00211 // the Context from the parent. This allows us to pass in current
00212 // function, etc. without the Context stack exploding
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    // We escape the loop by checking parseSibling() after 
00216    // parsing this DIE and its children, if any
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       // Insert only inserts the first time; we need that behavior
00236       enclosureMap.insert(std::make_pair(offset(), curEnclosure()));
00237       
00238       bool ret = false;
00239       
00240    // BLUEGENE BUG HACK
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     // XLC compilers nest a bunch of stuff under an invented function; however,
00246     // this is broken (they don't close the function properly). If we see a 
00247     // tag like this, close off the previous function immediately
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             /* If the pointer specifies argument types, this DIE has
00310                children of those types. */
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             // Parse child
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          // Parse children
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       /* Deallocate the entry we just parsed. */
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    // Name first
00372    if (!findFuncName()) return false;
00373 
00374    // Get the return type
00375    //if (!getReturnType(hasSpecification)) return false;
00376    Type *returnType;
00377    if (!getReturnType(false, returnType)) return false;
00378 
00379    if (curEnclosure() && !curFunc()) {
00380       // This is a member function; create the type entry
00381       // Since curFunc is false, we're not going back to reparse this
00382       // entry with a function object.
00383       addFuncToContainer(returnType);
00384    }
00385 
00386    // Dwarf outlines some function information. You have the base entry, which contains
00387    // address ranges, frame base information, and optionally a "abstract origin"
00388    // or "specification" entry that points to more information. 
00389    // We want to skip parsing specification or abstract entries until we have
00390    // the base entry and can find/create the corresponding function object. 
00391 
00392    // On the other hand, we can next actual function definitions. So...
00393    // Try to find a function, and just don't freak out if we don't find one. 
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      // Hopefully abstract or specification; skip for now.
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    // Get the frame base if it exists
00413    if (!getFrameBase()) return false;
00414 
00415    // Functions can operate as lexical blocks; this is optional, so we do _not_
00416    // return failure if it doesn't work. 
00417    parseLexicalBlock();
00418       
00419    // Parse parent nodes and their children but not their sibling
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       // An abstract origin will point to a specification if it exists
00430       // This can actually be three-layered, so backchain again
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    // These have two forms; a low..high range and a set
00443    // of address ranges. Right now we handle the first; 
00444    // TODO on the second when we find an example. 
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       //pgcc 6 is naming common blocks with a trailing underscore
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    // Right now we don't handle these
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    /* Acquire the name, type, and line number. */
00552    /* A variable may occur inside a function, as either static or local.
00553       A variable may occur inside a container, as C++ static member.
00554       A variable may not occur in either, as a global. 
00555       
00556       For the first two cases, we need the variable's name, its type,
00557       its line number, and its offset or address in order to tell
00558       Dyninst about it.  Dyninst only needs to know the name and type
00559       of a global.  (Actually, it already knows the names of the globals;
00560       we're really just telling it the types.)
00561       
00562       Variables may have two entries, the second, with a _specification,
00563       being the only one with the location. */
00564       
00565    /* If this DIE has a _specification, use that for the rest of our inquiries. */
00566    bool hasSpecification = false;
00567    if (!handleSpecification(hasSpecification)) return false;
00568 
00569    if (!findName(curName())) return false;
00570 
00571    removeFortranUnderscore(curName());
00572 
00573    /* We'll start with the location, since that's most likely to
00574       require the _specification. */
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       //if (locs[i].stClass != storageAddr) 
00582       //continue;
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       /* The typeOffset forms a module-unique type identifier,
00610          so the Type look-ups by it rather than name. */
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    } /* end if this variable is a global */
00623    else if (curFunc()) {
00624       /* We now have the variable name, type, offset, and line number.
00625          Tell Dyninst about it. */
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    } /* end if a local or static variable. */
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    } /* end if this variable is not global */
00654    return true;
00655 }
00656 
00657 bool DwarfWalker::parseFormalParam() {
00658    dwarf_printf("(0x%lx) Parsing formal parameter\n", id());
00659 
00660    /* A formal parameter must occur in the context of a function.
00661       (That is, we can't do anything with a formal parameter to a
00662       function we don't know about.) */
00663    /* It's probably worth noting that a formal parameter may have a
00664       default value.  Since, AFAIK, Dyninst does nothing with this information,
00665       neither will we. */
00666    if (!curFunc()) {
00667      dwarf_printf("(0x%lx) No function defined, returning\n", id());
00668      return true;
00669    }
00670 
00671    /* We need the formal parameter's name, its type, its line number,
00672       and its offset from the frame base in order to tell the 
00673       rest of Dyninst about it.  A single _formal_parameter
00674       DIE may not have all of this information; if it does not,
00675       we will ignore it, hoping to catch it when it is later
00676       referenced as an _abstract_origin from another _formal_parameter
00677       DIE.  If we never find such a DIE, than there is not enough
00678       information to introduce it to Dyninst. */
00679    
00680    /* We begin with the location, since this is the attribute
00681       most likely to require using the _abstract_origin. */
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    /* If the DIE has an _abstract_origin, we'll use that for the
00691       remainder of our inquiries. */
00692    bool hasAbstractOrigin;
00693    if (!handleAbstractOrigin(hasAbstractOrigin)) return false;
00694    if (hasAbstractOrigin) {
00695       // Clone to spec entry too
00696       setSpecEntry(abstractEntry());
00697    }
00698 
00699    if (!findName(curName())) return false;
00700    /* We can't do anything with anonymous parameters. */   
00701    if (!nameDefined()) {
00702      dwarf_printf("(0x%lx) No name associated with formal, returning\n", id());
00703      return true; 
00704    }
00705       
00706    /* Acquire the parameter's type. */
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    /* This is just brutally ugly.  Why don't we take care of this invariant automatically? */
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    /* Generate the appropriate built-in type; since there's no
00749       reliable way to distinguish between a built-in and a scalar,
00750       we don't bother to try. */
00751    typeScalar * baseType = new typeScalar( (typeId_t) offset(), (unsigned int) size, curName());
00752    assert( baseType != NULL );
00753    
00754    /* Add the basic type to our collection. */
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    /* Two words about pgf90 arrays.
00787       
00788       Primus: the PGI extensions to DWARF are documented in 
00789       '/p/paradyn/doc/External/manuals/pgf90-dwarf-arrays.txt'.
00790       
00791       Secundus: we ignore DW_AT_PGI_lbase, DW_AT_PGI_loffset, and DW_AT_PGI_lstride,
00792       even though libdwarf recognizes them, because our type modelling doesn't allow
00793       us to make use of this information.  Similarly, in virtually every place where
00794       the Portland Group extends DWARF to allow _form_block attributes encoding location
00795       lists, we ignore them.  We should, however, recognize these cases and ignore them
00796       gracefully, that is, without an error. :)
00797    */
00798 
00799    if (!findName(curName())) return false;
00800 
00801    // curName may get overridden by the subrange parsing code. 
00802    // TODO: make this part of the context stack. 
00803    std::string nameToUse = curName();
00804 
00805    Type *elementType = NULL;
00806    if (!findType(elementType, false)) return false;
00807    if (!elementType) return false;
00808 
00809    /* Find the range(s) of the elements. */
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    /* The baseArrayType is an anonymous type with its own typeID.  Extract
00826       the information and add an array type for this DIE. */
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    /* Don't parse the children again. */
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    /* Acquire the super class's type. */
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    /* Add a readily-recognizable 'bad' field to represent the superclass.
00884       Type::getComponents() will Do the Right Thing. */
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    /* DWARF stores offsets in bytes unless the member is a bit field.
00959       Correct memberOffset as indicated.  Also, memberSize is in bytes
00960       from the underlying type, not the # of bits used from it, so
00961       correct that as necessary as well. */
00962    
00963    long int memberSize = memberType->getSize();
00964 
00965    // This code changes memberSize, which is then discarded. I'm not sure why...
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 // TODO: this looks a lot like parseTypedef. Collapse?
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    /* Prefer linkage names. */
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    // Look it up by (entry) address
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       /* There's a return type attribute. */
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       //parsing_printf("%s/%d: ret type %d\n",
01264       //               __FILE__, __LINE__, typeOffset);
01265       
01266       returnType = tc()->findOrCreateType( (int) typeOffset );
01267       
01268       dwarf_dealloc( dbg(), typeAttribute, DW_DLA_ATTR );
01269    } /* end if not a void return type */
01270    return true;
01271 }
01272 
01273 // I'm not sure how the provided fieldListType is different from curEnclosure(),
01274 // but that's the way the code was structured and it was working. 
01275 bool DwarfWalker::addFuncToContainer(Type *returnType) {
01276    /* Using the mangled name allows us to distinguish between overridden
01277       functions, but confuses the tests.  Since Type uses vectors
01278       to hold field names, however, duplicate -- demangled names -- are OK. */
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       // Strip everything left of the rightmost ':' off to get rid of the class names
01289       toUse = demangledName;
01290       // rfind finds the last occurrence of ':'; add 1 to get past it. 
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    /* Acquire the parameter's type. */
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    /* The typeOffset forms a module-unique type identifier,
01322       so the Type look-ups by it rather than name. */
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    /* We don't need to tell Dyninst a line number for C++ static variables,
01358       so it's OK if there isn't one. */
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    /* Acquire the location of this formal parameter. */
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    // Get the form (datatype) for this particular attribute
01434    DWARF_FAIL_RET(dwarf_whatform(locationAttribute, &form, NULL));
01435    
01436    // And see if it's a constant
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    // Get the attribute
01456    Dwarf_Attribute d_attr;
01457    DWARF_FAIL_RET(dwarf_attr(entry(), attr, &d_attr, NULL));
01458 
01459    Dwarf_Half form;
01460    // Get the form (datatype) for this particular attribute
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    /* Acquire the visibility, if any.  DWARF calls it accessibility
01551       to distinguish it from symbol table visibility. */
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          //bperr ( "Uknown visibility, ignoring.\n" );
01569          break;
01570    } /* end visibility switch */
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       /* If the DW_AT_byte_size field exists, there's some padding.
01621          FIXME?  We ignore padding for now.  (We also don't seem to handle
01622          bitfields right in getComponents() anyway...) */
01623    }
01624    else 
01625    {
01626       if (locs.size())
01627          locs[0].frameOffset *= 8;
01628       size *= 8;
01629    } /* end if not a bit field member. */
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       /* If we're fortran, get rid of the trailing _ */
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    /* Set the default lower bound, if we know it. */
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    } /* end default lower bound switch */
01685    
01686    /* Look for the lower bound. */
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    } /* end if we found a lower bound. */
01695    
01696    /* Look for the upper bound. */
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    } /* end if we found an upper bound or count. */
01710    
01711    /* Construct the range type. */
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   /* Get the (negative) typeID for this range/subarray. */
01747   Dwarf_Off dieOffset;
01748   DWARF_FAIL_RET(dwarf_dieoffset( range, & dieOffset, NULL ));
01749 
01750   /* Determine the range. */
01751   std::string loBound;
01752   std::string hiBound;
01753   parseSubrangeAUX(range, loBound, hiBound);
01754 
01755   /* Does the recursion continue? */
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     /* Terminate the recursion by building an array type out of the elemental type.
01764        Use the negative dieOffset to avoid conflicts with the range type created
01765        by parseSubRangeDIE(). */
01766     // N.B.  I'm going to ignore the type id, and just create an anonymous type here
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   } /* end base-case of recursion. */
01777 
01778   /* If it does, build this array type out of the array type returned from the next recusion. */
01779   typeArray * innerType = parseMultiDimensionalArray( nextSibling, elementType);
01780   assert( innerType != NULL );
01781   // same here - type id ignored    jmo
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 } /* end parseMultiDimensionalArray() */
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          /* Acquire the referenced DIE. */
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       /* Does it have a name? */
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          /* Does it describe a nameless constant? */
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          /* PGI extends DWARF to allow some bounds to be location lists.  Since we can't
01877             do anything sane with them, ignore them. */
01878          // Dwarf_Locdesc * locationList;
01879          // Dwarf_Signed listLength;
01880          // status = dwarf_loclist( boundAttribute, & locationList, & listLength, NULL );
01881          boundString = "{PGI extension}";
01882          return false;
01883       } break;
01884       
01885       default:
01886          //bperr ( "Invalid bound form 0x%x\n", boundForm );
01887          boundString = "{invalid bound form}";
01888          return false;
01889          break;
01890    } /* end boundForm switch */
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   // expr_ptr is a pointer to a bytestream. Try to turn it into a Dwarf_Locdesc so
01902   // we can use decodeDwarfExpression. 
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   //deallocateLocationList(&descs, cnt);
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   /* We make a few heroic assumptions about locations in this decoder.
01928 
01929   We assume that all locations are either frame base-relative offsets,
01930   encoded with DW_OP_fbreg, or are absolute addresses.  We assume these
01931   locations are invariant with respect to the PC, which implies that all
01932   location lists have a single entry.  We assume that no location is
01933   calculated at run-time.
01934 
01935   We make these assumptions to match the assumptions of the rest of
01936   Dyninst, which makes no provision for pc-variant or run-time calculated
01937   locations, aside from the frame pointer.  However, it assumes that a frame
01938   pointer is readily available, which, on IA-64, it is not.  For that reason,
01939   when we encounter a function with a DW_AT_frame_base (effectively all of them),
01940   we do NOT use this decoder; we decode the location into an AST, which we
01941   will use to calculate the frame pointer when asked to do frame-relative operations.
01942   (These calculations will be invalid until the frame pointer is established,
01943   which may require some fiddling with the location of the 'entry' instpoint.) */
01944 
01945   /* We now parse the complete location list for variables and parameters within a
01946    * function. We still ignore the location list defined for DW_AT_frame_base of the
01947    * function as the frame pointer is readily available on all platforms(except for IA64)
01948    * May be we would need to parse the location list for IA64 functions to store the 
01949    * register numbers and offsets and use it based on the pc value. 
01950    */
01951  
01952    for (unsigned locIndex = 0 ; locIndex < listLength; locIndex++) {
01953                    
01954       /* There is only one location. */
01955       Dwarf_Locdesc *location = locationList[locIndex];
01956 
01957       VariableLocation loc;
01958       // Initialize location values.
01959       loc.stClass = storageAddr;
01960       loc.refClass = storageNoRef;
01961 
01962       // If location == 0..-1, it's "unset" and we keep the big range unless
01963       // we're in a lexical block construct. 
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          // Unset low and high. Use the lexical block info if present, otherwise
01982          // pass through. 
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    /* decode successful */
02017    return true;
02018 } /* end decodeLocationListForStaticOffsetOrAddress() */
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 } /* end deallocateLocationList() */
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 } /* end deallocateLocationList() */
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   // Bug workaround; if we're setting a function, ignore
02060   // any preceding lexical information since we probably 
02061   // nested. 
02062   c.top().func = f;
02063   clearRanges();
02064 }
02065 
02066 void DwarfWalker::Contexts::clearFunc() {
02067   // We can't edit in the middle of the stack...
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1