ARM IAS: support .personalityindex
[oota-llvm.git] / lib / DebugInfo / DWARFContext.cpp
index 9dc8f149933d4db53be5439f1dac5e884364c97e..b725619d8e2528f16def360a984676717979a480 100644 (file)
@@ -8,9 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "DWARFContext.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/Format.h"
@@ -34,27 +34,29 @@ static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
   OS << "\n." << Name << " contents:\n";
   DataExtractor pubNames(Data, LittleEndian, 0);
   uint32_t offset = 0;
-  OS << "Length:                " << pubNames.getU32(&offset) << "\n";
-  OS << "Version:               " << pubNames.getU16(&offset) << "\n";
-  OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n";
-  OS << "Size:                  " << pubNames.getU32(&offset) << "\n";
-  if (GnuStyle)
-    OS << "Offset     Linkage  Kind     Name\n";
-  else
-    OS << "Offset     Name\n";
-
-  while (offset < Data.size()) {
-    uint32_t dieRef = pubNames.getU32(&offset);
-    if (dieRef == 0)
-      break;
-    OS << format("0x%8.8x ", dieRef);
-    if (GnuStyle) {
-      PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
-      OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
-         << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
-         << ' ';
+  while (pubNames.isValidOffset(offset)) {
+    OS << "length = " << format("0x%08x", pubNames.getU32(&offset));
+    OS << " version = " << format("0x%04x", pubNames.getU16(&offset));
+    OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset));
+    OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n';
+    if (GnuStyle)
+      OS << "Offset     Linkage  Kind     Name\n";
+    else
+      OS << "Offset     Name\n";
+
+    while (offset < Data.size()) {
+      uint32_t dieRef = pubNames.getU32(&offset);
+      if (dieRef == 0)
+        break;
+      OS << format("0x%8.8x ", dieRef);
+      if (GnuStyle) {
+        PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
+        OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
+           << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
+           << ' ';
+      }
+      OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
     }
-    OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
   }
 }
 
@@ -64,18 +66,38 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
     getDebugAbbrev()->dump(OS);
   }
 
+  if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo)
+    if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) {
+      OS << "\n.debug_abbrev.dwo contents:\n";
+      D->dump(OS);
+    }
+
   if (DumpType == DIDT_All || DumpType == DIDT_Info) {
     OS << "\n.debug_info contents:\n";
     for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
       getCompileUnitAtIndex(i)->dump(OS);
   }
 
-  if (DumpType == DIDT_All || DumpType == DIDT_Types) {
+  if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) &&
+      getNumDWOCompileUnits()) {
+    OS << "\n.debug_info.dwo contents:\n";
+    for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
+      getDWOCompileUnitAtIndex(i)->dump(OS);
+  }
+
+  if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) {
     OS << "\n.debug_types contents:\n";
     for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i)
       getTypeUnitAtIndex(i)->dump(OS);
   }
 
+  if (DumpType == DIDT_All || DumpType == DIDT_TypesDwo)
+    if (getNumDWOTypeUnits()) {
+      OS << "\n.debug_types.dwo contents:\n";
+      for (unsigned i = 0, e = getNumDWOTypeUnits(); i != e; ++i)
+        getDWOTypeUnitAtIndex(i)->dump(OS);
+    }
+
   if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
     OS << "\n.debug_loc contents:\n";
     getDebugLoc()->dump(OS);
@@ -102,8 +124,8 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
       DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
       savedAddressByteSize = cu->getAddressByteSize();
       unsigned stmtOffset =
-        cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-                                                             -1U);
+          cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+              cu, DW_AT_stmt_list, -1U);
       if (stmtOffset != -1U) {
         DataExtractor lineData(getLineSection().Data, isLittleEndian(),
                                savedAddressByteSize);
@@ -124,6 +146,18 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
     }
   }
 
+  if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) &&
+      !getStringDWOSection().empty()) {
+    OS << "\n.debug_str.dwo contents:\n";
+    DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
+    offset = 0;
+    uint32_t strDWOOffset = 0;
+    while (const char *s = strDWOData.getCStr(&offset)) {
+      OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
+      strDWOOffset = offset;
+    }
+  }
+
   if (DumpType == DIDT_All || DumpType == DIDT_Ranges) {
     OS << "\n.debug_ranges contents:\n";
     // In fact, different compile units may have different address byte
@@ -154,44 +188,18 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
     dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
                    isLittleEndian(), true /* GnuStyle */);
 
