]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Add wasm support for llvm-readobj
authorDerek Schuff <dschuff@google.com>
Mon, 30 Jan 2017 23:30:52 +0000 (23:30 +0000)
committerDerek Schuff <dschuff@google.com>
Mon, 30 Jan 2017 23:30:52 +0000 (23:30 +0000)
Create a WasmDumper subclass of ObjDumper to support Webassembly binary
files.

Patch by Sam Clegg

Differential Revision: https://reviews.llvm.org/D27355

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293569 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/Wasm.h
include/llvm/Support/Wasm.h
lib/Object/WasmObjectFile.cpp
test/tools/llvm-readobj/Inputs/trivial.obj.wasm [new file with mode: 0644]
test/tools/llvm-readobj/file-headers.test
test/tools/llvm-readobj/sections.test
tools/llvm-readobj/CMakeLists.txt
tools/llvm-readobj/ObjDumper.h
tools/llvm-readobj/WasmDumper.cpp [new file with mode: 0644]
tools/llvm-readobj/llvm-readobj.cpp

index 2ece6a6c3770d7d9d5b852b1dc032ad81f9d3028..999d575943b6c85ac41a1b027707586705f1ad2b 100644 (file)
@@ -87,8 +87,8 @@ protected:
 
 private:
   const uint8_t *getPtr(size_t Offset) const;
-  Error parseUserSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
-                         size_t Length);
+  Error parseCustomSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
+                           size_t Length);
 
   wasm::WasmObjectHeader Header;
   std::vector<wasm::WasmSection> Sections;
index 8ac6b9038e913eed7289e4bacca9e2444adec4d6..b45149577a0ae4a24101eabb9f7b2eace4fa2f45 100644 (file)
@@ -38,7 +38,7 @@ struct WasmSection {
 };
 
 enum : unsigned {
-  WASM_SEC_USER = 0,     // User-defined section
+  WASM_SEC_CUSTOM = 0,   // Custom / User-defined section
   WASM_SEC_TYPE = 1,     // Function signature declarations
   WASM_SEC_IMPORT = 2,   // Import declarations
   WASM_SEC_FUNCTION = 3, // Function declarations
index 2b61a8a034f6c09ecadcc0e0e92575a826f114ff..e61ae156a749b5386da9d062c0205358507f5e96 100644 (file)
@@ -83,16 +83,17 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
   while (Ptr < Eof) {
     if ((Err = readSection(Sec, Ptr, getPtr(0))))
       return;
-    if (Sec.Type == wasm::WASM_SEC_USER) {
-      if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size())))
+    if (Sec.Type == wasm::WASM_SEC_CUSTOM) {
+      if ((Err =
+               parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size())))
         return;
     }
     Sections.push_back(Sec);
   }
 }
 
-Error WasmObjectFile::parseUserSection(wasm::WasmSection &Sec,
-                                       const uint8_t *Ptr, size_t Length) {
+Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec,
+                                         const uint8_t *Ptr, size_t Length) {
   Sec.Name = readString(Ptr);
   return Error::success();
 }
@@ -186,7 +187,7 @@ std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
     ECase(ELEM);
     ECase(CODE);
     ECase(DATA);
-  case wasm::WASM_SEC_USER:
+  case wasm::WASM_SEC_CUSTOM:
     Res = S.Name;
     break;
   default:
diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.wasm b/test/tools/llvm-readobj/Inputs/trivial.obj.wasm
new file mode 100644 (file)
index 0000000..b24ac79
Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/trivial.obj.wasm differ
index 662c9b6bd4d7b69c9cc8a4c9eba7fda3575cc7b2..4fcb2859d27a5c40b57719833013970ed61c3b28 100644 (file)
@@ -26,6 +26,12 @@ RUN: llvm-readobj -h %p/Inputs/magic.coff-importlib \
 RUN:   | FileCheck %s -check-prefix COFF-IMPORTLIB
 RUN: llvm-readobj -h %p/Inputs/trivial.obj.elf-lanai \
 RUN:   | FileCheck %s -check-prefix ELF-LANAI
+# trivial.obj.wasm was generated using wast2wasm which is part of the wabt
+# project (https://github.com/WebAssembly/wabt) using the following command:
+# $ wast2wasm --debug-names ./test/roundtrip/generate-some-names.txt -o \
+#   trivial.obj.wasm
+RUN: llvm-readobj -h %p/Inputs/trivial.obj.wasm \
+RUN:   | FileCheck %s -check-prefix WASM
 
 COFF-ARM:      File: {{(.*[/\\])?}}trivial.obj.coff-arm
 COFF-ARM-NEXT: Format: COFF-ARM
@@ -367,3 +373,8 @@ ELF-LANAI-NEXT:   SectionHeaderEntrySize: 40
 ELF-LANAI-NEXT:   SectionHeaderCount: 8
 ELF-LANAI-NEXT:   StringTableSectionIndex: 1
 ELF-LANAI-NEXT: }
+
+WASM: Format: WASM
+WASM-NEXT: Arch: wasm32
+WASM-NEXT: AddressSize: 32bit
+WASM-NEXT: Version: 0xD
index 54654e7070effa1ff0d2706b005ec65213c82093..26a72d85e49cf41c5b52c935cad3ce521744d42e 100644 (file)
@@ -14,6 +14,8 @@ RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc64 \
 RUN:   | FileCheck %s -check-prefix MACHO-PPC64
 RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-arm \
 RUN:   | FileCheck %s -check-prefix MACHO-ARM
+RUN: llvm-readobj -s %p/Inputs/trivial.obj.wasm \
+RUN:   | FileCheck %s -check-prefix WASM
 
 COFF:      Sections [
 COFF-NEXT:   Section {
@@ -490,3 +492,47 @@ MACHO-ARM-NEXT:    Reserved1: 0x0
 MACHO-ARM-NEXT:    Reserved2: 0x0
 MACHO-ARM-NEXT:  }
 MACHO-ARM-NEXT:]
