[lld] ad1f545 - [WebAssembly] Generate R_WASM_FUNCTION_OFFSET relocs in debuginfo sections

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 19 14:06:02 PDT 2021


Author: Derek Schuff
Date: 2021-07-19T14:02:33-07:00
New Revision: ad1f5457d2d89efa49a722404a5f0b744b7a64d1

URL: https://github.com/llvm/llvm-project/commit/ad1f5457d2d89efa49a722404a5f0b744b7a64d1
DIFF: https://github.com/llvm/llvm-project/commit/ad1f5457d2d89efa49a722404a5f0b744b7a64d1.diff

LOG: [WebAssembly] Generate R_WASM_FUNCTION_OFFSET relocs in debuginfo sections

Debug info sections need R_WASM_FUNCTION_OFFSET_I32 relocs (with FK_Data_4 fixup
kinds) to refer to functions (instead of R_WASM_TABLE_INDEX as is used in data
sections). Usually this is done in a convoluted way, with unnamed temp data
symbols which target the start of the function, in which case
WasmObjectWriter::recordRelocation converts it to use the section symbol
instead. However in some cases the function can actually be undefined; in this
case the dwarf generator uses the function symbol (a named undefined function
symbol) instead. In that case the section-symbol transform doesn't work and we
need to generate the correct reloc type a different way. In this change
WebAssemblyWasmObjectWriter::getRelocType takes the fixup section type into
account to choose the correct reloc type.

Fixes PR50408
Differential Revision: https://reviews.llvm.org/D103557

Added: 
    llvm/test/MC/WebAssembly/debug-template-param.ll
    llvm/test/MC/WebAssembly/debuginfo-relocs.s

Modified: 
    lld/test/wasm/map-file.s
    llvm/include/llvm/MC/MCWasmObjectWriter.h
    llvm/lib/MC/WasmObjectWriter.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp

Removed: 
    lld/test/wasm/debuginfo-relocs.s


################################################################################
diff  --git a/lld/test/wasm/debuginfo-relocs.s b/lld/test/wasm/debuginfo-relocs.s
deleted file mode 100644
index bece55f54ff29..0000000000000
--- a/lld/test/wasm/debuginfo-relocs.s
+++ /dev/null
@@ -1,23 +0,0 @@
-# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
-# RUN: wasm-ld %t.o -o %t.wasm
-# RUN: obj2yaml %t.wasm | FileCheck %s
-
-bar:
-    .functype bar () -> ()
-    end_function
-
-    .globl _start
-_start:
-    .functype _start () -> ()
-    call bar
-    end_function
-
-    .section .debug_info,"",@
-    .int32 bar
-
-# Even though `bar` is live in the final binary it doesn't have a table entry
-# since its not address taken in the code.  In this case any relocations in the
-# debug sections see a address of zero.
-
-# CHECK:         Name:            .debug_info
-# CHECK-NEXT:    Payload:         '00000000'

diff  --git a/lld/test/wasm/map-file.s b/lld/test/wasm/map-file.s
index a1964fb6ecd1f..1aae7a7aa2bd0 100644
--- a/lld/test/wasm/map-file.s
+++ b/lld/test/wasm/map-file.s
@@ -29,8 +29,9 @@ _start:
 
 .section .data.somedata,"",@
 somedata:
-    .int32 123
-.size somedata, 4
+  .int32 123
+  .int32 bar
+.size somedata, 8
 
 .section .bss.somezeroes,"",@
 somezeroes:
@@ -50,22 +51,23 @@ somezeroes:
 # CHECK-NEXT:       0        0        0         __stack_pointer
 # CHECK-NEXT:       1        0        0         wasm_global
 # CHECK-NEXT:       -       37       15 EXPORT
