Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 3cc1102

Browse files
committed
[AArch64] Better errors for out-of-range fixups
When a fixup that can be resolved by the assembler is out of range, we should report an error in the source, rather than crashing. Differential Revision: http://reviews.llvm.org/D18402 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265120 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 03b2cf6 commit 3cc1102

File tree

3 files changed

+110
-25
lines changed

3 files changed

+110
-25
lines changed

lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "MCTargetDesc/AArch64FixupKinds.h"
1313
#include "llvm/ADT/Triple.h"
1414
#include "llvm/MC/MCAsmBackend.h"
15+
#include "llvm/MC/MCContext.h"
1516
#include "llvm/MC/MCDirectives.h"
1617
#include "llvm/MC/MCELFObjectWriter.h"
1718
#include "llvm/MC/MCFixupKindInfo.h"
@@ -134,69 +135,83 @@ static unsigned AdrImmBits(unsigned Value) {
134135
return (hi19 << 5) | (lo2 << 29);
135136
}
136137

137-
static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
138+
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
139+
MCContext *Ctx) {
140+
unsigned Kind = Fixup.getKind();
138141
int64_t SignedValue = static_cast<int64_t>(Value);
139142
switch (Kind) {
140143
default:
141144
llvm_unreachable("Unknown fixup kind!");
142145
case AArch64::fixup_aarch64_pcrel_adr_imm21:
143-
if (SignedValue > 2097151 || SignedValue < -2097152)
144-
report_fatal_error("fixup value out of range");
146+
if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152))
147+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
145148
return AdrImmBits(Value & 0x1fffffULL);
146149
case AArch64::fixup_aarch64_pcrel_adrp_imm21:
147150
return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
148151
case AArch64::fixup_aarch64_ldr_pcrel_imm19:
149152
case AArch64::fixup_aarch64_pcrel_branch19:
150153
// Signed 21-bit immediate
151154
if (SignedValue > 2097151 || SignedValue < -2097152)
152-
report_fatal_error("fixup value out of range");
155+
if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
156+
if (Ctx && (Value & 0x3))
157+
Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
153158
// Low two bits are not encoded.
154159
return (Value >> 2) & 0x7ffff;
155160
case AArch64::fixup_aarch64_add_imm12:
156161
case AArch64::fixup_aarch64_ldst_imm12_scale1:
157162
// Unsigned 12-bit immediate
158-
if (Value >= 0x1000)
159-
report_fatal_error("invalid imm12 fixup value");
163+
if (Ctx && Value >= 0x1000)
164+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
160165
return Value;
161166
case AArch64::fixup_aarch64_ldst_imm12_scale2:
162167
// Unsigned 12-bit immediate which gets multiplied by 2
163-
if (Value & 1 || Value >= 0x2000)
164-
report_fatal_error("invalid imm12 fixup value");
168+
if (Ctx && (Value >= 0x2000))
169+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
170+
if (Ctx && (Value & 0x1))
171+
Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
165172
return Value >> 1;
166173
case AArch64::fixup_aarch64_ldst_imm12_scale4:
167174
// Unsigned 12-bit immediate which gets multiplied by 4
168-
if (Value & 3 || Value >= 0x4000)
169-
report_fatal_error("invalid imm12 fixup value");
175+
if (Ctx && (Value >= 0x4000))
176+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
177+
if (Ctx && (Value & 0x3))
178+
Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
170179
return Value >> 2;
171180
case AArch64::fixup_aarch64_ldst_imm12_scale8:
172181
// Unsigned 12-bit immediate which gets multiplied by 8
173-
if (Value & 7 || Value >= 0x8000)
174-
report_fatal_error("invalid imm12 fixup value");
182+
if (Ctx && (Value >= 0x8000))
183+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
184+
if (Ctx && (Value & 0x7))
185+
Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
175186
return Value >> 3;
176187
case AArch64::fixup_aarch64_ldst_imm12_scale16:
177188
// Unsigned 12-bit immediate which gets multiplied by 16
178-
if (Value & 15 || Value >= 0x10000)
179-
report_fatal_error("invalid imm12 fixup value");
189+
if (Ctx && (Value >= 0x10000))
190+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
191+
if (Ctx && (Value & 0xf))
192+
Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
180193
return Value >> 4;
181194
case AArch64::fixup_aarch64_movw:
182-
report_fatal_error("no resolvable MOVZ/MOVK fixups supported yet");
195+
if (Ctx)
196+
Ctx->reportError(Fixup.getLoc(),
197+
"no resolvable MOVZ/MOVK fixups supported yet");
183198
return Value;
184199
case AArch64::fixup_aarch64_pcrel_branch14:
185200
// Signed 16-bit immediate
186-
if (SignedValue > 32767 || SignedValue < -32768)
187-
report_fatal_error("fixup value out of range");
201+
if (Ctx && (SignedValue > 32767 || SignedValue < -32768))
202+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
188203
// Low two bits are not encoded (4-byte alignment assumed).
189-
if (Value & 0x3)
190-
report_fatal_error("fixup not sufficiently aligned");
204+
if (Ctx && (Value & 0x3))
205+
Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
191206
return (Value >> 2) & 0x3fff;
192207
case AArch64::fixup_aarch64_pcrel_branch26:
193208
case AArch64::fixup_aarch64_pcrel_call26:
194209
// Signed 28-bit immediate
195-
if (SignedValue > 134217727 || SignedValue < -134217728)
196-
report_fatal_error("fixup value out of range");
210+
if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728))
211+
Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
197212
// Low two bits are not encoded (4-byte alignment assumed).
198-
if (Value & 0x3)
199-
report_fatal_error("fixup not sufficiently aligned");
213+
if (Ctx && (Value & 0x3))
214+
Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
200215
return (Value >> 2) & 0x3ffffff;
201216
case FK_Data_1:
202217
case FK_Data_2:
@@ -253,7 +268,7 @@ void AArch64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
253268
return; // Doesn't change encoding.
254269
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
255270
// Apply any target-specific value adjustments.
256-
Value = adjustFixupValue(Fixup.getKind(), Value);
271+
Value = adjustFixupValue(Fixup, Value, nullptr);
257272

