1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[WebAssembly] Add new relocation for location relative data

This `R_WASM_MEMORY_ADDR_SELFREL_I32` relocation represents an offset
between its relocating address and the symbol address. It's very similar
to `R_X86_64_PC32` but restricted to be used for only data segments.

```
S + A - P
```

A: Represents the addend used to compute the value of the relocatable
field.
P: Represents the place of the storage unit being relocated.
S: Represents the value of the symbol whose index resides in the
relocation entry.

Proposal: https://github.com/WebAssembly/tool-conventions/issues/162

Differential Revision: https://reviews.llvm.org/D96659
This commit is contained in:
Yuta Saito 2021-03-08 11:23:33 -08:00 committed by Sam Clegg
parent a7e3a0cf49
commit 9526edaf68
9 changed files with 111 additions and 19 deletions

View File

@ -25,3 +25,4 @@ WASM_RELOC(R_WASM_TABLE_INDEX_I64, 19)
WASM_RELOC(R_WASM_TABLE_NUMBER_LEB, 20)
WASM_RELOC(R_WASM_MEMORY_ADDR_TLS_SLEB, 21)
WASM_RELOC(R_WASM_FUNCTION_OFFSET_I64, 22)
WASM_RELOC(R_WASM_MEMORY_ADDR_LOCREL_I32, 23)

View File

@ -33,8 +33,8 @@ public:
return W->getFormat() == Triple::Wasm;
}
virtual unsigned getRelocType(const MCValue &Target,
const MCFixup &Fixup) const = 0;
virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsLocRel) const = 0;
/// \name Accessors
/// @{

View File

@ -52,6 +52,7 @@ bool llvm::wasm::relocTypeHasAddend(uint32_t Type) {
case R_WASM_FUNCTION_OFFSET_I32:
case R_WASM_FUNCTION_OFFSET_I64:
case R_WASM_SECTION_OFFSET_I32:
case R_WASM_MEMORY_ADDR_LOCREL_I32:
return true;
default:
return false;

View File

@ -445,17 +445,35 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
MCContext &Ctx = Asm.getContext();
bool IsLocRel = false;
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
// To get here the A - B expression must have failed evaluateAsRelocatable.
// This means either A or B must be undefined and in WebAssembly we can't
// support either of those cases.
const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
Ctx.reportError(
Fixup.getLoc(),
Twine("symbol '") + SymB.getName() +
"': unsupported subtraction expression used in relocation.");
return;
if (FixupSection.getKind().isText()) {
Ctx.reportError(Fixup.getLoc(),
Twine("symbol '") + SymB.getName() +
"' unsupported subtraction expression used in "
"relocation in code section.");
return;
}
if (SymB.isUndefined()) {
Ctx.reportError(Fixup.getLoc(),
Twine("symbol '") + SymB.getName() +
"' can not be undefined in a subtraction expression");
return;
}
const MCSection &SecB = SymB.getSection();
if (&SecB != &FixupSection) {
Ctx.reportError(Fixup.getLoc(),
Twine("symbol '") + SymB.getName() +
"' can not be placed in a different section");
return;
}
IsLocRel = true;
C += FixupOffset - Layout.getSymbolOffset(SymB);
}
// We either rejected the fixup or folded B into C at this point.
@ -480,7 +498,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
// be negative and don't wrap.
FixedValue = 0;
unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup, IsLocRel);
// Absolute offset within a section or a function.
// Currently only supported for for metadata sections.
@ -611,7 +629,8 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
case wasm::R_WASM_MEMORY_ADDR_I32:
case wasm::R_WASM_MEMORY_ADDR_I64:
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: {
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
// Provisional value is address of the global plus the offset
// For undefined symbols, use zero
if (!RelEntry.Symbol->isDefined())
@ -707,6 +726,7 @@ void WasmObjectWriter::applyRelocations(
case wasm::R_WASM_FUNCTION_OFFSET_I32:
case wasm::R_WASM_SECTION_OFFSET_I32:
case wasm::R_WASM_GLOBAL_INDEX_I32:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
patchI32(Stream, Value, Offset);
break;
case wasm::R_WASM_TABLE_INDEX_I64:

View File

@ -575,6 +575,7 @@ static bool supportsWasm32(uint64_t Type) {
case wasm::R_WASM_EVENT_INDEX_LEB:
case wasm::R_WASM_GLOBAL_INDEX_I32:
case wasm::R_WASM_TABLE_NUMBER_LEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
return true;
default:
return false;
@ -611,6 +612,7 @@ static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
case wasm::R_WASM_EVENT_INDEX_LEB:
case wasm::R_WASM_GLOBAL_INDEX_I32:
case wasm::R_WASM_TABLE_NUMBER_LEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
// For wasm section, its offset at 0 -- ignoring Value
return LocData;
default:

View File

@ -905,6 +905,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_I32:
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
if (!isValidDataSymbol(Reloc.Index))
return make_error<GenericBinaryError>("invalid relocation data index",
object_error::parse_failed);
@ -953,6 +954,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
Size = 10;
if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)

View File

@ -34,8 +34,8 @@ public:
explicit WebAssemblyWasmObjectWriter(bool Is64Bit, bool IsEmscripten);
private:
unsigned getRelocType(const MCValue &Target,
const MCFixup &Fixup) const override;
unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsLocRel) const override;
};
} // end anonymous namespace
@ -63,7 +63,8 @@ static const MCSection *getFixupSection(const MCExpr *Expr) {
}
unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
const MCFixup &Fixup) const {
const MCFixup &Fixup,
bool IsLocRel) const {
const MCSymbolRefExpr *RefA = Target.getSymA();
assert(RefA);
auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol());
@ -122,7 +123,8 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
else if (!Section->isWasmData())
return wasm::R_WASM_SECTION_OFFSET_I32;
}
return wasm::R_WASM_MEMORY_ADDR_I32;
return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32
: wasm::R_WASM_MEMORY_ADDR_I32;
case FK_Data_8:
if (SymA.isFunction())
return wasm::R_WASM_TABLE_INDEX_I64;

