Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lld/test/ELF/aarch64-reloc-gotpcrel32.s
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ _start: // PC = 0x303a0
// bar@GOTPCREL-4 = 0x20390 (got entry for `bar`) - 0x303a8 (.) - 4 = 0xe4fffeff
// CHECK: Contents of section .data:
// CHECK-NEXT: {{.*}} f0fffeff f0fffeff e4fffeff
.word bar@GOTPCREL
.word bar@GOTPCREL+4
.word bar@GOTPCREL-4
.word %gotpcrel(bar)
.word %gotpcrel(bar+4)
.word %gotpcrel(bar-4)

// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
.word baz@GOTPCREL+0xffffffff
.word baz@GOTPCREL-0xffffffff
.word %gotpcrel(baz+0xffffffff)
.word %gotpcrel(baz-0xffffffff)
6 changes: 3 additions & 3 deletions lld/test/ELF/aarch64-reloc-plt32.s
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
.globl _start
_start:
.data
.word foo@PLT - . + 2149589079
.word foo@PLT - . - 2145378212
.word foo@PLT - .
.word %pltpcrel(foo + 2149589079)
.word %pltpcrel(foo - 2145378212)
.word %pltpcrel(foo)
24 changes: 24 additions & 0 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
OperandVector &Operands);

bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
bool parseDataExpr(const MCExpr *&Res) override;
bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);

Expand Down Expand Up @@ -8190,8 +8191,31 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
return false;
}

bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
SMLoc Loc = getLoc();
if (getLexer().getKind() != AsmToken::Identifier)
return TokError("expected '%' relocation specifier");
StringRef Identifier = getParser().getTok().getIdentifier();
auto Spec = AArch64::parsePercentSpecifierName(Identifier);
if (!Spec)
return TokError("invalid relocation specifier");

getParser().Lex(); // Eat the identifier
if (parseToken(AsmToken::LParen, "expected '('"))
return true;

const MCExpr *SubExpr;
if (getParser().parseParenExpression(SubExpr, E))
return true;

Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc);
return false;
}

bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
SMLoc EndLoc;
if (parseOptionalToken(AsmToken::Percent))
return parseExprWithSpecifier(Res, EndLoc);

if (getParser().parseExpression(Res))
return true;
Expand Down
25 changes: 20 additions & 5 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
break;
}

switch (RefKind) {
case AArch64::S_GOTPCREL:
case AArch64::S_PLT:
if (Kind == FK_Data_4)
break;
reportError(Fixup.getLoc(), AArch64::getSpecifierName(RefKind) +
" can only be used in a .word directive");
return ELF::R_RISCV_NONE;
default:
break;
}

// Extract the relocation type from the fixup kind, after applying STT_TLS as
// needed.
if (mc::isRelocation(Fixup.getKind()))
Expand All @@ -117,8 +129,7 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
case FK_Data_2:
return R_CLS(PREL16);
case FK_Data_4: {
return Target.getSpecifier() == AArch64::S_PLT ? R_CLS(PLT32)
: R_CLS(PREL32);
return R_CLS(PREL32);
}
case FK_Data_8:
if (IsILP32) {
Expand Down Expand Up @@ -220,9 +231,13 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
case FK_Data_2:
return R_CLS(ABS16);
case FK_Data_4:
return (!IsILP32 && Target.getSpecifier() == AArch64::S_GOTPCREL)
? ELF::R_AARCH64_GOTPCREL32
: R_CLS(ABS32);
if (!IsILP32) {
if (Target.getSpecifier() == AArch64::S_GOTPCREL)
return ELF::R_AARCH64_GOTPCREL32;
if (Target.getSpecifier() == AArch64::S_PLT)
return ELF::R_AARCH64_PLT32;
}
return R_CLS(ABS32);
case FK_Data_8: {
if (IsILP32) {
reportError(
Expand Down
17 changes: 16 additions & 1 deletion llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,22 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) {
case AArch64::S_GOT_AUTH: return ":got_auth:";
case AArch64::S_GOT_AUTH_PAGE: return ":got_auth:";
case AArch64::S_GOT_AUTH_LO12: return ":got_auth_lo12:";

case AArch64::S_GOTPCREL: return "%gotpcrel";
case AArch64::S_PLT: return "%pltpcrel";
default:
llvm_unreachable("Invalid relocation specifier");
}
// clang-format on
}

AArch64::Specifier AArch64::parsePercentSpecifierName(StringRef name) {
return StringSwitch<AArch64::Specifier>(name)
.Case("pltpcrel", AArch64::S_PLT)
.Case("gotpcrel", AArch64::S_GOTPCREL)
.Default(0);
}

static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res,
const MCAssembler *Asm) {
if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm))
Expand Down Expand Up @@ -232,8 +242,13 @@ void AArch64MCAsmInfoELF::printSpecifierExpr(
raw_ostream &OS, const MCSpecifierExpr &Expr) const {
if (auto *AE = dyn_cast<AArch64AuthMCExpr>(&Expr))
return AE->print(OS, this);
OS << AArch64::getSpecifierName(Expr.getSpecifier());
auto Str = AArch64::getSpecifierName(Expr.getSpecifier());
OS << Str;
if (!Str.empty() && Str[0] == '%')
OS << ')';
printExpr(OS, *Expr.getSubExpr());
if (!Str.empty() && Str[0] == '%')
OS << ')';
}

