[C++11] DWARF parser: use SmallVector<std::unique_ptr> for parsed units in DWARFConte...
[oota-llvm.git] / lib / DebugInfo / DWARFDebugInfoEntry.cpp
index e8b8748a9d73499b7c6364cd48c7ba00598acd57..bde25ec82d11b48c25831d27404f31a353bfb198 100644 (file)
@@ -40,11 +40,8 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u,
                      AbbrevDecl->hasChildren() ? '*' : ' ');
 
         // Dump all data in the DIE for the attributes.
-        const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
-        for (uint32_t i = 0; i != numAttributes; ++i) {
-          uint16_t attr = AbbrevDecl->getAttrByIndex(i);
-          uint16_t form = AbbrevDecl->getFormByIndex(i);
-          dumpAttribute(OS, u, &offset, attr, form, indent);
+        for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+          dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent);
         }
 
         const DWARFDebugInfoEntryMinimal *child = getFirstChild();
@@ -93,47 +90,11 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
 }
 
 bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
-                                             const uint8_t *FixedFormSizes,
                                              uint32_t *OffsetPtr) {
   Offset = *OffsetPtr;
   DataExtractor DebugInfoData = U->getDebugInfoExtractor();
-  uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
-  if (0 == AbbrCode) {
-    // NULL debug tag entry.
-    AbbrevDecl = NULL;
-    return true;
-  }
-  AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
-  assert(AbbrevDecl);
-  assert(FixedFormSizes); // For best performance this should be specified!
-
-  // Skip all data in the .debug_info for the attributes
-  for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
-    uint16_t Form = AbbrevDecl->getFormByIndex(i);
-
-    // FIXME: Currently we're checking if this is less than the last
-    // entry in the fixed_form_sizes table, but this should be changed
-    // to use dynamic dispatch.
-    uint8_t FixedFormSize =
-        (Form < DW_FORM_ref_sig8) ? FixedFormSizes[Form] : 0;
-    if (FixedFormSize)
-      *OffsetPtr += FixedFormSize;
-    else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr,
-                                        U)) {
-      // Restore the original offset.
-      *OffsetPtr = Offset;
-      return false;
-    }
-  }
-  return true;
-}
-
-bool DWARFDebugInfoEntryMinimal::extract(const DWARFUnit *U,
-                                         uint32_t *OffsetPtr) {
-  DataExtractor DebugInfoData = U->getDebugInfoExtractor();
-  const uint32_t UEndOffset = U->getNextUnitOffset();
-  Offset = *OffsetPtr;
-  if ((Offset >= UEndOffset) || !DebugInfoData.isValidOffset(Offset))
+  uint32_t UEndOffset = U->getNextUnitOffset();
+  if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
     return false;
   uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
   if (0 == AbbrCode) {
@@ -147,26 +108,19 @@ bool DWARFDebugInfoEntryMinimal::extract(const DWARFUnit *U,
     *OffsetPtr = Offset;
     return false;
   }
-  bool IsCompileUnitTag = (AbbrevDecl->getTag() == DW_TAG_compile_unit);
-  if (IsCompileUnitTag)
-    const_cast<DWARFUnit *>(U)->setBaseAddress(0);
+  ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes(
+      U->getAddressByteSize(), U->getVersion());
+  assert(FixedFormSizes.size() > 0);
 
   // Skip all data in the .debug_info for the attributes
-  for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
-    uint16_t Attr = AbbrevDecl->getAttrByIndex(i);
-    uint16_t Form = AbbrevDecl->getFormByIndex(i);
-
-    if (IsCompileUnitTag &&
-        ((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
-      DWARFFormValue FormValue(Form);
-      if (FormValue.extractValue(DebugInfoData, OffsetPtr, U)) {
-        if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc) {
-          Optional<uint64_t> BaseAddr = FormValue.getAsAddress(U);
-          if (BaseAddr.hasValue())
-            const_cast<DWARFUnit *>(U)->setBaseAddress(BaseAddr.getValue());
-        }
-      }
-    } else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
+  for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+    uint16_t Form = AttrSpec.Form;
+
+    uint8_t FixedFormSize =
+        (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0;
+    if (FixedFormSize)
+      *OffsetPtr += FixedFormSize;
+    else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
       // Restore the original offset.
       *OffsetPtr = Offset;
       return false;
@@ -258,11 +212,17 @@ uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
                                                  uint64_t &LowPC,
                                                  uint64_t &HighPC) const {
-  HighPC = -1ULL;
   LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
-  // FIXME: Check if HighPC is of class constant (it has different semantics).
-  if (LowPC != -1ULL)
-    HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
+  if (LowPC == -1ULL)
+    return false;
+  HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
+  if (HighPC == -1ULL) {
+    // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
+    // it represents function size.
+    HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
+    if (HighPC != -1ULL)
+      HighPC += LowPC;
+  }
   return (HighPC != -1ULL);
 }
 
@@ -320,7 +280,7 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
       getAttributeValueAsReference(U, DW_AT_specification, -1U);
   if (spec_ref != -1U) {
     DWARFDebugInfoEntryMinimal spec_die;
-    if (spec_die.extract(U, &spec_ref)) {
+    if (spec_die.extractFast(U, &spec_ref)) {
       if (const char *name = spec_die.getSubroutineName(U))
         return name;
     }
@@ -330,7 +290,7 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const {
       getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U);
   if (abs_origin_ref != -1U) {
     DWARFDebugInfoEntryMinimal abs_origin_die;
-    if (abs_origin_die.extract(U, &abs_origin_ref)) {
+    if (abs_origin_die.extractFast(U, &abs_origin_ref)) {
       if (const char *name = abs_origin_die.getSubroutineName(U))
         return name;
     }