[lld] r331566 - [WebAssembly] Add support for debug (DWARF) sections

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri May 4 16:14:42 PDT 2018


Author: sbc
Date: Fri May  4 16:14:42 2018
New Revision: 331566

URL: http://llvm.org/viewvc/llvm-project?rev=331566&view=rev
Log:
[WebAssembly] Add support for debug (DWARF) sections

Specifically add support for custom sections that contain
relocations, and for the two new relocation types needed
by DWARF sections.

See: https://reviews.llvm.org/D44184

Patch by Yury Delendik!

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

Added:
    lld/trunk/test/wasm/Inputs/debuginfo1.ll
    lld/trunk/test/wasm/Inputs/debuginfo2.ll
    lld/trunk/test/wasm/debuginfo.test
Modified:
    lld/trunk/wasm/InputChunks.cpp
    lld/trunk/wasm/InputChunks.h
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/InputFiles.h
    lld/trunk/wasm/OutputSections.cpp
    lld/trunk/wasm/OutputSections.h
    lld/trunk/wasm/Symbols.cpp
    lld/trunk/wasm/Symbols.h
    lld/trunk/wasm/Writer.cpp

Added: lld/trunk/test/wasm/Inputs/debuginfo1.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/debuginfo1.ll?rev=331566&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/debuginfo1.ll (added)
+++ lld/trunk/test/wasm/Inputs/debuginfo1.ll Fri May  4 16:14:42 2018
@@ -0,0 +1,68 @@
+; ModuleID = 'hi.c'
+source_filename = "hi.c"
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; // hi.c:
+; extern void foo(int);
+;  
+; int test(int t) {
+;   return t * t;
+; }
+;
+; int _start() {
+;   foo(test(10));
+;   return 0;
+; }
+
+; Function Attrs: nounwind readnone
+define hidden i32 @test(i32 %t) local_unnamed_addr #0 !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %t, metadata !12, metadata !DIExpression()), !dbg !13
+  %mul = mul nsw i32 %t, %t, !dbg !14
+  ret i32 %mul, !dbg !15
+}
+
+; Function Attrs: nounwind
+define hidden i32 @_start() local_unnamed_addr #1 !dbg !16 {
+entry:
+  tail call void @foo(i32 100) #4, !dbg !19
+  ret i32 0, !dbg !20
+}
+
+declare void @foo(i32) local_unnamed_addr #2
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.0 (trunk 331321)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "hi.c", directory: "/Users/yury/llvmwasm")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 7.0.0 (trunk 331321)"}
+!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!12}
+!12 = !DILocalVariable(name: "t", arg: 1, scope: !7, file: !1, line: 3, type: !10)
+!13 = !DILocation(line: 3, column: 14, scope: !7)
+!14 = !DILocation(line: 4, column: 12, scope: !7)
+!15 = !DILocation(line: 4, column: 3, scope: !7)
+!16 = distinct !DISubprogram(name: "_start", scope: !1, file: !1, line: 7, type: !17, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: true, unit: !0, variables: !2)
+!17 = !DISubroutineType(types: !18)
+!18 = !{!10}
+!19 = !DILocation(line: 8, column: 3, scope: !16)
+!20 = !DILocation(line: 9, column: 3, scope: !16)