bool AArch64MCAsmInfoELF::evaluateAsRelocatableImpl(
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ enum {
/// (e.g. ":got:", ":lo12:").
StringRef getSpecifierName(Specifier S);

Specifier parsePercentSpecifierName(StringRef);

inline Specifier getSymbolLoc(Specifier S) {
return static_cast<Specifier>(S & AArch64::S_SymLocBits);
}
Expand Down
62 changes: 33 additions & 29 deletions llvm/test/MC/AArch64/data-directive-specifier.s
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
# RUN: llvm-mc -triple=aarch64 -filetype=obj %s | llvm-readobj -r - | FileCheck %s
# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym OBJERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJERR --implicit-check-not=error:
# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR0=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR0 --implicit-check-not=error:
# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:

.globl g
g:
l:

# CHECK: Section ({{.*}}) .rela.data {
# CHECK-NEXT: 0x0 R_AARCH64_PLT32 l 0x0
# CHECK-NEXT: 0x4 R_AARCH64_PLT32 l 0x4
# CHECK-NEXT: 0x8 R_AARCH64_PLT32 extern 0x4
# CHECK-NEXT: 0xC R_AARCH64_PLT32 g 0x8
# CHECK-NEXT: 0x10 R_AARCH64_PLT32 g 0x18
# CHECK-NEXT: 0x4 R_AARCH64_PLT32 extern 0x4
# CHECK-NEXT: 0x8 R_AARCH64_PLT32 g 0x8
# CHECK-NEXT: }
.data
.word l@plt - .
.word l@plt - .data

.word extern@plt - . + 4
.word g@plt - . + 8
.word g@plt - .data + 8
.word %pltpcrel(l)
.word %pltpcrel(extern + 4), %pltpcrel(g + 8)

# CHECK: Section ({{.*}}) .rela.data1 {
# CHECK-NEXT: 0x0 R_AARCH64_GOTPCREL32 data1 0x0
# CHECK-NEXT: 0x4 R_AARCH64_GOTPCREL32 extern 0x4
# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB
# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB
# CHECK-NEXT: }
.section .data1,"aw"
data1:
.word data1@GOTPCREL
.word extern@gotpcrel+4
.word extern@GOTPCREL-5
.word %gotpcrel(data1)
.word %gotpcrel(extern+4), %gotpcrel(extern-5)

## Test parse-time errors
.ifdef ERR
# ERR: [[#@LINE+1]]:9: error: @ specifier only allowed after a symbol
.quad 3@plt - .
.ifdef ERR0
# ERR0: [[#@LINE+1]]:8: error: invalid relocation specifier
.word %xxx(l)

# ERR0: [[#@LINE+1]]:17: error: expected '('
.word %pltpcrel l

# ERR: [[#@LINE+1]]:9: error: expected ')'
.quad (l@plt - .)
# ERR0: [[#@LINE+2]]:14: error: unknown token in expression
# ERR0: [[#@LINE+1]]:14: error: invalid operand
ldr w0, [x1, %pltpcrel(g)]
.endif

.ifdef OBJERR
.quad g@plt - .
.ifdef ERR
# ERR: [[#@LINE+1]]:8: error: %pltpcrel can only be used in a .word directive
.quad %pltpcrel(g)

# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
.word %pltpcrel(g-.)

# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
.word %pltpcrel(extern - und)

.word extern@gotpcrel - .
# ERR: [[#@LINE+1]]:8: error: %gotpcrel can only be used in a .word directive
.quad %gotpcrel(g)

# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
.word extern@plt - und
# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
.word %gotpcrel(extern - .)

# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
.word extern@gotpcrel - und
# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
.word %gotpcrel(extern - und)
.endif
Loading