+
+WASM: Sections [
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: TYPE (0x1)
+WASM-NEXT:     Size: 15
+WASM-NEXT:     Offset: 8
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: IMPORT (0x2)
+WASM-NEXT:     Size: 11
+WASM-NEXT:     Offset: 25
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: FUNCTION (0x3)
+WASM-NEXT:     Size: 3
+WASM-NEXT:     Offset: 38
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: TABLE (0x4)
+WASM-NEXT:     Size: 5
+WASM-NEXT:     Offset: 43
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: EXPORT (0x7)
+WASM-NEXT:     Size: 14
+WASM-NEXT:     Offset: 50
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: ELEM (0x9)
+WASM-NEXT:     Size: 7
+WASM-NEXT:     Offset: 66
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: CODE (0xA)
+WASM-NEXT:     Size: 42
+WASM-NEXT:     Offset: 75
+WASM-NEXT:   }
+WASM-NEXT:   Section {
+WASM-NEXT:     Type: CUSTOM (0x0)
+WASM-NEXT:     Size: 44
+WASM-NEXT:     Offset: 119
+WASM-NEXT:     Name: name
+WASM-NEXT:   }
+WASM-NEXT: ]
index d4b7125dbbbc626c51c9105aac235cb99d2baee2..5fd45a8cff688a4555a649b10aa85262d0e8a93b 100644 (file)
@@ -15,5 +15,6 @@ add_llvm_tool(llvm-readobj
   llvm-readobj.cpp
   MachODumper.cpp
   ObjDumper.cpp
+  WasmDumper.cpp
   Win64EHDumper.cpp
   )
index c91558ecbfa7594bb0ad66518d8153f29b8c6db7..75090312b214f4b4d3462cacac0c75ef2b703ad8 100644 (file)
@@ -96,6 +96,10 @@ std::error_code createMachODumper(const object::ObjectFile *Obj,
                                   ScopedPrinter &Writer,
                                   std::unique_ptr<ObjDumper> &Result);
 
+std::error_code createWasmDumper(const object::ObjectFile *Obj,
+                                 ScopedPrinter &Writer,
+                                 std::unique_ptr<ObjDumper> &Result);
+
 void dumpCOFFImportFile(const object::COFFImportFile *File);
 
 void dumpCodeViewMergedTypes(ScopedPrinter &Writer,
diff --git a/tools/llvm-readobj/WasmDumper.cpp b/tools/llvm-readobj/WasmDumper.cpp
new file mode 100644 (file)
index 0000000..8f3ec57
--- /dev/null
@@ -0,0 +1,92 @@
+//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Wasm-specific dumper for llvm-readobj.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "ObjDumper.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+
+const char *wasmSectionTypeToString(uint32_t Type) {
+#define ECase(X)                                                               \
+  case wasm::WASM_SEC_##X:                                                     \
+    return #X;
+  switch (Type) {
+    ECase(CUSTOM);
+    ECase(TYPE);
+    ECase(IMPORT);
+    ECase(FUNCTION);
+    ECase(TABLE);
+    ECase(MEMORY);
+    ECase(GLOBAL);
+    ECase(EXPORT);
+    ECase(START);
+    ECase(ELEM);
+    ECase(CODE);
+    ECase(DATA);
+  }
+#undef ECase
+  return "";
+}
+
+class WasmDumper : public ObjDumper {
+public:
+  WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
+      : ObjDumper(Writer), Obj(Obj) {}
+
+  void printFileHeaders() override {
+    W.printHex("Version", Obj->getHeader().Version);
+  }
+
+  void printSections() override {
+    ListScope Group(W, "Sections");
+    for (const SectionRef &Section : Obj->sections()) {
+      const wasm::WasmSection *WasmSec = Obj->getWasmSection(Section);
+      DictScope SectionD(W, "Section");
+      const char *Type = wasmSectionTypeToString(WasmSec->Type);
+      W.printHex("Type", Type, WasmSec->Type);
+      W.printNumber("Size", WasmSec->Content.size());
+      W.printNumber("Offset", WasmSec->Offset);
+      if (WasmSec->Type == wasm::WASM_SEC_CUSTOM) {
+        W.printString("Name", WasmSec->Name);
+      }
+    }
+  }
+  void printRelocations() override { llvm_unreachable("unimplemented"); }
+  void printSymbols() override { llvm_unreachable("unimplemented"); }
+  void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
+  void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
+  void printStackMap() const override { llvm_unreachable("unimplemented"); }
+
+private:
+  const WasmObjectFile *Obj;
+};
+}
+
+namespace llvm {
+
+std::error_code createWasmDumper(const object::ObjectFile *Obj,
+                                 ScopedPrinter &Writer,
+                                 std::unique_ptr<ObjDumper> &Result) {
+  const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
+  assert(WasmObj && "createWasmDumper called with non-wasm object");
+
+  Result.reset(new WasmDumper(WasmObj, Writer));
+  return readobj_error::success;
+}
+
+} // namespace llvm
index 970e1545de0ad968d7649e5a1f8d494e0f93fd02..fffcd1790e3f635acb751eefd88757ccd8ec5d27 100644 (file)
@@ -358,6 +358,8 @@ static std::error_code createDumper(const ObjectFile *Obj,
     return createELFDumper(Obj, Writer, Result);
   if (Obj->isMachO())
     return createMachODumper(Obj, Writer, Result);
+  if (Obj->isWasm())
+    return createWasmDumper(Obj, Writer, Result);
 
   return readobj_error::unsupported_obj_file_format;
 }