void DWARFUnit::updateAddressDieMap(DWARFDie Die) { if (Die.isSubroutineDIE()) { auto DIERangesOrError = Die.getAddressRanges(); if (DIERangesOrError) { for (const auto &R : DIERangesOrError.get()) { // Ignore 0-sized ranges. if (R.LowPC == R.HighPC) continue; auto B = AddrDieMap.upper_bound(R.LowPC); if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { // The range is a sub-range of existing ranges, we need to split the // existing range. if (R.HighPC < B->second.first) AddrDieMap[R.HighPC] = B->second; if (R.LowPC > B->first) AddrDieMap[B->first].first = R.LowPC; } AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); } } else llvm::consumeError(DIERangesOrError.takeError()); } // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to // simplify the logic to update AddrDieMap. The child's range will always // be equal or smaller than the parent's range. With this assumption, when // adding one range into the map, it will at most split a range into 3 // sub-ranges. for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) updateAddressDieMap(Child); }
void DwarfVariableFinder::findVariables(const DWARFDie &die) { for (auto child = die.getFirstChild(); child; child = child.getSibling()) { switch(child.getTag()) { case dwarf::DW_TAG_variable: case dwarf::DW_TAG_formal_parameter: case dwarf::DW_TAG_constant: handleVariable(child); break; default: if (child.hasChildren()) findVariables(child); } } }
DwarfVariableFinder::DwarfVariableFinder(const DWARFDie &die, raw_ostream &os) : OS(os) { if(!die.hasChildren()) { outs() << "No child \n\n"; return; } for (auto child = die.getFirstChild(); child; child = child.getSibling()) { //Go over all the top level sub_programs if(child.isSubprogramDIE() || child.isSubroutineDIE()) { getInfo(child); //Look for variables among children of sub_program die if(!child.hasChildren()) { continue; } findVariables(child); } } }
std::shared_ptr<TypeInfo> DwarfVariableFinder::makeType(const DWARFDie &die) { if (!die.isValid()) { return std::make_shared<TypeInfo>("", ~0u); } auto opSize = die.find(dwarf::DW_AT_byte_size); unsigned size = 1; if(opSize.hasValue()) { size = opSize.getValue().getAsUnsignedConstant().getValue(); } std::string type_encoding = ""; raw_string_ostream SS(type_encoding); switch (die.getTag()) { case dwarf::DW_TAG_base_type: { auto opForm = die.find(dwarf::DW_AT_encoding); auto opEnc = opForm->getAsUnsignedConstant(); assert(opEnc < HANDLE_DW_ATE_SIZE); SS << HANDLE_DW_ATE[*opEnc]; opForm = die.find(dwarf::DW_AT_name); opForm->dump(SS); return std::make_shared<TypeInfo>(SS.str(), size); } case dwarf::DW_TAG_reference_type: case dwarf::DW_TAG_rvalue_reference_type: case dwarf::DW_TAG_pointer_type: { auto baseType = getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type)); SS << "*" << baseType->getName(); return std::make_shared<TypeInfo>(SS.str(), size); } case dwarf::DW_TAG_array_type: { auto baseType = getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type)); SS << baseType->getName(); size *= baseType->getSize(); for (auto childDie = die.getFirstChild(); childDie && childDie.getTag(); childDie = childDie.getSibling()) { std::shared_ptr<TypeInfo> rangeInfo = makeType(childDie); SS << "["; SS << rangeInfo->getName(); SS << "]"; size *= rangeInfo->getSize(); } return std::make_shared<TypeInfo>(SS.str(), size); } case dwarf::DW_TAG_subrange_type: { uint64_t count = 0; auto opCount = die.find(dwarf::DW_AT_count); if(opCount.hasValue()) { count = opCount.getValue().getAsUnsignedConstant().getValue(); } else { opCount = die.find(dwarf::DW_AT_upper_bound); assert(opCount.hasValue()); count = opCount.getValue().getAsUnsignedConstant().getValue() +1; } return std::make_shared<TypeInfo>(std::to_string(count), count); } case dwarf::DW_TAG_typedef: { return getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type)); } case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_class_type: case dwarf::DW_TAG_union_type: { SS << "struct" << dwarf::toString(die.find(dwarf::DW_AT_name), "None"); auto structType = std::make_shared<TypeInfo>(SS.str(), size); // Add subentries for various pieces of the struct. for (auto childDie = die.getFirstChild(); childDie && childDie.getTag(); childDie = childDie.getSibling()) { if (childDie.getTag() != dwarf::DW_TAG_inheritance && childDie.getTag() != dwarf::DW_TAG_member) { continue; } uint64_t dataMemOffset = dwarf::toUnsigned(childDie.find(dwarf::DW_AT_data_member_location), ~0U); structType->getFields().emplace_back(makeType(childDie), dataMemOffset); } return structType; } case dwarf::DW_TAG_inheritance: case dwarf::DW_TAG_member: { return getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type)); } default: { auto tagString = TagString(die.getTag()); if (tagString.empty()) { llvm::errs() << format("DW_TAG_Unknown_%x", die.getTag()); } die.dump(llvm::errs(), 10); return std::make_shared<TypeInfo>("", ~0u); } } }