-# CHECK-NEXT:       -       4c       2d CODE
-# CHECK-NEXT:       -       4d       10         {{.*}}{{/|\\}}map-file.s.tmp1.o:(bar)
-# CHECK-NEXT:       -       4d       10                 bar
-# CHECK-NEXT:       -       5d        b         {{.*}}{{/|\\}}map-file.s.tmp1.o:(write_global)
-# CHECK-NEXT:       -       5d        b                 write_global
-# CHECK-NEXT:       -       68        f         {{.*}}{{/|\\}}map-file.s.tmp1.o:(_start)
-# CHECK-NEXT:       -       68        f                 _start
-# CHECK-NEXT:       -       79        d DATA
-# CHECK-NEXT:     400       7a        4 .data
-# CHECK-NEXT:     400       80        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
-# CHECK-NEXT:     400       80        4                 somedata
-# CHECK-NEXT:     404       79        4 .bss
-# CHECK-NEXT:     404        0        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.bss.somezeroes)
-# CHECK-NEXT:     404        0        4                 somezeroes
-# CHECK-NEXT:       -       86       12 CUSTOM(.debug_info)
-# CHECK-NEXT:       -       98       50 CUSTOM(name)
+# CHECK-NEXT:       -       4c        9 ELEM
+# CHECK-NEXT:       -       55       2d CODE
+# CHECK-NEXT:       -       56       10         {{.*}}{{/|\\}}map-file.s.tmp1.o:(bar)
+# CHECK-NEXT:       -       56       10                 bar
+# CHECK-NEXT:       -       66        b         {{.*}}{{/|\\}}map-file.s.tmp1.o:(write_global)
+# CHECK-NEXT:       -       66        b                 write_global
+# CHECK-NEXT:       -       71        f         {{.*}}{{/|\\}}map-file.s.tmp1.o:(_start)
+# CHECK-NEXT:       -       71        f                 _start
+# CHECK-NEXT:       -       82       11 DATA
+# CHECK-NEXT:     400       83        8 .data
+# CHECK-NEXT:     400       89        8         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
+# CHECK-NEXT:     400       89        8                 somedata
+# CHECK-NEXT:     408       82        4 .bss
+# CHECK-NEXT:     408        0        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.bss.somezeroes)
+# CHECK-NEXT:     408        0        4                 somezeroes
+# CHECK-NEXT:       -       93       12 CUSTOM(.debug_info)
+# CHECK-NEXT:       -       a5       50 CUSTOM(name)
 
 # RUN: not wasm-ld %t1.o -o /dev/null -Map=/ 2>&1 \
 # RUN:  | FileCheck -check-prefix=FAIL %s

diff  --git a/llvm/include/llvm/MC/MCWasmObjectWriter.h b/llvm/include/llvm/MC/MCWasmObjectWriter.h
index 4c75ea1557943..3d5b09407507a 100644
--- a/llvm/include/llvm/MC/MCWasmObjectWriter.h
+++ b/llvm/include/llvm/MC/MCWasmObjectWriter.h
@@ -15,6 +15,7 @@
 namespace llvm {
 
 class MCFixup;
+class MCSectionWasm;
 class MCValue;
 class raw_pwrite_stream;
 
@@ -34,6 +35,7 @@ class MCWasmObjectTargetWriter : public MCObjectTargetWriter {
   }
 
   virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
+                                const MCSectionWasm &FixupSection,
                                 bool IsLocRel) const = 0;
 
   /// \name Accessors

diff  --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index b86604d54f443..0dc5c9111db2c 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -498,14 +498,21 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
   // be negative and don't wrap.
   FixedValue = 0;
 
-  unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup, IsLocRel);
+  unsigned Type =
+      TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel);
 
   // Absolute offset within a section or a function.
   // Currently only supported for for metadata sections.
   // See: test/MC/WebAssembly/blockaddress.ll
-  if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
-      Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
-      Type == wasm::R_WASM_SECTION_OFFSET_I32) {
+  if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
+       Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
+       Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
+      SymA->isDefined()) {
+    // SymA can be a temp data symbol that represents a function (in which case
+    // it needs to be replaced by the section symbol), [XXX and it apparently
+    // later gets changed again to a func symbol?] or it can be a real
+    // function symbol, in which case it can be left as-is.
+
     if (!FixupSection.getKind().isMetadata())
       report_fatal_error("relocations for function or section offsets are "
                          "only supported in metadata sections");
@@ -620,6 +627,8 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
   case wasm::R_WASM_FUNCTION_OFFSET_I32:
   case wasm::R_WASM_FUNCTION_OFFSET_I64:
   case wasm::R_WASM_SECTION_OFFSET_I32: {
+    if (!RelEntry.Symbol->isDefined())
+      return 0;
     const auto &Section =
         static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
     return Section.getSectionOffset() + RelEntry.Addend;

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
index 48e86544149fa..f67fab9467467 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -35,6 +35,7 @@ class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
 
 private:
   unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
+                        const MCSectionWasm &FixupSection,
                         bool IsLocRel) const override;
 };
 } // end anonymous namespace