Added: lld/trunk/test/wasm/Inputs/debuginfo2.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/debuginfo2.ll?rev=331566&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/debuginfo2.ll (added)
+++ lld/trunk/test/wasm/Inputs/debuginfo2.ll Fri May  4 16:14:42 2018
@@ -0,0 +1,64 @@
+; ModuleID = 'hi_foo.c'
+source_filename = "hi_foo.c"
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; // hi_foo.c:
+; int y[2] = {23, 41};
+;  
+; void foo(int p) {
+;   y[p & 1]++;
+; }
+
+ at y = hidden local_unnamed_addr global [2 x i32] [i32 23, i32 41], align 4, !dbg !0
+
+; Function Attrs: nounwind
+define hidden void @foo(i32 %p) local_unnamed_addr #0 !dbg !14 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %p, metadata !18, metadata !DIExpression()), !dbg !19
+  %and = and i32 %p, 1, !dbg !20
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @y, i32 0, i32 %and, !dbg !21
+  %0 = load i32, i32* %arrayidx, align 4, !dbg !22, !tbaa !23
+  %inc = add nsw i32 %0, 1, !dbg !22
+  store i32 %inc, i32* %arrayidx, align 4, !dbg !22, !tbaa !23
+  ret void, !dbg !27
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11, !12}
+!llvm.ident = !{!13}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "y", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 331321)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "hi_foo.c", directory: "/Users/yury/llvmwasm")
+!4 = !{}
+!5 = !{!0}
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 64, elements: !8)
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{!9}
+!9 = !DISubrange(count: 2)
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!13 = !{!"clang version 7.0.0 (trunk 331321)"}
+!14 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !15, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !2, variables: !17)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null, !7}
+!17 = !{!18}
+!18 = !DILocalVariable(name: "p", arg: 1, scope: !14, file: !3, line: 3, type: !7)
+!19 = !DILocation(line: 3, column: 14, scope: !14)
+!20 = !DILocation(line: 4, column: 7, scope: !14)
+!21 = !DILocation(line: 4, column: 3, scope: !14)
+!22 = !DILocation(line: 4, column: 11, scope: !14)
+!23 = !{!24, !24, i64 0}
+!24 = !{!"int", !25, i64 0}
+!25 = !{!"omnipotent char", !26, i64 0}
+!26 = !{!"Simple C/C++ TBAA"}
+!27 = !DILocation(line: 5, column: 1, scope: !14)

Added: lld/trunk/test/wasm/debuginfo.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/debuginfo.test?rev=331566&view=auto
==============================================================================
--- lld/trunk/test/wasm/debuginfo.test (added)
+++ lld/trunk/test/wasm/debuginfo.test Fri May  4 16:14:42 2018
@@ -0,0 +1,73 @@
+RUN: llc -filetype=obj %p/Inputs/debuginfo1.ll -o %t.debuginfo1.o
+RUN: llc -filetype=obj %p/Inputs/debuginfo2.ll -o %t.debuginfo2.o
+RUN: wasm-ld -r -o %t.wasm %t.debuginfo1.o %t.debuginfo2.o
+RUN: llvm-dwarfdump %t.wasm | FileCheck %s
+
+CHECK: file format WASM
+
+CHECK: .debug_info contents:
+CHECK: DW_TAG_compile_unit
+CHECK-NEXT:              DW_AT_producer	("clang version 7.0.0 (trunk 331321)")
+CHECK-NEXT:              DW_AT_language	(DW_LANG_C99)
+CHECK-NEXT:              DW_AT_name	("hi.c")
+
+CHECK:   DW_TAG_subprogram
+CHECK-NEXT:                DW_AT_low_pc
+CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_name	("test")
+CHECK-NEXT:                DW_AT_decl_file	("/Users/yury/llvmwasm/hi.c")
+CHECK-NEXT:                DW_AT_decl_line	(3)
+CHECK-NEXT:                DW_AT_prototyped	(true)
+
+CHECK:     DW_TAG_formal_parameter
+CHECK-NEXT:                  DW_AT_name	("t")
+CHECK-NEXT:                  DW_AT_decl_file	("/Users/yury/llvmwasm/hi.c")
+CHECK-NEXT:                  DW_AT_decl_line	(3)
+
+CHECK:   DW_TAG_subprogram
+CHECK-NEXT:                DW_AT_low_pc
+CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_name	("_start")
+CHECK-NEXT:                DW_AT_decl_file	("/Users/yury/llvmwasm/hi.c")
+CHECK-NEXT:                DW_AT_decl_line	(7)
+
+CHECK:   DW_TAG_base_type
+CHECK-NEXT:                DW_AT_name	("int")
+CHECK-NEXT:                DW_AT_encoding	(DW_ATE_signed)
+CHECK-NEXT:                DW_AT_byte_size	(0x04)
+
+CHECK: DW_TAG_compile_unit
+CHECK-NEXT:              DW_AT_producer	("clang version 7.0.0 (trunk 331321)")
+CHECK-NEXT:              DW_AT_language	(DW_LANG_C99)
+CHECK-NEXT:              DW_AT_name	("hi_foo.c")
+
+CHECK:   DW_TAG_variable
+CHECK-NEXT:                DW_AT_name	("y")
+CHECK-NEXT:                "int[]"
+
+CHECK:   DW_TAG_array_type
+
+CHECK:     DW_TAG_subrange_type
+
+CHECK:   DW_TAG_base_type
+CHECK-NEXT:                DW_AT_name	("int")
+CHECK-NEXT:                DW_AT_encoding	(DW_ATE_signed)
+CHECK-NEXT:                DW_AT_byte_size	(0x04)
+
+CHECK:   DW_TAG_base_type
+CHECK-NEXT:                DW_AT_name	("__ARRAY_SIZE_TYPE__")
+CHECK-NEXT:                DW_AT_byte_size	(0x08)
+CHECK-NEXT:                DW_AT_encoding	(DW_ATE_unsigned)
+
+CHECK:   DW_TAG_subprogram
+CHECK-NEXT:                DW_AT_low_pc	
+CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_name	("foo")
+CHECK-NEXT:                DW_AT_decl_file	("/Users/yury/llvmwasm/hi_foo.c")
+CHECK-NEXT:                DW_AT_decl_line	(3)
+
+CHECK:     DW_TAG_formal_parameter
+CHECK-NEXT:                  DW_AT_name	("p")
+CHECK-NEXT:                  DW_AT_decl_file	("/Users/yury/llvmwasm/hi_foo.c")
+CHECK-NEXT:                  DW_AT_decl_line	(3)
+

Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Fri May  4 16:14:42 2018
@@ -89,6 +89,8 @@ void InputChunk::writeTo(uint8_t *Buf) c
       break;
     case R_WEBASSEMBLY_TABLE_INDEX_I32:
     case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+    case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+    case R_WEBASSEMBLY_SECTION_OFFSET_I32:
       ExistingValue = static_cast<uint32_t>(read32le(Loc));
       write32le(Loc, Value);
       break;
