llvm-readobj: add support to dump (COFF) directives
[oota-llvm.git] / tools / llvm-readobj / COFFDumper.cpp
index 3d71d832f99b07bdc582d9d5eef8cbd8cc85959e..84cd9a689e3a773046e0aa0e943241629b02f6c2 100644 (file)
@@ -55,6 +55,8 @@ public:
   void printSymbols() override;
   void printDynamicSymbols() override;
   void printUnwindInfo() override;
+  void printCOFFImports() override;
+  void printCOFFDirectives() override;
 
 private:
   void printSymbol(const SymbolRef &Sym);
@@ -74,10 +76,15 @@ private:
   std::error_code resolveSymbolName(const coff_section *Section,
                                     uint64_t Offset, StringRef &Name);
 
+  void printImportedSymbols(imported_symbol_iterator I,
+                            imported_symbol_iterator E);
+
   typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
 
   const llvm::object::COFFObjectFile *Obj;
   RelocMapTy RelocMap;
+  StringRef CVFileIndexToStringOffsetTable;
+  StringRef CVStringTable;
 };
 
 } // namespace
@@ -436,8 +443,6 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
 
   SmallVector<StringRef, 10> FunctionNames;
   StringMap<StringRef> FunctionLineTables;
-  StringRef FileIndexToStringOffsetTable;
-  StringRef StringTable;
 
   ListScope D(W, "CodeViewLineTables");
   {
@@ -498,25 +503,25 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
         break;
       }
       case COFF::DEBUG_STRING_TABLE_SUBSECTION:
-        if (PayloadSize == 0 || StringTable.data() != nullptr ||
+        if (PayloadSize == 0 || CVStringTable.data() != nullptr ||
             Contents.back() != '\0') {
           // Empty or duplicate or non-null-terminated subsection.
           error(object_error::parse_failed);
           return;
         }
-        StringTable = Contents;
+        CVStringTable = Contents;
         break;
       case COFF::DEBUG_INDEX_SUBSECTION:
         // Holds the translation table from file indices
         // to offsets in the string table.
 
         if (PayloadSize == 0 ||
-            FileIndexToStringOffsetTable.data() != nullptr) {
+            CVFileIndexToStringOffsetTable.data() != nullptr) {
           // Empty or duplicate subsection.
           error(object_error::parse_failed);
           return;
         }
-        FileIndexToStringOffsetTable = Contents;
+        CVFileIndexToStringOffsetTable = Contents;
         break;
       }
       Offset += PayloadSize;
@@ -551,7 +556,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
 
       uint32_t FilenameOffset;
       {
-        DataExtractor SDE(FileIndexToStringOffsetTable, true, 4);
+        DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4);
         uint32_t OffsetInSDE = OffsetInIndex;
         if (!SDE.isValidOffset(OffsetInSDE)) {
           error(object_error::parse_failed);
@@ -560,15 +565,15 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
         FilenameOffset = SDE.getU32(&OffsetInSDE);
       }
 
-      if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() ||
-          StringTable.data()[FilenameOffset - 1] != '\0') {
+      if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() ||
+          CVStringTable.data()[FilenameOffset - 1] != '\0') {
         // Each string in an F3 subsection should be preceded by a null
         // character.
         error(object_error::parse_failed);
         return;
       }
 
-      StringRef Filename(StringTable.data() + FilenameOffset);
+      StringRef Filename(CVStringTable.data() + FilenameOffset);
       ListScope S(W, "FilenameSegment");
       W.printString("Filename", Filename);
       for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
@@ -882,3 +887,67 @@ void COFFDumper::printUnwindInfo() {
   }
 }
 
+void COFFDumper::printImportedSymbols(imported_symbol_iterator I,
+                                      imported_symbol_iterator E) {
+  for (; I != E; ++I) {
+    StringRef Sym;
+    if (error(I->getSymbolName(Sym))) return;
+    uint16_t Ordinal;
+    if (error(I->getOrdinal(Ordinal))) return;
+    W.printNumber("Symbol", Sym, Ordinal);
+  }
+}
+
+void COFFDumper::printCOFFImports() {
+  // Regular imports
+  for (auto I = Obj->import_directory_begin(), E = Obj->import_directory_end();
+       I != E; ++I) {
+    DictScope Import(W, "Import");
+    StringRef Name;
+    if (error(I->getName(Name))) return;
+    W.printString("Name", Name);
+    uint32_t Addr;
+    if (error(I->getImportLookupTableRVA(Addr))) return;
+    W.printHex("ImportLookupTableRVA", Addr);
+    if (error(I->getImportAddressTableRVA(Addr))) return;
+    W.printHex("ImportAddressTableRVA", Addr);
+    printImportedSymbols(I->imported_symbol_begin(), I->imported_symbol_end());
+  }
+
+  // Delay imports
+  for (auto I = Obj->delay_import_directory_begin(),
+            E = Obj->delay_import_directory_end();
+       I != E; ++I) {
+    DictScope Import(W, "DelayImport");
+    StringRef Name;
+    if (error(I->getName(Name))) return;
+    W.printString("Name", Name);
+    const delay_import_directory_table_entry *Table;
+    if (error(I->getDelayImportTable(Table))) return;
+    W.printHex("Attributes", Table->Attributes);
+    W.printHex("ModuleHandle", Table->ModuleHandle);
+    W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
+    W.printHex("ImportNameTable", Table->DelayImportNameTable);
+    W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);
+    W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);
+    printImportedSymbols(I->imported_symbol_begin(), I->imported_symbol_end());
+  }
+}
+
+void COFFDumper::printCOFFDirectives() {
+  for (const SectionRef &Section : Obj->sections()) {
+    StringRef Contents;
+    StringRef Name;
+
+    if (error(Section.getName(Name)))
+      continue;
+    if (Name != ".drectve")
+      continue;
+
+    if (error(Section.getContents(Contents)))
+      return;
+
+    W.printString("Directive(s)", Contents);
+  }
+}
+