@@ -43,7 +44,7 @@ WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit,
                                                          bool IsEmscripten)
     : MCWasmObjectTargetWriter(Is64Bit, IsEmscripten) {}
 
-static const MCSection *getFixupSection(const MCExpr *Expr) {
+static const MCSection *getTargetSection(const MCExpr *Expr) {
   if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) {
     if (SyExp->getSymbol().isInSection())
       return &SyExp->getSymbol().getSection();
@@ -51,20 +52,20 @@ static const MCSection *getFixupSection(const MCExpr *Expr) {
   }
 
   if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {
-    auto SectionLHS = getFixupSection(BinOp->getLHS());
-    auto SectionRHS = getFixupSection(BinOp->getRHS());
+    auto SectionLHS = getTargetSection(BinOp->getLHS());
+    auto SectionRHS = getTargetSection(BinOp->getRHS());
     return SectionLHS == SectionRHS ? nullptr : SectionLHS;
   }
 
   if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
-    return getFixupSection(UnOp->getSubExpr());
+    return getTargetSection(UnOp->getSubExpr());
 
   return nullptr;
 }
 
-unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
-                                                   const MCFixup &Fixup,
-                                                   bool IsLocRel) const {
+unsigned WebAssemblyWasmObjectWriter::getRelocType(
+    const MCValue &Target, const MCFixup &Fixup,
+    const MCSectionWasm &FixupSection, bool IsLocRel) const {
   const MCSymbolRefExpr *RefA = Target.getSymA();
   assert(RefA);
   auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
@@ -114,12 +115,16 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
     assert(SymA.isData());
     return wasm::R_WASM_MEMORY_ADDR_LEB64;
   case FK_Data_4:
-    if (SymA.isFunction())
+    if (SymA.isFunction()) {
+      if (FixupSection.getKind().isMetadata())
+        return wasm::R_WASM_FUNCTION_OFFSET_I32;
+      assert(FixupSection.isWasmData());
       return wasm::R_WASM_TABLE_INDEX_I32;
+    }
     if (SymA.isGlobal())
       return wasm::R_WASM_GLOBAL_INDEX_I32;
     if (auto Section = static_cast<const MCSectionWasm *>(
-            getFixupSection(Fixup.getValue()))) {
+            getTargetSection(Fixup.getValue()))) {
       if (Section->getKind().isText())
         return wasm::R_WASM_FUNCTION_OFFSET_I32;
       else if (!Section->isWasmData())
@@ -128,12 +133,15 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
     return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
                     : wasm::R_WASM_MEMORY_ADDR_I32;
   case FK_Data_8:
-    if (SymA.isFunction())
+    if (SymA.isFunction()) {
+      if (FixupSection.getKind().isMetadata())
+        return wasm::R_WASM_FUNCTION_OFFSET_I64;
       return wasm::R_WASM_TABLE_INDEX_I64;
+    }
     if (SymA.isGlobal())
       llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64");
     if (auto Section = static_cast<const MCSectionWasm *>(
-            getFixupSection(Fixup.getValue()))) {
+            getTargetSection(Fixup.getValue()))) {
       if (Section->getKind().isText())
         return wasm::R_WASM_FUNCTION_OFFSET_I64;
       else if (!Section->isWasmData())

diff  --git a/llvm/test/MC/WebAssembly/debug-template-param.ll b/llvm/test/MC/WebAssembly/debug-template-param.ll
new file mode 100644
index 0000000000000..6f17f1c06a772
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/debug-template-param.ll
@@ -0,0 +1,67 @@
+; RUN: llc -filetype=obj %s -o - | llvm-readobj -r  - | FileCheck %s
+
+; Test for PR50408. Compiled from:
+; char a();
+; template <typename, char b()>
+; void f() { b(); }
+; void g() { f<char, a>(); }
+
+; CHECK: Section (10) .debug_addr
+; CHECK-NEXT:    0x8 R_WASM_FUNCTION_OFFSET_I32 _Z1gv 0
+; CHECK-NEXT:   0xC R_WASM_FUNCTION_OFFSET_I32 _Z1fIcXadL_Z1avEEEvv 0
+; ensure that the reloc type is correct for _Z1av which is undefined
+; CHECK-NEXT:    0x10 R_WASM_FUNCTION_OFFSET_I32 _Z1av 0
+; CHECK-NEXT:  }
+
+; ModuleID = 'PR50408.cc'
+source_filename = "PR50408.cc"
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1"
+target triple = "wasm32-unknown-emscripten"
+
+$_Z1fIcXadL_Z1avEEEvv = comdat any
+
+; Function Attrs: noinline optnone mustprogress
+define hidden void @_Z1gv() #0 !dbg !7 {
+entry:
+  call void @_Z1fIcXadL_Z1avEEEvv(), !dbg !10
+  ret void, !dbg !11
+}
+
+; Function Attrs: noinline optnone mustprogress
+define linkonce_odr hidden void @_Z1fIcXadL_Z1avEEEvv() #0 comdat !dbg !12 {
+entry:
+  %call = call signext i8 @_Z1av(), !dbg !20
+  ret void, !dbg !21
+}
+
+declare signext i8 @_Z1av() #1
+
+attributes #0 = { noinline optnone mustprogress "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" }
+attributes #1 = { "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 5027637fa1d409e3ca78dab60dc2e2db6c62c175)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "PR50408.cc", directory: "/s/emr/emscripten-releases/localtests", checksumkind: CSK_MD5, checksum: "285a5682ae46dbbe90ccfb84cdef66c7")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 5}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 5027637fa1d409e3ca78dab60dc2e2db6c62c175)"}
+!7 = distinct !DISubprogram(name: "g", linkageName: "_Z1gv", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}
+!10 = !DILocation(line: 5, column: 12, scope: !7)
+!11 = !DILocation(line: 5, column: 26, scope: !7)
+!12 = distinct !DISubprogram(name: "f<char, &a>", linkageName: "_Z1fIcXadL_Z1avEEEvv", scope: !1, file: !1, line: 4, type: !8, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, templateParams: !13, retainedNodes: !2)
+!13 = !{!14, !16}
+!14 = !DITemplateTypeParameter(type: !15)
+!15 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!16 = !DITemplateValueParameter(name: "b", type: !17, value: i8 ()* @_Z1av)
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 32)
+!18 = !DISubroutineType(types: !19)
+!19 = !{!15}
+!20 = !DILocation(line: 4, column: 12, scope: !12)
+!21 = !DILocation(line: 4, column: 17, scope: !12)