@@ -124,7 +126,9 @@ void InputChunk::writeRelocations(raw_os
     case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
     case R_WEBASSEMBLY_MEMORY_ADDR_I32:
-      writeSleb128(OS, Rel.Addend, "reloc addend");
+    case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+    case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+      writeSleb128(OS, File->calcNewAddend(Rel), "reloc addend");
       break;
     }
   }

Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Fri May  4 16:14:42 2018
@@ -130,6 +130,8 @@ public:
   StringRef getName() const override { return Function->SymbolName; }
   StringRef getDebugName() const override { return Function->DebugName; }
   uint32_t getComdat() const override { return Function->Comdat; }
+  const ArrayRef<uint8_t> getFunctionBody() const { return Function->Body; }
+  uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); }
   uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }
   bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }
   void setFunctionIndex(uint32_t Index);

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Fri May  4 16:14:42 2018
@@ -16,6 +16,7 @@
 #include "lld/Common/Memory.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/Wasm.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/raw_ostream.h"
 
 #define DEBUG_TYPE "lld"
@@ -42,6 +43,12 @@ Optional<MemoryBufferRef> lld::wasm::rea
   return MBRef;
 }
 
+static size_t getFunctionCodeOffset(ArrayRef<uint8_t> FunctionBody) {
+  unsigned Count;
+  llvm::decodeULEB128(FunctionBody.data(), &Count);
+  return Count;
+}
+
 void ObjFile::dumpInfo() const {
   log("info for: " + getName() +
       "\n              Symbols : " + Twine(Symbols.size()) +
@@ -60,6 +67,22 @@ uint32_t ObjFile::calcNewIndex(const Was
   return Symbols[Reloc.Index]->getOutputSymbolIndex();
 }
 
+// Relocations can contain addend for combined sections. This function takes a
+// relocation and returns updated addend by offset in the output section.
+uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {
+  switch (Reloc.Type) {
+  case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+  case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+  case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+  case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+    return Reloc.Addend;
+  case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+    return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
+  default:
+    llvm_unreachable("unexpected relocation type");
+  }
+}
+
 // Calculate the value we expect to find at the relocation location.
 // This is used as a sanity check before applying a relocation to a given
 // location.  It is useful for catching bugs in the compiler and linker.
@@ -80,6 +103,16 @@ uint32_t ObjFile::calcExpectedValue(cons
     return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset +
            Reloc.Addend;
   }
+  case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+    if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {
+      size_t FunctionCodeOffset =
+          getFunctionCodeOffset(Sym->Function->getFunctionBody());
+      return Sym->Function->getFunctionInputOffset() + FunctionCodeOffset +
+             Reloc.Addend;
+    }
+    return 0;
+  case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+    return Reloc.Addend;
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     return Reloc.Index;
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
@@ -110,6 +143,15 @@ uint32_t ObjFile::calcNewValue(const Was
     return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     return getGlobalSymbol(Reloc.Index)->getGlobalIndex();
+  case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+    if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {
+      size_t FunctionCodeOffset =
+          getFunctionCodeOffset(Sym->Function->getFunctionBody());
+      return Sym->Function->OutputOffset + FunctionCodeOffset + Reloc.Addend;
+    }
+    return 0;
+  case R_WEBASSEMBLY_SECTION_OFFSET_I32:
+    return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
   default:
     llvm_unreachable("unknown relocation type");
   }
@@ -147,14 +189,19 @@ void ObjFile::parse() {
 
   // Find the code and data sections.  Wasm objects can have at most one code
   // and one data section.
+  uint32_t SectionIndex = 0;
   for (const SectionRef &Sec : WasmObj->sections()) {
     const WasmSection &Section = WasmObj->getWasmSection(Sec);
-    if (Section.Type == WASM_SEC_CODE)
+    if (Section.Type == WASM_SEC_CODE) {
       CodeSection = &Section;
-    else if (Section.Type == WASM_SEC_DATA)
+    } else if (Section.Type == WASM_SEC_DATA) {
       DataSection = &Section;
-    else if (Section.Type == WASM_SEC_CUSTOM)
+    } else if (Section.Type == WASM_SEC_CUSTOM) {
       CustomSections.emplace_back(make<InputSection>(Section, this));
+      CustomSections.back()->copyRelocations(Section);
+      CustomSectionsByIndex[SectionIndex] = CustomSections.back();
+    }
+    SectionIndex++;
   }
 
   TypeMap.resize(getWasmObj()->types().size());
@@ -215,6 +262,10 @@ GlobalSymbol *ObjFile::getGlobalSymbol(u
   return cast<GlobalSymbol>(Symbols[Index]);
 }
 
+SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const {
+  return cast<SectionSymbol>(Symbols[Index]);
+}
+
 DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
   return cast<DataSymbol>(Symbols[Index]);
 }
@@ -253,14 +304,20 @@ Symbol *ObjFile::createDefined(const Was
       return make<DefinedData>(Name, Flags, this, Seg, Offset, Size);
     return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size);
   }
-  case WASM_SYMBOL_TYPE_GLOBAL:
+  case WASM_SYMBOL_TYPE_GLOBAL: {
     InputGlobal *Global =
         Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()];
     if (Sym.isBindingLocal())
       return make<DefinedGlobal>(Name, Flags, this, Global);
     return Symtab->addDefinedGlobal(Name, Flags, this, Global);
   }
