[llvm] 56ad9e9 - [AArch64][ELF] Support R_AARCH64_AUTH_ABS64 static relocation

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 24 08:59:42 PDT 2023


Author: Daniil Kovalev
Date: 2023-08-24T18:58:06+03:00
New Revision: 56ad9e9171a4845ba18a7375321156c547bf5906

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

LOG: [AArch64][ELF] Support R_AARCH64_AUTH_ABS64 static relocation

The patch adds parser, MCExpr, and emitter support for the authenticated
pointer auth relocation.

In assembly, this is expressed using:
  .quad <symbol>@AUTH(<key>, <discriminator> [, addr])
For example:
  .quad _g3 at AUTH(ib, 1234, addr)

The optional 'addr' specifier represents whether the generated pointer
authentication code will also include address diversity (by blending the
address of the storage location of the relocated pointer with the
user-specified constant discriminator).

The @AUTH expression lowers to R_AARCH64_AUTH_ABS64 ELF relocation.

The signing schema is encoded in the place of relocation to be applied
as follows:

```
| 63                | 62 | 61:60 | 59:48 |  47:32        | 31:0   |
| ----------------- | -- | ----- | ----- | ------------- | ------ |
| address diversity | 0  | key   | 0     | discriminator | addend |
```

See the following for details:
https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#static-relocations

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

Co-authored-by: Ahmed Bougacha <ahmed at bougacha.org>
Co-authored-by: Peter Collingbourne <peter at pcc.me.uk>

Added: 
    llvm/test/MC/AArch64/elf-reloc-ptrauth.s

Modified: 
    llvm/docs/PointerAuth.md
    llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h

Removed: 
    