258273
// Shift the value into position.
259274
Value <<= Info.TargetOffset;
@@ -544,6 +559,12 @@ void ELFAArch64AsmBackend::processFixupValue(
544559
// to the linker -- a relocation!
545560
if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
546561
IsResolved = false;
562+
563+
// Try to get the encoded value for the fixup as-if we're mapping it into
564+
// the instruction. This allows adjustFixupValue() to issue a diagnostic
565+
// if the value is invalid.
566+
if (IsResolved)
567+
(void)adjustFixupValue(Fixup, Value, &Asm.getContext());
547568
}
548569

549570
}

test/MC/AArch64/fixup-out-of-range.s

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
4+
adr x0, distant
5+
6+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
7+
ldr x0, distant
8+
9+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
10+
ldr x0, unaligned
11+
12+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
13+
b.eq distant
14+
15+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
16+
b.eq unaligned
17+
18+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
19+
ldr x0, [x1, distant-.]
20+
21+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 8-byte aligned
22+
ldr x0, [x1, unaligned-.]
23+
24+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
25+
ldr w0, [x1, distant-.]
26+
27+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 4-byte aligned
28+
ldr w0, [x1, unaligned-.]
29+
30+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
31+
ldrh w0, [x1, distant-.]
32+
33+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 2-byte aligned
34+
ldrh w0, [x1, unaligned-.]
35+
36+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
37+
ldrb w0, [x1, distant-.]
38+
39+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
40+
ldr q0, [x1, distant-.]
41+
42+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 16-byte aligned
43+
ldr q0, [x1, unaligned-.]
44+
45+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
46+
tbz x0, #1, distant
47+
48+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
49+
tbz x0, #1, unaligned
50+
51+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
52+
b distant
53+
54+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
55+
b unaligned
56+
57+
.byte 0
58+
unaligned:
59+
.byte 0
60+
61+
.space 1<<27
62+
.balign 8
63+
distant:
64+
.word 0

test/MC/AArch64/ldr-pseudo-obj-errors.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88

99
.text
1010
foo:
11+
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
1112
ldr x0, =0x10111
1213
.space 0xdeadb0
13-
// CHECK: LVM ERROR: fixup value out of range

0 commit comments

Comments
 (0)