mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[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
This commit is contained in:
parent
846c3e0e7d
commit
0c7127a873
@ -15,6 +15,7 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class MCFixup;
|
class MCFixup;
|
||||||
|
class MCSectionWasm;
|
||||||
class MCValue;
|
class MCValue;
|
||||||
class raw_pwrite_stream;
|
class raw_pwrite_stream;
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
|
virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||||
|
const MCSectionWasm &FixupSection,
|
||||||
bool IsLocRel) const = 0;
|
bool IsLocRel) const = 0;
|
||||||
|
|
||||||
/// \name Accessors
|
/// \name Accessors
|
||||||
|
@ -498,14 +498,21 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
|
|||||||
// be negative and don't wrap.
|
// be negative and don't wrap.
|
||||||
FixedValue = 0;
|
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.
|
// Absolute offset within a section or a function.
|
||||||
// Currently only supported for for metadata sections.
|
// Currently only supported for for metadata sections.
|
||||||
// See: test/MC/WebAssembly/blockaddress.ll
|
// See: test/MC/WebAssembly/blockaddress.ll
|
||||||
if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
|
if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
|
||||||
Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
|
Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
|
||||||
Type == wasm::R_WASM_SECTION_OFFSET_I32) {
|
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())
|
if (!FixupSection.getKind().isMetadata())
|
||||||
report_fatal_error("relocations for function or section offsets are "
|
report_fatal_error("relocations for function or section offsets are "
|
||||||
"only supported in metadata sections");
|
"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_I32:
|
||||||
case wasm::R_WASM_FUNCTION_OFFSET_I64:
|
case wasm::R_WASM_FUNCTION_OFFSET_I64:
|
||||||
case wasm::R_WASM_SECTION_OFFSET_I32: {
|
case wasm::R_WASM_SECTION_OFFSET_I32: {
|
||||||
|
if (!RelEntry.Symbol->isDefined())
|
||||||
|
return 0;
|
||||||
const auto &Section =
|
const auto &Section =
|
||||||
static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
|
static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
|
||||||
return Section.getSectionOffset() + RelEntry.Addend;
|
return Section.getSectionOffset() + RelEntry.Addend;
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
|
unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||||
|
const MCSectionWasm &FixupSection,
|
||||||
bool IsLocRel) const override;
|
bool IsLocRel) const override;
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@ -43,7 +44,7 @@ WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit,
|
|||||||
bool IsEmscripten)
|
bool IsEmscripten)
|
||||||
: MCWasmObjectTargetWriter(Is64Bit, 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 (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) {
|
||||||
if (SyExp->getSymbol().isInSection())
|
if (SyExp->getSymbol().isInSection())
|
||||||
return &SyExp->getSymbol().getSection();
|
return &SyExp->getSymbol().getSection();
|
||||||
@ -51,20 +52,20 @@ static const MCSection *getFixupSection(const MCExpr *Expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {
|
if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {
|
||||||
auto SectionLHS = getFixupSection(BinOp->getLHS());
|
auto SectionLHS = getTargetSection(BinOp->getLHS());
|
||||||
auto SectionRHS = getFixupSection(BinOp->getRHS());
|
auto SectionRHS = getTargetSection(BinOp->getRHS());
|
||||||
return SectionLHS == SectionRHS ? nullptr : SectionLHS;
|
return SectionLHS == SectionRHS ? nullptr : SectionLHS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
|
if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
|
||||||
return getFixupSection(UnOp->getSubExpr());
|
return getTargetSection(UnOp->getSubExpr());
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
unsigned WebAssemblyWasmObjectWriter::getRelocType(
|
||||||
const MCFixup &Fixup,
|
const MCValue &Target, const MCFixup &Fixup,
|
||||||
bool IsLocRel) const {
|
const MCSectionWasm &FixupSection, bool IsLocRel) const {
|
||||||
const MCSymbolRefExpr *RefA = Target.getSymA();
|
const MCSymbolRefExpr *RefA = Target.getSymA();
|
||||||
assert(RefA);
|
assert(RefA);
|
||||||
auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
|
auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
|
||||||
@ -114,12 +115,16 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
|||||||
assert(SymA.isData());
|
assert(SymA.isData());
|
||||||
return wasm::R_WASM_MEMORY_ADDR_LEB64;
|
return wasm::R_WASM_MEMORY_ADDR_LEB64;
|
||||||
case FK_Data_4:
|
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;
|
return wasm::R_WASM_TABLE_INDEX_I32;
|
||||||
|
}
|
||||||
if (SymA.isGlobal())
|
if (SymA.isGlobal())
|
||||||
return wasm::R_WASM_GLOBAL_INDEX_I32;
|
return wasm::R_WASM_GLOBAL_INDEX_I32;
|
||||||
if (auto Section = static_cast<const MCSectionWasm *>(
|
if (auto Section = static_cast<const MCSectionWasm *>(
|
||||||
getFixupSection(Fixup.getValue()))) {
|
getTargetSection(Fixup.getValue()))) {
|
||||||
if (Section->getKind().isText())
|
if (Section->getKind().isText())
|
||||||
return wasm::R_WASM_FUNCTION_OFFSET_I32;
|
return wasm::R_WASM_FUNCTION_OFFSET_I32;
|
||||||
else if (!Section->isWasmData())
|
else if (!Section->isWasmData())
|
||||||
@ -128,12 +133,15 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
|||||||
return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
|
return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
|
||||||
: wasm::R_WASM_MEMORY_ADDR_I32;
|
: wasm::R_WASM_MEMORY_ADDR_I32;
|
||||||
case FK_Data_8:
|
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;
|
return wasm::R_WASM_TABLE_INDEX_I64;
|
||||||
|
}
|
||||||
if (SymA.isGlobal())
|
if (SymA.isGlobal())
|
||||||
llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64");
|
llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64");
|
||||||
if (auto Section = static_cast<const MCSectionWasm *>(
|
if (auto Section = static_cast<const MCSectionWasm *>(
|
||||||
getFixupSection(Fixup.getValue()))) {
|
getTargetSection(Fixup.getValue()))) {
|
||||||
if (Section->getKind().isText())
|
if (Section->getKind().isText())
|
||||||
return wasm::R_WASM_FUNCTION_OFFSET_I64;
|
return wasm::R_WASM_FUNCTION_OFFSET_I64;
|
||||||
else if (!Section->isWasmData())
|
else if (!Section->isWasmData())
|
||||||
|
67
test/MC/WebAssembly/debug-template-param.ll
Normal file
67
test/MC/WebAssembly/debug-template-param.ll
Normal file
@ -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)
|
43
test/MC/WebAssembly/debuginfo-relocs.s
Normal file
43
test/MC/WebAssembly/debuginfo-relocs.s
Normal file
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user