################################################################################
diff  --git a/llvm/docs/PointerAuth.md b/llvm/docs/PointerAuth.md
index b606e84541481a..de8e3392af48e4 100644
--- a/llvm/docs/PointerAuth.md
+++ b/llvm/docs/PointerAuth.md
@@ -300,3 +300,43 @@ instructions as such:
 * [``llvm.ptrauth.resign``](#llvm-ptrauth-resign): ``AUT*+PAC*``.  These are
   represented as a single pseudo-instruction in the backend to guarantee that
   the intermediate raw pointer value is not spilled and attackable.
+
+#### Assembly Representation
+
+At the assembly level,
+[Authenticated Relocations](#authenticated-global-relocation) are represented
+using the `@AUTH` modifier:
+
+```asm
+    .quad _target at AUTH(<key>,<discriminator>[,addr])
+```
+
+where:
+* `key` is the Armv8.3-A key identifier (`ia`, `ib`, `da`, `db`)
+* `discriminator` is the 16-bit unsigned discriminator value
+* `addr` signifies that the authenticated pointer is address-discriminated
+  (that is, that the relocation's target address is to be blended into the
+  `discriminator` before it is used in the sign operation.
+
+For example:
+```asm
+  _authenticated_reference_to_sym:
+    .quad _sym at AUTH(db,0)
+  _authenticated_reference_to_sym_addr_disc:
+    .quad _sym at AUTH(ia,12,addr)
+```
+
+#### ELF Object File Representation
+
+At the object file level,
+[Authenticated Relocations](#authenticated-global-relocation) are represented
+using the `R_AARCH64_AUTH_ABS64` relocation kind (with value `0xE100`).
+
+The signing schema is encoded in the place of relocation to be applied
+as follows:
+
+```
+| 63                | 62       | 61:60    | 59:48    |  47:32        | 31:0                |
+| ----------------- | -------- | -------- | -------- | ------------- | ------------------- |
+| address diversity | reserved | key      | reserved | discriminator | reserved for addend |
+```

diff  --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
index 96a4efe8256043..b507109b19e1b9 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
@@ -134,6 +134,7 @@ ELF_RELOC(R_AARCH64_TLS_DTPREL64,                    0x405)
 ELF_RELOC(R_AARCH64_TLS_TPREL64,                     0x406)
 ELF_RELOC(R_AARCH64_TLSDESC,                         0x407)
 ELF_RELOC(R_AARCH64_IRELATIVE,                       0x408)
+ELF_RELOC(R_AARCH64_AUTH_ABS64,                      0xe100)
 
 // ELF_RELOC(R_AARCH64_P32_NONE,                         0)
 ELF_RELOC(R_AARCH64_P32_ABS32,                       0x001)

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 5a692215dc2082..392bc200ef30b4 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -738,17 +738,24 @@ static void AttemptToFoldSymbolOffsetDifference(
 /// They might look redundant, but this function can be used before layout
 /// is done (see the object streamer for example) and having the Asm argument
 /// lets us avoid relaxations early.
-static bool
-EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout,
-                    const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS,
-                    const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B,
-                    int64_t RHS_Cst, MCValue &Res) {
+static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
+                                const MCAsmLayout *Layout,
+                                const SectionAddrMap *Addrs, bool InSet,
+                                const MCValue &LHS, const MCValue &RHS,
+                                MCValue &Res) {
   // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
   // about dealing with modifiers. This will ultimately bite us, one day.
   const MCSymbolRefExpr *LHS_A = LHS.getSymA();
   const MCSymbolRefExpr *LHS_B = LHS.getSymB();
   int64_t LHS_Cst = LHS.getConstant();
 
+  const MCSymbolRefExpr *RHS_A = RHS.getSymA();
+  const MCSymbolRefExpr *RHS_B = RHS.getSymB();
+  int64_t RHS_Cst = RHS.getConstant();
+
+  if (LHS.getRefKind() != RHS.getRefKind())
+    return false;
+
   // Fold the result constant immediately.
   int64_t Result_Cst = LHS_Cst + RHS_Cst;
 
@@ -957,14 +964,19 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
       case MCBinaryExpr::Sub:
         // Negate RHS and add.
         // The cast avoids undefined behavior if the constant is INT64_MIN.
-        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
-                                   RHSValue.getSymB(), RHSValue.getSymA(),
-                                   -(uint64_t)RHSValue.getConstant(), Res);
+        return EvaluateSymbolicAdd(
+            Asm, Layout, Addrs, InSet, LHSValue,
+            MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),
+                         -(uint64_t)RHSValue.getConstant(),
+                         RHSValue.getRefKind()),
+            Res);
 
       case MCBinaryExpr::Add:
-        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
-                                   RHSValue.getSymA(), RHSValue.getSymB(),
-                                   RHSValue.getConstant(), Res);
+        return EvaluateSymbolicAdd(
+            Asm, Layout, Addrs, InSet, LHSValue,
+            MCValue::get(RHSValue.getSymA(), RHSValue.getSymB(),
+                         RHSValue.getConstant(), RHSValue.getRefKind()),
+            Res);
       }
     }
 

diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 4756746063d559..d81c2ee30ce8a0 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -180,6 +180,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
   bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
                       OperandVector &Operands);
 
+  bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);
+
   bool parseDirectiveArch(SMLoc L);
   bool parseDirectiveArchExtension(SMLoc L);
   bool parseDirectiveCPU(SMLoc L);
@@ -324,6 +326,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
 
+  bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
+
   static bool classifySymbolRef(const MCExpr *Expr,
                                 AArch64MCExpr::VariantKind &ELFRefKind,
                                 MCSymbolRefExpr::VariantKind &DarwinRefKind,
@@ -7451,6 +7455,112 @@ bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
   return false;
 }
 
