Example #1
0
/// Print only DIEs that have a certain name.
static void filterByName(const StringSet<> &Names,
                         DWARFContext::cu_iterator_range CUs, raw_ostream &OS) {
  for (const auto &CU : CUs)
    for (const auto &Entry : CU->dies()) {
      DWARFDie Die = {CU.get(), &Entry};
      if (const char *NamePtr = Die.getName(DINameKind::ShortName)) {
        std::string Name =
            (IgnoreCase && !UseRegex) ? StringRef(NamePtr).lower() : NamePtr;
        // Match regular expression.
        if (UseRegex)
          for (auto Pattern : Names.keys()) {
            Regex RE(Pattern, IgnoreCase ? Regex::IgnoreCase : Regex::NoFlags);
            std::string Error;
            if (!RE.isValid(Error)) {
              errs() << "error in regular expression: " << Error << "\n";
              exit(1);
            }
            if (RE.match(Name))
              Die.dump(OS, 0, getDumpOpts());
          }
        // Match full text.
        else if (Names.count(Name))
          Die.dump(OS, 0, getDumpOpts());
      }
    }

}
Example #2
0
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
                                        DieRangeInfo &ParentRI) {
  unsigned NumErrors = 0;

  if (!Die.isValid())
    return NumErrors;

  DWARFAddressRangesVector Ranges = Die.getAddressRanges();

  // Build RI for this DIE and check that ranges within this DIE do not
  // overlap.
  DieRangeInfo RI(Die);
  for (auto Range : Ranges) {
    if (!Range.valid()) {
      ++NumErrors;
      error() << "Invalid address range " << Range << "\n";
      continue;
    }

    // Verify that ranges don't intersect.
    const auto IntersectingRange = RI.insert(Range);
    if (IntersectingRange != RI.Ranges.end()) {
      ++NumErrors;
      error() << "DIE has overlapping address ranges: " << Range << " and "
              << *IntersectingRange << "\n";
      break;
    }
  }

  // Verify that children don't intersect.
  const auto IntersectingChild = ParentRI.insert(RI);
  if (IntersectingChild != ParentRI.Children.end()) {
    ++NumErrors;
    error() << "DIEs have overlapping address ranges:";
    Die.dump(OS, 0);
    IntersectingChild->Die.dump(OS, 0);
    OS << "\n";
  }

  // Verify that ranges are contained within their parent.
  bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
                           !(Die.getTag() == DW_TAG_subprogram &&
                             ParentRI.Die.getTag() == DW_TAG_subprogram);
  if (ShouldBeContained && !ParentRI.contains(RI)) {
    ++NumErrors;
    error() << "DIE address ranges are not "
               "contained in its parent's ranges:";
    Die.dump(OS, 0);
    ParentRI.Die.dump(OS, 0);
    OS << "\n";
  }

  // Recursively check children.
  for (DWARFDie Child : Die)
    NumErrors += verifyDieRanges(Child, RI);

  return NumErrors;
}
Example #3
0
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                                 DWARFAttribute &AttrValue) {
  const DWARFObject &DObj = DCtx.getDWARFObj();
  unsigned NumErrors = 0;
  const auto Attr = AttrValue.Attr;
  switch (Attr) {
  case DW_AT_ranges:
    // Make sure the offset in the DW_AT_ranges attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getRangeSection().Data.size()) {
        ++NumErrors;
        OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
              "bounds:\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumErrors;
      OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;
  case DW_AT_stmt_list:
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getLineSection().Data.size()) {
        ++NumErrors;
        OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
              "bounds: "
           << format("0x%08" PRIx64, *SectionOffset) << "\n";
        Die.dump(OS, 0);
        OS << "\n";
      }
    } else {
      ++NumErrors;
      OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
      Die.dump(OS, 0);
      OS << "\n";
    }
    break;

  default:
    break;
  }
  return NumErrors;
}
Example #4
0
/// Helper to dump a DIE with all of its parents, but no siblings.
static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent,
                                DIDumpOptions DumpOpts) {
  if (!Die)
    return Indent;
  Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts);
  Die.dump(OS, Indent, DumpOpts);
  return Indent + 2;
}
Example #5
0
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                                 DWARFAttribute &AttrValue) {
  unsigned NumErrors = 0;
  auto ReportError = [&](const Twine &TitleMsg) {
    ++NumErrors;
    error() << TitleMsg << '\n';
    Die.dump(OS, 0, DumpOpts);
    OS << "\n";
  };

  const DWARFObject &DObj = DCtx.getDWARFObj();
  const auto Attr = AttrValue.Attr;
  switch (Attr) {
  case DW_AT_ranges:
    // Make sure the offset in the DW_AT_ranges attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getRangeSection().Data.size())
        ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
      break;
    }
    ReportError("DIE has invalid DW_AT_ranges encoding:");
    break;
  case DW_AT_stmt_list:
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getLineSection().Data.size())
        ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
                    llvm::formatv("{0:x8}", *SectionOffset));
      break;
    }
    ReportError("DIE has invalid DW_AT_stmt_list encoding:");
    break;
  case DW_AT_location: {
    Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock();
    if (!Expr) {
      ReportError("DIE has invalid DW_AT_location encoding:");
      break;
    }

    DWARFUnit *U = Die.getDwarfUnit();
    DataExtractor Data(
        StringRef(reinterpret_cast<const char *>(Expr->data()), Expr->size()),
        DCtx.isLittleEndian(), 0);
    DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
    bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
      return Op.isError();
    });
    if (Error)
      ReportError("DIE contains invalid DWARF expression:");
    break;
  }

  default:
    break;
  }
  return NumErrors;
}
Example #6
0
void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
                    unsigned Indent) const {
  if (!isValid())
    return;
  DataExtractor debug_info_data = U->getDebugInfoExtractor();
  const uint32_t Offset = getOffset();
  uint32_t offset = Offset;
  
  if (debug_info_data.isValidOffset(offset)) {
    uint32_t abbrCode = debug_info_data.getULEB128(&offset);
    WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
    
    if (abbrCode) {
      auto AbbrevDecl = getAbbreviationDeclarationPtr();
      if (AbbrevDecl) {
        auto tagString = TagString(getTag());
        if (!tagString.empty())
          WithColor(OS, syntax::Tag).get().indent(Indent) << tagString;
        else
          WithColor(OS, syntax::Tag).get().indent(Indent)
          << format("DW_TAG_Unknown_%x", getTag());
        
        OS << format(" [%u] %c\n", abbrCode,
                     AbbrevDecl->hasChildren() ? '*' : ' ');
        
        // Dump all data in the DIE for the attributes.
        for (const auto &AttrSpec : AbbrevDecl->attributes()) {
          if (AttrSpec.Form == DW_FORM_implicit_const) {
            // We are dumping .debug_info section ,
            // implicit_const attribute values are not really stored here,
            // but in .debug_abbrev section. So we just skip such attrs.
            continue;
          }
          dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
                        Indent);
        }
        
        DWARFDie child = getFirstChild();
        if (RecurseDepth > 0 && child) {
          while (child) {
            child.dump(OS, RecurseDepth-1, Indent+2);
            child = child.getSibling();
          }
        }
      } else {
        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
        << abbrCode << '\n';
      }
    } else {
      OS.indent(Indent) << "NULL\n";
    }
  }
}
Example #7
0
/// Print only DIEs that have a certain name.
static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
                              raw_ostream &OS) {
  SmallVector<uint64_t, 4> Offsets;
  for (const auto &Name : Names) {
    getDIEOffset(DICtx.getAppleNames(), Name, Offsets);
    getDIEOffset(DICtx.getAppleTypes(), Name, Offsets);
    getDIEOffset(DICtx.getAppleNamespaces(), Name, Offsets);
    getDIEOffset(DICtx.getDebugNames(), Name, Offsets);
  }
  llvm::sort(Offsets.begin(), Offsets.end());
  Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());

  for (uint64_t Off: Offsets) {
    DWARFDie Die = DICtx.getDIEForOffset(Off);
    Die.dump(OS, 0, getDumpOpts());
  }
}
Example #8
0
unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
                                            DWARFAttribute &AttrValue) {
  const DWARFObject &DObj = DCtx.getDWARFObj();
  unsigned NumErrors = 0;
  const auto Form = AttrValue.Value.getForm();
  switch (Form) {
  case DW_FORM_ref1:
  case DW_FORM_ref2:
  case DW_FORM_ref4:
  case DW_FORM_ref8:
  case DW_FORM_ref_udata: {
    // Verify all CU relative references are valid CU offsets.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      auto DieCU = Die.getDwarfUnit();
      auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
      auto CUOffset = AttrValue.Value.getRawUValue();
      if (CUOffset >= CUSize) {
        ++NumErrors;
        error() << FormEncodingString(Form) << " CU offset "
                << format("0x%08" PRIx64, CUOffset)
                << " is invalid (must be less than CU size of "
                << format("0x%08" PRIx32, CUSize) << "):\n";
        Die.dump(OS, 0, DumpOpts);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_ref_addr: {
    // Verify all absolute DIE references have valid offsets in the
    // .debug_info section.
    Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
    assert(RefVal);
    if (RefVal) {
      if (*RefVal >= DObj.getInfoSection().Data.size()) {
        ++NumErrors;
        error() << "DW_FORM_ref_addr offset beyond .debug_info "
                   "bounds:\n";
        Die.dump(OS, 0, DumpOpts);
        OS << "\n";
      } else {
        // Valid reference, but we will verify it points to an actual
        // DIE later.
        ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
      }
    }
    break;
  }
  case DW_FORM_strp: {
    auto SecOffset = AttrValue.Value.getAsSectionOffset();
    assert(SecOffset); // DW_FORM_strp is a section offset.
    if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
      ++NumErrors;
      error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
      Die.dump(OS, 0, DumpOpts);
      OS << "\n";
    }
    break;
  }
  default:
    break;
  }
  return NumErrors;
}
Example #9
0
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
                                                 DWARFAttribute &AttrValue) {
  unsigned NumErrors = 0;
  auto ReportError = [&](const Twine &TitleMsg) {
    ++NumErrors;
    error() << TitleMsg << '\n';
    Die.dump(OS, 0, DumpOpts);
    OS << "\n";
  };

  const DWARFObject &DObj = DCtx.getDWARFObj();
  const auto Attr = AttrValue.Attr;
  switch (Attr) {
  case DW_AT_ranges:
    // Make sure the offset in the DW_AT_ranges attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getRangeSection().Data.size())
        ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
      break;
    }
    ReportError("DIE has invalid DW_AT_ranges encoding:");
    break;
  case DW_AT_stmt_list:
    // Make sure the offset in the DW_AT_stmt_list attribute is valid.
    if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
      if (*SectionOffset >= DObj.getLineSection().Data.size())
        ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
                    llvm::formatv("{0:x8}", *SectionOffset));
      break;
    }
    ReportError("DIE has invalid DW_AT_stmt_list encoding:");
    break;
  case DW_AT_location: {
    auto VerifyLocation = [&](StringRef D) {
      DWARFUnit *U = Die.getDwarfUnit();
      DataExtractor Data(D, DCtx.isLittleEndian(), 0);
      DWARFExpression Expression(Data, U->getVersion(),
                                 U->getAddressByteSize());
      bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
        return Op.isError();
      });
      if (Error)
        ReportError("DIE contains invalid DWARF expression:");
    };
    if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) {
      // Verify inlined location.
      VerifyLocation(llvm::toStringRef(*Expr));
    } else if (auto LocOffset = AttrValue.Value.getAsUnsignedConstant()) {
      // Verify location list.
      if (auto DebugLoc = DCtx.getDebugLoc())
        if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset))
          for (const auto &Entry : LocList->Entries)
            VerifyLocation({Entry.Loc.data(), Entry.Loc.size()});
    }
    break;
  }

  default:
    break;
  }
  return NumErrors;
}
Example #10
0
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);
             }
  }
}
Example #11
0
void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
                    DIDumpOptions DumpOpts) const {
  if (!isValid())
    return;
  DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor();
  const uint32_t Offset = getOffset();
  uint32_t offset = Offset;
  if (DumpOpts.ShowParents) {
    DIDumpOptions ParentDumpOpts = DumpOpts;
    ParentDumpOpts.ShowParents = false;
    ParentDumpOpts.ShowChildren = false;
    Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts);
  }

  if (debug_info_data.isValidOffset(offset)) {
    uint32_t abbrCode = debug_info_data.getULEB128(&offset);
    if (DumpOpts.ShowAddresses)
      WithColor(OS, HighlightColor::Address).get()
          << format("\n0x%8.8x: ", Offset);

    if (abbrCode) {
      auto AbbrevDecl = getAbbreviationDeclarationPtr();
      if (AbbrevDecl) {
        WithColor(OS, HighlightColor::Tag).get().indent(Indent)
            << formatv("{0}", getTag());
        if (DumpOpts.Verbose)
          OS << format(" [%u] %c", abbrCode,
                       AbbrevDecl->hasChildren() ? '*' : ' ');
        OS << '\n';

        // Dump all data in the DIE for the attributes.
        for (const auto &AttrSpec : AbbrevDecl->attributes()) {
          if (AttrSpec.Form == DW_FORM_implicit_const) {
            // We are dumping .debug_info section ,
            // implicit_const attribute values are not really stored here,
            // but in .debug_abbrev section. So we just skip such attrs.
            continue;
          }
          dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
                        Indent, DumpOpts);
        }

        DWARFDie child = getFirstChild();
        if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) {
          DumpOpts.RecurseDepth--;
          DIDumpOptions ChildDumpOpts = DumpOpts;
          ChildDumpOpts.ShowParents = false;
          while (child) {
            child.dump(OS, Indent + 2, ChildDumpOpts);
            child = child.getSibling();
          }
        }
      } else {
        OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
           << abbrCode << '\n';
      }
    } else {
      OS.indent(Indent) << "NULL\n";
    }
  }
}