-  llvm_unreachable("unkown symbol kind");
+  case WASM_SYMBOL_TYPE_SECTION: {
+    InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
+    assert(Sym.isBindingLocal());
+    return make<SectionSymbol>(Name, Flags, Section, this);
+  }
+  }
+  llvm_unreachable("unknown symbol kind");
 }
 
 Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
@@ -274,8 +331,10 @@ Symbol *ObjFile::createUndefined(const W
     return Symtab->addUndefinedData(Name, Flags, this);
   case WASM_SYMBOL_TYPE_GLOBAL:
     return Symtab->addUndefinedGlobal(Name, Flags, this, Sym.GlobalType);
+  case WASM_SYMBOL_TYPE_SECTION:
+    llvm_unreachable("section symbols cannot be undefined");
   }
-  llvm_unreachable("unkown symbol kind");
+  llvm_unreachable("unknown symbol kind");
 }
 
 void ArchiveFile::parse() {

Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Fri May  4 16:14:42 2018
@@ -95,6 +95,7 @@ public:
 
   uint32_t calcNewIndex(const WasmRelocation &Reloc) const;
   uint32_t calcNewValue(const WasmRelocation &Reloc) const;
+  uint32_t calcNewAddend(const WasmRelocation &Reloc) const;
   uint32_t calcExpectedValue(const WasmRelocation &Reloc) const;
 
   const WasmSection *CodeSection = nullptr;
@@ -110,12 +111,14 @@ public:
   std::vector<InputFunction *> Functions;
   std::vector<InputGlobal *> Globals;
   std::vector<InputSection *> CustomSections;
+  llvm::DenseMap<uint32_t, InputSection *> CustomSectionsByIndex;
 
   ArrayRef<Symbol *> getSymbols() const { return Symbols; }
   Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; }
   FunctionSymbol *getFunctionSymbol(uint32_t Index) const;
   DataSymbol *getDataSymbol(uint32_t Index) const;
   GlobalSymbol *getGlobalSymbol(uint32_t Index) const;
