{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
-{ "fixup_arm_bl", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx ||
(unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl ||
(unsigned)Fixup.getKind() == ARM::fixup_arm_blx ||
- (unsigned)Fixup.getKind() == ARM::fixup_arm_bl))
+ (unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl ||
+ (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl))
IsResolved = false;
}
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
- case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_uncondbl:
+ case ARM::fixup_arm_condbl:
case ARM::fixup_arm_blx:
// These values don't encode the low two bits since they're always zero.
// Offset by 8 just as above.
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
- case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_uncondbl:
+ case ARM::fixup_arm_condbl:
case ARM::fixup_arm_blx:
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
break;
}
break;
- case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_uncondbl:
case ARM::fixup_arm_blx:
case ARM::fixup_arm_uncondbranch:
switch (Modifier) {
break;
}
break;
+ case ARM::fixup_arm_condbl:
case ARM::fixup_arm_condbranch:
Type = ELF::R_ARM_JUMP24;
break;
// fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions.
fixup_arm_thumb_br,
- // fixup_arm_bl - Fixup for ARM BL instructions.
- fixup_arm_bl,
+ // The following fixups handle the ARM BL instructions. These can be
+ // conditionalised; however, the ARM ELF ABI requires a different relocation
+ // in that case: R_ARM_JUMP24 instead of R_ARM_CALL. The difference is that
+ // R_ARM_CALL is allowed to change the instruction to a BLX inline, which has
+ // no conditional version; R_ARM_JUMP24 would have to insert a veneer.
+ //
+ // MachO does not draw a distinction between the two cases, so it will treat
+ // fixup_arm_uncondbl and fixup_arm_condbl as identical fixups.
+
+ // fixup_arm_uncondbl - Fixup for unconditional ARM BL instructions.
+ fixup_arm_uncondbl,
+
+ // fixup_arm_condbl - Fixup for ARM BL instructions with nontrivial
+ // conditionalisation.
+ fixup_arm_condbl,
// fixup_arm_blx - Fixup for ARM BLX instructions.
fixup_arm_blx,
getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand MO = MI.getOperand(OpIdx);
- if (MO.isExpr())
- return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_bl, Fixups);
+ if (MO.isExpr()) {
+ if (HasConditionalBranch(MI))
+ return ::getBranchTargetOpValue(MI, OpIdx,
+ ARM::fixup_arm_condbl, Fixups);
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_uncondbl, Fixups);
+ }
return MO.getImm() >> 2;
}
case ARM::fixup_arm_adr_pcrel_12:
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
- case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_uncondbl:
+ case ARM::fixup_arm_condbl:
case ARM::fixup_arm_blx:
RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
// Report as 'long', even though that is not quite accurate.
bl _printf
@ CHECK: bl _printf @ encoding: [A,A,A,0xeb]
-@ CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_bl
+@ CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbl
mov r9, :lower16:(_foo)
movw r9, :lower16:(_foo)
@------------------------------------------------------------------------------
bl _bar
+ bleq _bar
blx _bar
blls #28634268
blx #32424576
blx #16212288
@ CHECK: bl _bar @ encoding: [A,A,A,0xeb]
-@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_bl
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbl
+@ CHECK: bleq _bar @ encoding: [A,A,A,0x0b]
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_condbl
@ CHECK: blx _bar @ encoding: [A,A,A,0xfa]
@ fixup A - offset: 0, value: _bar, kind: fixup_arm_blx
@ CHECK: blls #28634268 @ encoding: [0x27,0x3b,0x6d,0x9b]
--- /dev/null
+// RUN: llvm-mc -triple=armv7-linux-gnueabi -filetype=obj %s -o - | \
+// RUN: elf-dump | FileCheck -check-prefix=OBJ %s
+
+ bleq some_label
+ bl some_label
+ blx some_label
+// OBJ: .rel.text
+
+// OBJ: 'r_offset', 0x00000000
+// OBJ-NEXT: 'r_sym', 0x000004
+// OBJ-NEXT: 'r_type', 0x1d
+
+// OBJ: 'r_offset', 0x00000004
+// OBJ-NEXT: 'r_sym', 0x000004
+// OBJ-NEXT: 'r_type', 0x1c
+
+// OBJ: 'r_offset', 0x00000008
+// OBJ-NEXT: 'r_sym', 0x000004
+// OBJ-NEXT: 'r_type', 0x1c
+
+// OBJ: .symtab
+// OBJ: Symbol 4
+// OBJ-NEXT: some_label
\ No newline at end of file