+bool AArch64AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+  // Try @AUTH expressions: they're more complex than the usual symbol variants.
+  if (!parseAuthExpr(Res, EndLoc))
+    return false;
+  return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
+}
+
+///  parseAuthExpr
+///  ::= _sym at AUTH(ib,123[,addr])
+///  ::= (_sym + 5)@AUTH(ib,123[,addr])
+///  ::= (_sym - 5)@AUTH(ib,123[,addr])
+bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+  MCAsmParser &Parser = getParser();
+  MCContext &Ctx = getContext();
+
+  AsmToken Tok = Parser.getTok();
+
+  // Look for '_sym at AUTH' ...
+  if (Tok.is(AsmToken::Identifier) && Tok.getIdentifier().endswith("@AUTH")) {
+    StringRef SymName = Tok.getIdentifier().drop_back(strlen("@AUTH"));
+    if (SymName.find('@') != StringRef::npos)
+      return TokError(
+          "combination of @AUTH with other modifiers not supported");
+    Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
+
+    Parser.Lex(); // Eat the identifier.
+  } else {
+    // ... or look for a more complex symbol reference, such as ...
+    SmallVector<AsmToken, 6> Tokens;
+
+    // ... '"_long sym"@AUTH' ...
+    if (Tok.is(AsmToken::String))
+      Tokens.resize(2);
+    // ... or '(_sym + 5)@AUTH'.
+    else if (Tok.is(AsmToken::LParen))
+      Tokens.resize(6);
+    else
+      return true;
+
+    if (Parser.getLexer().peekTokens(Tokens) != Tokens.size())
+      return true;
+
+    // In either case, the expression ends with '@' 'AUTH'.
+    if (Tokens[Tokens.size() - 2].isNot(AsmToken::At) ||
+        Tokens[Tokens.size() - 1].isNot(AsmToken::Identifier) ||
+        Tokens[Tokens.size() - 1].getIdentifier() != "AUTH")
+      return true;
+
+    if (Tok.is(AsmToken::String)) {
+      StringRef SymName;
+      if (Parser.parseIdentifier(SymName))
+        return true;
+      Res = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(SymName), Ctx);
+    } else {
+      if (Parser.parsePrimaryExpr(Res, EndLoc, nullptr))
+        return true;
+    }
+
+    Parser.Lex(); // '@'
+    Parser.Lex(); // 'AUTH'
+  }
+
+  // At this point, we encountered "<id>@AUTH". There is no fallback anymore.
+  if (parseToken(AsmToken::LParen, "expected '('"))
+    return true;
+
+  if (Parser.getTok().isNot(AsmToken::Identifier))
+    return TokError("expected key name");
+
+  StringRef KeyStr = Parser.getTok().getIdentifier();
+  auto KeyIDOrNone = AArch64StringToPACKeyID(KeyStr);
+  if (!KeyIDOrNone)
+    return TokError("invalid key '" + KeyStr + "'");
+  Parser.Lex();
+
+  if (parseToken(AsmToken::Comma, "expected ','"))
+    return true;
+
+  if (Parser.getTok().isNot(AsmToken::Integer))
+    return TokError("expected integer discriminator");
+  int64_t Discriminator = Parser.getTok().getIntVal();
+
+  if (!isUInt<16>(Discriminator))
+    return TokError("integer discriminator " + Twine(Discriminator) +
+                    " out of range [0, 0xFFFF]");
+  Parser.Lex();
+
+  bool UseAddressDiversity = false;
+  if (Parser.getTok().is(AsmToken::Comma)) {
+    Parser.Lex();
+    if (Parser.getTok().isNot(AsmToken::Identifier) ||
+        Parser.getTok().getIdentifier() != "addr")
+      return TokError("expected 'addr'");
+    UseAddressDiversity = true;
+    Parser.Lex();
+  }
+
+  EndLoc = Parser.getTok().getEndLoc();
+  if (parseToken(AsmToken::RParen, "expected ')'"))
+    return true;
+
+  Res = AArch64AuthMCExpr::create(Res, Discriminator, *KeyIDOrNone,
+                                  UseAddressDiversity, Ctx);
+  return false;
+}
+
 bool
 AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
                                     AArch64MCExpr::VariantKind &ELFRefKind,

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index b5d230668a5e9f..be248125d8263f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -400,6 +400,19 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                                    MutableArrayRef<char> Data, uint64_t Value,
                                    bool IsResolved,
                                    const MCSubtargetInfo *STI) const {
+  if (Fixup.getTargetKind() == FK_Data_8 && TheTriple.isOSBinFormatELF()) {
+    auto RefKind = static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
+    AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
+    if (SymLoc == AArch64AuthMCExpr::VK_AUTH ||
+        SymLoc == AArch64AuthMCExpr::VK_AUTHADDR) {
+      assert(Value == 0);
+      const auto *Expr = cast<AArch64AuthMCExpr>(Fixup.getValue());
+      Value = (uint64_t(Expr->getDiscriminator()) << 32) |
+              (uint64_t(Expr->getKey()) << 60) |
+              (uint64_t(Expr->hasAddressDiversity()) << 63);
+    }
+  }
+
   if (!Value)
     return; // Doesn't change encoding.
   unsigned Kind = Fixup.getKind();

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index bcb6c7c1a0fa05..5d6a41558bc624 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -207,8 +207,12 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
                         "ILP32 8 byte absolute data "
                         "relocation not supported (LP64 eqv: ABS64)");
         return ELF::R_AARCH64_NONE;