View File

@ -13,6 +13,22 @@ bar:
.int8 1
.size bar, 1
.section .data.fizz,"",@
fizz:
.int8 1
.size fizz, 1
.section .data.segment1,"",@
segment1:
// CHECK: 'bar' can not be placed in a different section
.int32 fizz-bar
// CHECK: 'undef_baz' can not be undefined in a subtraction expression
.int32 fizz-undef_baz
// CHECK: 'fizz' can not be placed in a different section
.int32 undef_baz-fizz
.size segment1, 12
.text
.section .text.main,"",@
main:
@ -23,10 +39,10 @@ main:
i32.const foo-foo_other+2
i32.const foo_other-foo-10
// CHECK: 'bar': unsupported subtraction expression used in relocation
// CHECK: 'bar' unsupported subtraction expression used in relocation in code section.
i32.const foo-bar
// CHECK: 'undef_baz': unsupported subtraction expression used in relocation
// CHECK: 'undef_baz' unsupported subtraction expression used in relocation in code section.
i32.const foo-undef_baz
// CHECK: 'foo': unsupported subtraction expression used in relocation
// CHECK: 'foo' unsupported subtraction expression used in relocation in code section.
i32.const undef_baz-foo
end_function

View File

@ -0,0 +1,48 @@
; RUN: llc -O0 -filetype=obj %s -o - | llvm-readobj -r --expand-relocs - | FileCheck %s
; CHECK: Format: WASM
; CHECK: Relocations [
; CHECK-NEXT: Section (3) DATA {
; CHECK-NEXT: Relocation {
; CHECK-NEXT: Type: R_WASM_MEMORY_ADDR_LOCREL_I32 (23)
; CHECK-NEXT: Offset: 0x6
; CHECK-NEXT: Symbol: foo
; CHECK-NEXT: Addend: 0
; CHECK-NEXT: }
; CHECK-NEXT: Relocation {
; CHECK-NEXT: Type: R_WASM_MEMORY_ADDR_LOCREL_I32 (23)
; CHECK-NEXT: Offset: 0xA
; CHECK-NEXT: Symbol: fizz
; CHECK-NEXT: Addend: 0
; CHECK-NEXT: }
; CHECK-NEXT: Relocation {
; CHECK-NEXT: Type: R_WASM_MEMORY_ADDR_LOCREL_I32 (23)
; CHECK-NEXT: Offset: 0x17
; CHECK-NEXT: Symbol: foo
; CHECK-NEXT: Addend: 4
; CHECK-NEXT: }
; CHECK-NEXT: }
; CHECK-NEXT: ]
target triple = "wasm32-unknown-unknown"
; @foo - @bar
@foo = external global i32, align 4
@bar = constant i32 sub (
i32 ptrtoint (i32* @foo to i32),
i32 ptrtoint (i32* @bar to i32)
), section ".sec1"
; @foo - @addend + 4
@fizz = constant i32 42, align 4, section ".sec2"
@addend = constant i32 sub (
i32 ptrtoint (i32* @foo to i32),
i32 ptrtoint (i32* @fizz to i32)
), section ".sec2"
@x_sec = constant i32 sub (
i32 ptrtoint (i32* @fizz to i32),
i32 ptrtoint (i32* @x_sec to i32)
), section ".sec1"