-  if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
-    const DWARFDebugAbbrev *D = getDebugAbbrevDWO();
-    if (D) {
-      OS << "\n.debug_abbrev.dwo contents:\n";
-      getDebugAbbrevDWO()->dump(OS);
+  if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) &&
+      !getStringOffsetDWOSection().empty()) {
+    OS << "\n.debug_str_offsets.dwo contents:\n";
+    DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(),
+                               0);
+    offset = 0;
+    uint64_t size = getStringOffsetDWOSection().size();
+    while (offset < size) {
+      OS << format("0x%8.8x: ", offset);
+      OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
     }
   }
-
-  if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo)
-    if (getNumDWOCompileUnits()) {
-      OS << "\n.debug_info.dwo contents:\n";
-      for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i)
-        getDWOCompileUnitAtIndex(i)->dump(OS);
-    }
-
-  if (DumpType == DIDT_All || DumpType == DIDT_StrDwo)
-    if (!getStringDWOSection().empty()) {
-      OS << "\n.debug_str.dwo contents:\n";
-      DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
-      offset = 0;
-      uint32_t strDWOOffset = 0;
-      while (const char *s = strDWOData.getCStr(&offset)) {
-        OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
-        strDWOOffset = offset;
-      }
-    }
-
-  if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo)
-    if (!getStringOffsetDWOSection().empty()) {
-      OS << "\n.debug_str_offsets.dwo contents:\n";
-      DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
-      offset = 0;
-      uint64_t size = getStringOffsetDWOSection().size();
-      while (offset < size) {
-        OS << format("0x%8.8x: ", offset);
-        OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
-      }
-    }
 }
 
 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@@ -262,8 +270,8 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
     Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
 
   unsigned stmtOffset =
-    cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-                                                         -1U);
+      cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
+          cu, DW_AT_stmt_list, -1U);
   if (stmtOffset == -1U)
     return 0; // No line table for this compile unit.
 
@@ -295,10 +303,8 @@ void DWARFContext::parseCompileUnits() {
 }
 
 void DWARFContext::parseTypeUnits() {
-  const std::map<object::SectionRef, Section> &Sections = getTypesSections();
-  for (std::map<object::SectionRef, Section>::const_iterator
-           I = Sections.begin(),
-           E = Sections.end();
+  const TypeSectionMap &Sections = getTypesSections();
+  for (TypeSectionMap::const_iterator I = Sections.begin(), E = Sections.end();
        I != E; ++I) {
     uint32_t offset = 0;
     const DataExtractor &DIData =
@@ -334,6 +340,27 @@ void DWARFContext::parseDWOCompileUnits() {
   }
 }
 
+void DWARFContext::parseDWOTypeUnits() {
+  const TypeSectionMap &Sections = getTypesDWOSections();
+  for (TypeSectionMap::const_iterator I = Sections.begin(), E = Sections.end();
+       I != E; ++I) {
+    uint32_t offset = 0;
+    const DataExtractor &DIData =
+        DataExtractor(I->second.Data, isLittleEndian(), 0);
+    while (DIData.isValidOffset(offset)) {
+      OwningPtr<DWARFTypeUnit> TU(new DWARFTypeUnit(
+          getDebugAbbrevDWO(), I->second.Data, getAbbrevDWOSection(),
+          getRangeDWOSection(), getStringDWOSection(),
+          getStringOffsetDWOSection(), getAddrSection(), &I->second.Relocs,
+          isLittleEndian()));
+      if (!TU->extract(DIData, &offset))
+        break;
+      DWOTUs.push_back(TU.take());
+      offset = DWOTUs.back()->getNextUnitOffset();
+    }
+  }
+}
+
 namespace {
   struct OffsetComparator {
     bool operator()(const DWARFCompileUnit *LHS,
@@ -633,6 +660,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
       // Find debug_types data by section rather than name as there are
       // multiple, comdat grouped, debug_types sections.
       TypesSections[*i].Data = data;
+    } else if (name == "debug_types.dwo") {
+      TypesDWOSections[*i].Data = data;
     }
 
     section_iterator RelocatedSection = i->getRelocatedSection();
@@ -653,11 +682,14 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
         .Case("debug_line", &LineSection.Relocs)
         .Default(0);
     if (!Map) {
-      if (RelSecName != "debug_types")
-        continue;
       // Find debug_types relocs by section rather than name as there are
       // multiple, comdat grouped, debug_types sections.
-      Map = &TypesSections[*RelocatedSection].Relocs;
+      if (RelSecName == "debug_types")
+        Map = &TypesSections[*RelocatedSection].Relocs;
+      else if (RelSecName == "debug_types.dwo")
+        Map = &TypesDWOSections[*RelocatedSection].Relocs;
+      else
+        continue;
     }
 
     if (i->begin_relocations() != i->end_relocations()) {