-      } else
+      } else {
+        if (RefKind == AArch64MCExpr::VK_AUTH ||
+            RefKind == AArch64MCExpr::VK_AUTHADDR)
+          return ELF::R_AARCH64_AUTH_ABS64;
         return ELF::R_AARCH64_ABS64;
+      }
     case AArch64::fixup_aarch64_add_imm12:
       if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
         return R_CLS(TLSLD_ADD_DTPREL_HI12);

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
index cb39c2a114872b..0c5a9d79f6cbc8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
@@ -154,3 +154,47 @@ void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
 
   fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
 }
+
+const AArch64AuthMCExpr *AArch64AuthMCExpr::create(const MCExpr *Expr,
+                                                   uint16_t Discriminator,
+                                                   AArch64PACKey::ID Key,
+                                                   bool HasAddressDiversity,
+                                                   MCContext &Ctx) {
+  return new (Ctx)
+      AArch64AuthMCExpr(Expr, Discriminator, Key, HasAddressDiversity);
+}
+
+void AArch64AuthMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+  bool WrapSubExprInParens = !isa<MCSymbolRefExpr>(getSubExpr());
+  if (WrapSubExprInParens)
+    OS << '(';
+  getSubExpr()->print(OS, MAI);
+  if (WrapSubExprInParens)
+    OS << ')';
+
+  OS << "@AUTH(" << AArch64PACKeyIDToString(Key) << ',' << Discriminator;
+  if (hasAddressDiversity())
+    OS << ",addr";
+  OS << ')';
+}
+
+void AArch64AuthMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
+  Streamer.visitUsedExpr(*getSubExpr());
+}
+
+MCFragment *AArch64AuthMCExpr::findAssociatedFragment() const {
+  llvm_unreachable("FIXME: what goes here?");
+}
+
+bool AArch64AuthMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
+                                                  const MCAsmLayout *Layout,
+                                                  const MCFixup *Fixup) const {
+  if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
+    return false;
+
+  if (Res.getSymB())
+    report_fatal_error("Auth relocation can't reference two symbols");
+
+  Res = MCValue::get(Res.getSymA(), nullptr, Res.getConstant(), getKind());
+  return true;
+}

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
index f8938cdbbec305..48235988869ca0 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
@@ -14,7 +14,9 @@
 #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCEXPR_H
 #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCEXPR_H
 