+  SectionSymbol *getSectionSymbol(uint32_t Index) const;
 
 private:
   Symbol *createDefined(const WasmSymbol &Sym);

Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Fri May  4 16:14:42 2018
@@ -224,3 +224,15 @@ void CustomSection::writeTo(uint8_t *Buf
   parallelForEach(InputSections,
                   [&](const InputSection *Section) { Section->writeTo(Buf); });
 }
+
+uint32_t CustomSection::numRelocations() const {
+  uint32_t Count = 0;
+  for (const InputSection *InputSect : InputSections)
+    Count += InputSect->NumRelocations();
+  return Count;
+}
+
+void CustomSection::writeRelocations(raw_ostream &OS) const {
+  for (const InputSection *S : InputSections)
+    S->writeRelocations(OS);
+}

Modified: lld/trunk/wasm/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.h?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.h (original)
+++ lld/trunk/wasm/OutputSections.h Fri May  4 16:14:42 2018
@@ -127,6 +127,8 @@ public:
     return Header.size() + NameData.size() + PayloadSize;
   }
   void writeTo(uint8_t *Buf) override;
+  uint32_t numRelocations() const override;
+  void writeRelocations(raw_ostream &OS) const override;
 
 protected:
   size_t PayloadSize;

Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Fri May  4 16:14:42 2018
@@ -36,6 +36,8 @@ WasmSymbolType Symbol::getWasmType() con
     return llvm::wasm::WASM_SYMBOL_TYPE_DATA;
   if (isa<GlobalSymbol>(this))
     return llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL;
+  if (isa<SectionSymbol>(this))
+    return llvm::wasm::WASM_SYMBOL_TYPE_SECTION;
   llvm_unreachable("invalid symbol kind");
 }
 
@@ -194,6 +196,19 @@ DefinedGlobal::DefinedGlobal(StringRef N
                    Global ? &Global->getType() : nullptr),
       Global(Global) {}
 
