]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Add size of section header to data relocation offsets.
authorSam Clegg <sbc@chromium.org>
Fri, 28 Apr 2017 21:22:38 +0000 (21:22 +0000)
committerSam Clegg <sbc@chromium.org>
Fri, 28 Apr 2017 21:22:38 +0000 (21:22 +0000)
Also, add test for data relocations and fix addend to
be signed.

Subscribers: jfb, dschuff

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

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

include/llvm/MC/MCSectionWasm.h
include/llvm/MC/MCWasmObjectWriter.h
include/llvm/Support/Wasm.h
lib/MC/WasmObjectWriter.cpp
test/MC/WebAssembly/reloc-data.ll [new file with mode: 0644]

index 4e19196175c074703df2656bf6123c763f17435e..29d62a7a6f82b29483ee41361a30e0725cdb2977 100644 (file)
@@ -26,6 +26,7 @@ class MCSymbol;
 
 /// This represents a section on wasm.
 class MCSectionWasm final : public MCSection {
+private:
   /// This is the name of the section.  The referenced memory is owned by
   /// TargetLoweringObjectFileWasm's WasmUniqueMap.
   StringRef SectionName;
@@ -40,10 +41,11 @@ class MCSectionWasm final : public MCSection {
 
   const MCSymbolWasm *Group;
 
-  // The offset of the MC function section in the wasm code section.
+  // The offset of the MC function/data section in the wasm code/data section.
+  // For data relocations the offset is relative to start of the data payload
+  // itself and does not include the size of the section header.
   uint64_t SectionOffset;
 
-private:
   friend class MCContext;
   MCSectionWasm(StringRef Section, unsigned type, unsigned flags, SectionKind K,
                 const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin)
index 6e458eaac9c83d5e2ac03196106b44662a41f90e..a4dd382706d78f9dad0de2a27060df947297c4e5 100644 (file)
@@ -32,12 +32,12 @@ class raw_pwrite_stream;
 struct WasmRelocationEntry {
   uint64_t Offset;            // Where is the relocation.
   const MCSymbolWasm *Symbol; // The symbol to relocate with.
-  uint64_t Addend;            // A value to add to the symbol.
+  int64_t Addend;             // A value to add to the symbol.
   unsigned Type;              // The type of the relocation.
   MCSectionWasm *FixupSection;// The section the relocation is targeting.
 
   WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
-                      uint64_t Addend, unsigned Type,
+                      int64_t Addend, unsigned Type,
                       MCSectionWasm *FixupSection)
       : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
         FixupSection(FixupSection) {}
index b02fcb19e3d0d46a0aa5e22a5b18872816207f6d..a48dfe10b3bb5d0020d1b97e37b19b8d18fb5d2a 100644 (file)
@@ -108,7 +108,7 @@ struct WasmRelocation {
   uint32_t Type;         // The type of the relocation.
   int32_t Index;         // Index into function to global index space.
   uint64_t Offset;       // Offset from the start of the section.
-  uint64_t Addend;       // A value to add to the symbol.
+  int64_t Addend;        // A value to add to the symbol.
 };
 
 enum : unsigned {
index ae66829741be2a2ce0f1ee55164caf57fd4e1b1d..0540c4c47a3f007cca19bbe5672551c117f401ab 100644 (file)
@@ -468,16 +468,16 @@ static void ApplyRelocations(
 
 // Write out the portions of the relocation records that the linker will
 // need to handle.
-static void WriteRelocations(
-    ArrayRef<WasmRelocationEntry> Relocations,
-    raw_pwrite_stream &Stream,
-    DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices)
-{
+static void
+WriteRelocations(ArrayRef<WasmRelocationEntry> Relocations,
+                 raw_pwrite_stream &Stream,
+                 DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices,
+                 uint64_t HeaderSize) {
   for (const WasmRelocationEntry RelEntry : Relocations) {
     encodeULEB128(RelEntry.Type, Stream);
 
     uint64_t Offset = RelEntry.Offset +
-                      RelEntry.FixupSection->getSectionOffset();
+                      RelEntry.FixupSection->getSectionOffset() + HeaderSize;
     uint32_t Index = SymbolIndices[RelEntry.Symbol];
     int64_t Addend = RelEntry.Addend;
 
@@ -1052,6 +1052,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   }
 
   // === Data Section ==========================================================
+  uint32_t DataSectionHeaderSize = 0;
   if (!DataBytes.empty()) {
     startSection(Section, wasm::WASM_SEC_DATA);
 
@@ -1061,11 +1062,12 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     encodeSLEB128(0, getStream()); // offset
     write8(wasm::WASM_OPCODE_END);
     encodeULEB128(DataBytes.size(), getStream()); // size
+    DataSectionHeaderSize = getStream().tell() - Section.ContentsOffset;
     writeBytes(DataBytes); // data
 
     // Apply fixups.
     ApplyRelocations(DataRelocations, getStream(), SymbolIndices,
-                     Section.ContentsOffset);
+                     Section.ContentsOffset + DataSectionHeaderSize);
 
     endSection(Section);
   }
@@ -1109,7 +1111,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
 
     encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream());
 
-    WriteRelocations(CodeRelocations, getStream(), SymbolIndices);
+    WriteRelocations(CodeRelocations, getStream(), SymbolIndices, 0);
     WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream());
 
     endSection(Section);
@@ -1123,7 +1125,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
 
     encodeULEB128(DataRelocations.size(), getStream());
 
-    WriteRelocations(DataRelocations, getStream(), SymbolIndices);
+    WriteRelocations(DataRelocations, getStream(), SymbolIndices,
+                     DataSectionHeaderSize);
 
     endSection(Section);
   }
diff --git a/test/MC/WebAssembly/reloc-data.ll b/test/MC/WebAssembly/reloc-data.ll
new file mode 100644 (file)
index 0000000..5bd18fa
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: llc -O0 -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s
+
+; foo and bar are external and internal symbols.  a and b are pointers
+; initialized to these locations offset by 2 and -2 elements respecitively.
+@foo = external global i32, align 4
+@bar = global i64 7, align 4
+@a = global i32* getelementptr (i32, i32* @foo, i32 2), align 8
+@b = global i64* getelementptr (i64, i64* @bar, i64 -2), align 8
+
+; CHECK: Format: WASM
+; CHECK: Relocations [
+; CHECK:   Section (6) DATA {
+; CHECK:     Relocation {
+; CHECK:       Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 (5)
+; CHECK:       Offset: 0xE
+; CHECK:       Index: 0x0
+; CHECK:       Addend: 8
+; CHECK:     }
+; CHECK:     Relocation {
+; CHECK:       Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 (5)
+; CHECK:       Offset: 0x16
+; CHECK:       Index: 0x1
+; CHECK:       Addend: -16
+; CHECK:     }
+; CHECK:   }
+; CHECK: ]