+#include "Utils/AArch64BaseInfo.h"
 #include "llvm/MC/MCExpr.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 
 namespace llvm {
@@ -34,6 +36,8 @@ class AArch64MCExpr : public MCTargetExpr {
     VK_TPREL    = 0x007,
     VK_TLSDESC  = 0x008,
     VK_SECREL   = 0x009,
+    VK_AUTH     = 0x00a,
+    VK_AUTHADDR = 0x00b,
     VK_SymLocBits = 0x00f,
 
     // Variants specifying which part of the final address calculation is
@@ -116,6 +120,7 @@ class AArch64MCExpr : public MCTargetExpr {
   const MCExpr *Expr;
   const VariantKind Kind;
 
+protected:
   explicit AArch64MCExpr(const MCExpr *Expr, VariantKind Kind)
     : Expr(Expr), Kind(Kind) {}
 
@@ -171,6 +176,42 @@ class AArch64MCExpr : public MCTargetExpr {
     return E->getKind() == MCExpr::Target;
   }
 };
+
+class AArch64AuthMCExpr final : public AArch64MCExpr {
+  uint16_t Discriminator;
+  AArch64PACKey::ID Key;
+
+  explicit AArch64AuthMCExpr(const MCExpr *Expr, uint16_t Discriminator,
+                             AArch64PACKey::ID Key, bool HasAddressDiversity)
+      : AArch64MCExpr(Expr, HasAddressDiversity ? VK_AUTHADDR : VK_AUTH),
+        Discriminator(Discriminator), Key(Key) {}
+
+public:
+  static const AArch64AuthMCExpr *
+  create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key,
+         bool HasAddressDiversity, MCContext &Ctx);
+
+  AArch64PACKey::ID getKey() const { return Key; }
+  uint16_t getDiscriminator() const { return Discriminator; }
+  bool hasAddressDiversity() const { return getKind() == VK_AUTHADDR; }
+
+  void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
+
+  void visitUsedExpr(MCStreamer &Streamer) const override;
+
+  MCFragment *findAssociatedFragment() const override;
+
+  bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
+                                 const MCFixup *Fixup) const override;
+
+  static bool classof(const MCExpr *E) {
+    return isa<AArch64MCExpr>(E) && classof(cast<AArch64MCExpr>(E));
+  }
+
+  static bool classof(const AArch64MCExpr *E) {
+    return E->getKind() == VK_AUTH || E->getKind() == VK_AUTHADDR;
+  }
+};
 } // end namespace llvm
 
 #endif