+uint32_t SectionSymbol::getOutputSectionIndex() const {
+  DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
+  assert(OutputSectionIndex != INVALID_INDEX);
+  return OutputSectionIndex;
+}
+
+void SectionSymbol::setOutputSectionIndex(uint32_t Index) {
+  DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index
+               << "\n");
+  assert(Index != INVALID_INDEX);
+  OutputSectionIndex = Index;
+}
+
 void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
 
 std::string lld::toString(const wasm::Symbol &Sym) {
@@ -219,6 +234,8 @@ std::string lld::toString(wasm::Symbol::
     return "UndefinedGlobal";
   case wasm::Symbol::LazyKind:
     return "LazyKind";
+  case wasm::Symbol::SectionKind:
+    return "SectionKind";
   }
   llvm_unreachable("invalid symbol kind");
 }

Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Fri May  4 16:14:42 2018
@@ -30,6 +30,7 @@ class InputChunk;
 class InputSegment;
 class InputFunction;
 class InputGlobal;
+class InputSection;
 
 #define INVALID_INDEX UINT32_MAX
 
@@ -40,6 +41,7 @@ public:
     DefinedFunctionKind,
     DefinedDataKind,
     DefinedGlobalKind,
+    SectionKind,
     UndefinedFunctionKind,
     UndefinedDataKind,
     UndefinedGlobalKind,
@@ -50,7 +52,7 @@ public:
 
   bool isDefined() const {
     return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
-           SymbolKind == DefinedGlobalKind;
+           SymbolKind == DefinedGlobalKind || SymbolKind == SectionKind;
   }
 
   bool isUndefined() const {
@@ -155,6 +157,23 @@ public:
   }
 };
 
+class SectionSymbol : public Symbol {
+public:
+  static bool classof(const Symbol *S) { return S->kind() == SectionKind; }
+
+  SectionSymbol(StringRef Name, uint32_t Flags, const InputSection *S,
+                InputFile *F = nullptr)
+      : Symbol(Name, SectionKind, Flags, F), Section(S) {}
+
+  const InputSection *Section;
+
+  uint32_t getOutputSectionIndex() const;
+  void setOutputSectionIndex(uint32_t Index);
+
+protected:
+  uint32_t OutputSectionIndex = INVALID_INDEX;
+};
+
 class DataSymbol : public Symbol {
 public:
   static bool classof(const Symbol *S) {
@@ -301,6 +320,7 @@ union SymbolUnion {
   alignas(UndefinedFunction) char E[sizeof(UndefinedFunction)];
   alignas(UndefinedData) char F[sizeof(UndefinedData)];
   alignas(UndefinedGlobal) char G[sizeof(UndefinedGlobal)];
+  alignas(SectionSymbol) char I[sizeof(SectionSymbol)];
 };
 
 template <typename T, typename... ArgT>

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=331566&r1=331565&r2=331566&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Fri May  4 16:14:42 2018
@@ -67,6 +67,7 @@ private:
   void assignIndexes();
   void calculateImports();
   void calculateExports();
+  void calculateCustomSections();
   void assignSymtab();
   void calculateTypes();
   void createOutputSegments();
@@ -114,6 +115,7 @@ private:
   std::vector<WasmInitEntry> InitFunctions;
 
   llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
+  llvm::StringMap<SectionSymbol *> CustomSectionSymbols;
 
   // Elements that are used to construct the final output
   std::string Header;
@@ -299,18 +301,35 @@ void Writer::createExportSection() {
   }
 }
 
+void Writer::calculateCustomSections() {
+  log("calculateCustomSections");
+  bool StripDebug = Config->StripDebug || Config->StripAll;
+  for (ObjFile *File : Symtab->ObjectFiles) {
+    for (InputSection *Section : File->CustomSections) {
+      StringRef Name = Section->getName();
+      // These custom sections are known the linker and synthesized rather than
+      // blindly copied
+      if (Name == "linking" || Name == "name" || Name.startswith("reloc."))
+        continue;
+      // .. or it is a debug section
+      if (StripDebug && Name.startswith(".debug_"))
+        continue;
+      CustomSectionMapping[Name].push_back(Section);
+    }
+  }
+}
+
 void Writer::createCustomSections() {
   log("createCustomSections");
-  for (ObjFile *File : Symtab->ObjectFiles)
-    for (InputSection *Section : File->CustomSections)
-      CustomSectionMapping[Section->getName()].push_back(Section);
-
   for (auto &Pair : CustomSectionMapping) {
     StringRef Name = Pair.first();
-    // These custom sections are known the linker and synthesized rather than
-    // blindly copied
-    if (Name == "linking" || Name == "name" || Name.startswith("reloc."))
-      continue;
+
+    auto P = CustomSectionSymbols.find(Name);
+    if (P != CustomSectionSymbols.end()) {
+      uint32_t SectionIndex = OutputSections.size();
+      P->second->setOutputSectionIndex(SectionIndex);
+    }
+
     DEBUG(dbgs() << "createCustomSection: " << Name << "\n");
     OutputSections.push_back(make<CustomSection>(Name, Pair.second));
   }
@@ -375,8 +394,11 @@ void Writer::createRelocSections() {
       Name = "reloc.DATA";
     else if (OSec->Type == WASM_SEC_CODE)
       Name = "reloc.CODE";
+    else if (OSec->Type == WASM_SEC_CUSTOM)
+      Name = Saver.save("reloc." + OSec->Name);
     else
-      llvm_unreachable("relocations only supported for code and data");
+      llvm_unreachable(
+          "relocations only supported for code, data, or custom sections");
 
     SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, Name);
     raw_ostream &OS = Section->getStream();
@@ -452,8 +474,7 @@ void Writer::createLinkingSection() {
         writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
         if (Sym->isDefined())
           writeStr(Sub.OS, Sym->getName(), "sym name");
-      } else {
-        assert(isa<DataSymbol>(Sym));
+      } else if (auto *D = dyn_cast<DataSymbol>(Sym)) {
         writeStr(Sub.OS, Sym->getName(), "sym name");
         if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
           writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
@@ -461,6 +482,9 @@ void Writer::createLinkingSection() {
                        "data offset");
           writeUleb128(Sub.OS, DataSym->getSize(), "data size");
         }
+      } else {
+        auto *S = cast<SectionSymbol>(Sym);
+        writeUleb128(Sub.OS, S->getOutputSectionIndex(), "sym section index");
       }
     }
 