diff  --git a/llvm/test/MC/WebAssembly/debuginfo-relocs.s b/llvm/test/MC/WebAssembly/debuginfo-relocs.s
new file mode 100644
index 0000000000000..e0343c9877fd5
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/debuginfo-relocs.s
@@ -0,0 +1,43 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: obj2yaml %t.o | FileCheck %s
+
+.functype undef () -> ()
+
+bar:
+    .functype bar () -> ()
+    end_function
+
+    .globl _start
+_start:
+    .functype _start () -> ()
+    call bar
+    end_function
+
+.section .debug_int,"",@
+.Ld:
+  .int32 1
+.size .Ld, 4
+
+.section .debug_info,"",@
+    .int32 bar
+    .int32 undef
+    .int32 .Ld
+
+## Test that relocations in metadata sections against both defined and undef
+## function symbols get R_WASM_FUNCTION_OFFSET relocations, and relocs against
+## data symbols get R_WASM_SECTION_OFFSET relocs.
+# CHECK:     - Type: CUSTOM
+# CHECK-NEXT:  Name: .debug_int
+# CHECK:     - Type: CUSTOM
+# CHECK-NEXT:    Relocations:
+# CHECK-NEXT:      - Type:            R_WASM_FUNCTION_OFFSET_I32
+# CHECK-NEXT:        Index:           0
+# CHECK-NEXT:        Offset:          0x0
+# CHECK-NEXT:      - Type:            R_WASM_FUNCTION_OFFSET_I32
+# CHECK-NEXT:        Index:           3
+# CHECK-NEXT:        Offset:          0x4
+# CHECK-NEXT:      - Type:            R_WASM_SECTION_OFFSET_I32
+# CHECK-NEXT:        Index:           2
+# CHECK-NEXT:        Offset:          0x8
+# CHECK-NEXT:         Name:            .debug_info
+


        


More information about the llvm-commits mailing list