diff  --git a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
new file mode 100644
index 00000000000000..1ce008117ac302
--- /dev/null
+++ b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
@@ -0,0 +1,193 @@
+// RUN: llvm-mc -triple=aarch64 %s --defsym=ASMONLY=1 | FileCheck %s --check-prefix=ASM
+
+// RUN: llvm-mc -triple=aarch64 -filetype=obj %s | \
+// RUN:   llvm-readelf -S -r -x .test - | FileCheck %s --check-prefix=RELOC
+
+// RELOC: Relocation section '.rela.test' at offset 0x230 contains 8 entries:
+// RELOC-NEXT:  Offset Info Type Symbol's Value Symbol's Name + Addend
+// RELOC-NEXT: 0000000000000000 000000010000e100 R_AARCH64_AUTH_ABS64 0000000000000000 .helper + 0
+// RELOC-NEXT: 0000000000000010 000000080000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g1 + 0
+// RELOC-NEXT: 0000000000000020 000000090000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g2 + 0
+// RELOC-NEXT: 0000000000000030 0000000a0000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g3 + 0
+// RELOC-NEXT: 0000000000000040 0000000b0000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g4 + 7
+// RELOC-NEXT: 0000000000000050 0000000c0000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g5 - 3
+// RELOC-NEXT: 0000000000000060 000000020000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g 6 + 0
+// RELOC-NEXT: 0000000000000070 0000000d0000e100 R_AARCH64_AUTH_ABS64 0000000000000000 _g 7 + 7
+
+// RELOC: Hex dump of section '.test':
+//                VVVVVVVV addend, not needed for rela
+//                             VV reserved
+// RELOC-NEXT: 00 00000000 2a000000
+//                         ^^^^ discriminator
+//                               ^^ 0 no addr diversity 0 reserved 00 ia key 0000 reserved
+// RELOC-NEXT: 10 00000000 00000010
+//                         ^^^^ discriminator
+//                               ^^ 0 no addr diversity 0 reserved 01 ib key 0000 reserved
+// RELOC-NEXT: 20 00000000 050000a0
+//                         ^^^^ discriminator
+//                               ^^ 1    addr diversity 0 reserved 10 da key 0000 reserved
+// RELOC-NEXT: 30 00000000 ffff00b0
+//                         ^^^^ discriminator
+//                               ^^ 1    addr diversity 0 reserved 11 db key 0000 reserved
+// RELOC-NEXT: 40 00000000 00000000
+//                         ^^^^ discriminator
+//                               ^^ 0 no addr diversity 0 reserved 00 ia key 0000 reserved
+// RELOC-NEXT: 50 00000000 00de0010
+//                         ^^^^ discriminator
+//                               ^^ 0 no addr diversity 0 reserved 01 ib key 0000 reserved
+// RELOC-NEXT: 60 00000000 ff0000b0
+//                         ^^^^ discriminator
+//                               ^^ 1    addr diversity 0 reserved 11 db key 0000 reserved
+// RELOC-NEXT: 70 00000000 10000000
+//                         ^^^^ discriminator
+//                               ^^ 0 no addr diversity 0 reserved 00 ia key 0000 reserved
+// RELOC-NEXT: 80 04000000 00000000
+// Folded to constant 4 bytes 
diff erence between _g9 and _g8
+
+.section    .helper
+.local "_g 6"
+.type _g0, @function
+_g0:
+  ret
+.type _g8, @function
+_g8:
+  ret
+.type _g9, @function
+_g9:
+  ret
+
+.section	.test
+.p2align	3
+
+// ASM:          .xword _g0 at AUTH(ia,42)
+.quad _g0 at AUTH(ia,42)
+.quad 0
+
+// ASM:          .xword _g1 at AUTH(ib,0)
+.quad _g1 at AUTH(ib,0)
+.quad 0
+
+// ASM:          .xword _g2 at AUTH(da,5,addr)
+.quad _g2 at AUTH(da,5,addr)
+.quad 0
+
+// ASM:          .xword _g3 at AUTH(db,65535,addr)
+.quad _g3 at AUTH(db,0xffff,addr)
+.quad 0
+
+// ASM:          .xword (_g4+7)@AUTH(ia,0)
+.quad (_g4 + 7)@AUTH(ia,0)
+.quad 0
+
+// ASM:          .xword (_g5-3)@AUTH(ib,56832)
+.quad (_g5 - 3)@AUTH(ib,0xde00)
+.quad 0
+
+// ASM:          .xword "_g 6"@AUTH(db,255,addr)
+.quad "_g 6"@AUTH(db,0xff,addr)
+.quad 0
+
+// ASM:          .xword ("_g 7"+7)@AUTH(ia,16)
+.quad ("_g 7" + 7)@AUTH(ia,16)
+.quad 0
+
+// ASM:          .xword (_g9 at AUTH(ia,42))-(_g8 at AUTH(ia,42))
+.quad _g9 at AUTH(ia,42) - _g8 at AUTH(ia,42)
+.quad 0
+
+.ifdef ASMONLY
+
+// ASM:          .xword (_g10 at AUTH(ia,42))+1
+.quad _g10 at AUTH(ia,42) + 1
+
+// ASM:          .xword 1+(_g11 at AUTH(ia,42))
+.quad 1 + _g11 at AUTH(ia,42)
+
+// ASM:          .xword (1+(_g12 at AUTH(ia,42)))+1
+.quad 1 + _g12 at AUTH(ia,42) + 1
+
+// ASM:          .xword (_g13 at AUTH(ia,42))+(_g14 at AUTH(ia,42))
+.quad _g13 at AUTH(ia,42) + _g14 at AUTH(ia,42)
+
+// ASM:          .xword (_g9 at AUTH(ia,42))-_g8
+.quad _g9 at AUTH(ia,42) - _g8
+.quad 0
+
+.endif // ASMONLY
+
+.ifdef ERR
+// RUN: not llvm-mc -triple=aarch64 --defsym=ERR=1 %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=ERR
+
+// ERR: :[[#@LINE+1]]:15: error: expected '('
+.quad sym at AUTH)ia,42)
+
+// ERR: :[[#@LINE+1]]:16: error: expected key name
+.quad sym at AUTH(42,42)
+
+// ERR: :[[#@LINE+1]]:16: error: invalid key 'ic'
+.quad sym at AUTH(ic,42)
+
+// ERR: :[[#@LINE+1]]:19: error: expected ','
+.quad sym at AUTH(ia 42)
+
+// ERR: :[[#@LINE+1]]:19: error: expected integer discriminator
+.quad sym at AUTH(ia,xxx)
+
+// ERR: :[[#@LINE+1]]:19: error: integer discriminator 65536 out of range [0, 0xFFFF]
+.quad sym at AUTH(ia,65536)
+
+// ERR: :[[#@LINE+1]]:22: error: expected 'addr'
+.quad sym at AUTH(ia,42,add)
+
+// ERR: :[[#@LINE+1]]:21: error: expected ')'
+.quad sym at AUTH(ia,42(
+
+// ERR: :[[#@LINE+1]]:7: error: combination of @AUTH with other modifiers not supported
+.quad sym at PLT@AUTH(ia,42)
+
+// ERR: :[[#@LINE+1]]:11: error: invalid variant 'AUTH at GOT'
+.quad sym at AUTH@GOT(ia,42)
+
+// ERR: :[[#@LINE+1]]:18: error: invalid variant 'TLSDESC at AUTH'
+.quad "long sym"@TLSDESC at AUTH(ia,42)
+
+// ERR: :[[#@LINE+1]]:18: error: invalid variant 'AUTH at PLT'
+.quad "long sym"@AUTH at PLT(ia,42)
+
+// ERR: :[[#@LINE+1]]:17: error: invalid variant 'GOT at AUTH'
+.quad (sym - 5)@GOT at AUTH(ia,42)
+
+// ERR: :[[#@LINE+1]]:17: error: invalid variant 'AUTH at TLSDESC'
+.quad (sym + 5)@AUTH at TLSDESC(ia,42)
+
+// ERR: :[[#@LINE+1]]:12: error: invalid variant 'AUTH'
+.quad +sym at AUTH(ia,42)
+
+.endif // ERR
+
+.ifdef ERROBJ
+// RUN: not llvm-mc -triple=aarch64 -filetype=obj --defsym=ERROBJ=1 %s -o /dev/null 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=ERROBJ
+
+// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
+.quad sym at AUTH(ia,42) + 1
+
+// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
+.quad 1 + sym at AUTH(ia,42)
+
+// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
+.quad 1 + sym at AUTH(ia,42) + 1
+
+// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
+.quad sym at AUTH(ia,42) + sym at AUTH(ia,42)
+
+// TODO: do we really want to emit an error here? It might not be important
+// whether a symbol has an AUTH modifier or not since the compile-time computed
+// distance remains the same. Leave it in such state as for now since it
+// makes code simpler: subtraction of a non-AUTH symbol and of a constant
+// are handled identically.
+// ERROBJ: :[[#@LINE+1]]:7: error: expected relocatable expression
+.quad _g9 at AUTH(ia,42) - _g8
+
+.endif // ERROBJ


        


More information about the llvm-commits mailing list