@@ -751,12 +775,32 @@ void Writer::assignSymtab() {
   if (!Config->Relocatable)
     return;
 
+  StringMap<uint32_t> SectionSymbolIndices;
+
   unsigned SymbolIndex = SymtabEntries.size();
   for (ObjFile *File : Symtab->ObjectFiles) {
     DEBUG(dbgs() << "Symtab entries: " << File->getName() << "\n");
     for (Symbol *Sym : File->getSymbols()) {
       if (Sym->getFile() != File)
         continue;
+
+      if (auto *S = dyn_cast<SectionSymbol>(Sym)) {
+        StringRef Name = S->getName();
+        if (CustomSectionMapping.count(Name) == 0)
+          continue;
+
+        auto SSI = SectionSymbolIndices.find(Name);
+        if (SSI != SectionSymbolIndices.end()) {
+          Sym->setOutputSymbolIndex(SSI->second);
+          continue;
+        }
+
+        SectionSymbolIndices[Name] = SymbolIndex;
+        CustomSectionSymbols[Name] = cast<SectionSymbol>(Sym);
+
+        Sym->markLive();
+      }
+
       // (Since this is relocatable output, GC is not performed so symbols must
       // be live.)
       assert(Sym->isLive());
@@ -855,6 +899,8 @@ void Writer::assignIndexes() {
       HandleRelocs(Chunk);
     for (InputChunk *Chunk : File->Segments)
       HandleRelocs(Chunk);
+    for (auto &P : File->CustomSections)
+      HandleRelocs(P);
   }
 
   uint32_t GlobalIndex = NumImportedGlobals + InputGlobals.size();
@@ -976,6 +1022,8 @@ void Writer::run() {
   layoutMemory();
   log("-- calculateExports");
   calculateExports();
+  log("-- calculateCustomSections");
+  calculateCustomSections();
   log("-- assignSymtab");
   assignSymtab();
 




More information about the llvm-commits mailing list