Skip to content

Instantly share code, notes, and snippets.

@mskvortsov
Last active November 2, 2017 09:53
Show Gist options
  • Save mskvortsov/5eaf3ac7d81da38b6e7e61b562153cab to your computer and use it in GitHub Desktop.
Save mskvortsov/5eaf3ac7d81da38b6e7e61b562153cab to your computer and use it in GitHub Desktop.
diff --git a/lib/ObjWriter/objwriter.cpp b/lib/ObjWriter/objwriter.cpp
index 5024c55..c2f302c 100644
--- a/lib/ObjWriter/objwriter.cpp
+++ b/lib/ObjWriter/objwriter.cpp
@@ -303,6 +303,15 @@ void ObjectWriter::EmitIntValue(uint64_t Value, unsigned Size) {
void ObjectWriter::EmitSymbolDef(const char *SymbolName) {
MCSymbol *Sym = OutContext->getOrCreateSymbol(Twine(SymbolName));
Streamer->EmitSymbolAttribute(Sym, MCSA_Global);
+
+ // A Thumb2 function symbol should be marked with an appropriate ELF
+ // attribute to make later computation of a relocation address value correct
+ if (GetTriple().getArch() == Triple::thumb &&
+ GetTriple().getObjectFormat() == Triple::ELF &&
+ Streamer->getCurrentSectionOnly()->getKind().isText()) {
+ Streamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
+ }
+
Streamer->EmitLabel(Sym);
}
@@ -317,6 +326,51 @@ ObjectWriter::GetSymbolRefExpr(const char *SymbolName,
int ObjectWriter::EmitSymbolRef(const char *SymbolName,
RelocType RelocationType, int Delta) {
+ if (GetTriple().getArch() == Triple::thumb)
+ {
+ const MCExpr *TargetExpr =
+ GetSymbolRefExpr(SymbolName, MCSymbolRefExpr::VK_None);
+ if (Delta != 0) {
+ TargetExpr = MCBinaryExpr::createAdd(TargetExpr,
+ MCConstantExpr::create(Delta, *OutContext), *OutContext);
+ }
+
+ MCDataFragment *DF = Streamer->getOrCreateDataFragment();
+ unsigned Offset = DF->getContents().size();
+ const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, *OutContext);
+
+ switch (RelocationType)
+ {
+ case RelocType::IMAGE_REL_BASED_REL32:
+ // If the fixup is pc-relative, we need to bias the value to be relative
+ // to the start of the field, not the end of the field
+ TargetExpr = MCBinaryExpr::createSub(
+ TargetExpr, MCConstantExpr::create(4, *OutContext), *OutContext);
+ Streamer->EmitValueImpl(TargetExpr, 4, SMLoc(), true);
+ return 4;
+
+ case RelocType::IMAGE_REL_BASED_HIGHLOW:
+ Streamer->EmitValueImpl(TargetExpr, 4, SMLoc());
+ return 4;
+
+ case RelocType::IMAGE_REL_BASED_THUMB_MOV32:
+ Streamer->EmitRelocDirective(*OffsetExpr, "R_ARM_THM_MOVW_ABS_NC",
+ TargetExpr, SMLoc());
+ OffsetExpr = MCConstantExpr::create(Offset + 4, *OutContext);
+ Streamer->EmitRelocDirective(*OffsetExpr, "R_ARM_THM_MOVT_ABS",
+ TargetExpr, SMLoc());
+ return 8;
+
+ case RelocType::IMAGE_REL_BASED_THUMB_BRANCH24:
+ Streamer->EmitRelocDirective(*OffsetExpr, "R_ARM_THM_JUMP24", TargetExpr,
+ SMLoc());
+ return 4;
+
+ default:
+ assert(false && "EmitSymbolRef: unknown RelocationType!");
+ }
+ }
+
bool IsPCRelative = false;
int Size = 0;
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
diff --git a/lib/ObjWriter/objwriter.h b/lib/ObjWriter/objwriter.h
index c4a07b3..ee145c6 100644
--- a/lib/ObjWriter/objwriter.h
+++ b/lib/ObjWriter/objwriter.h
@@ -34,8 +34,10 @@ enum CustomSectionAttributes : int32_t {
enum class RelocType {
IMAGE_REL_BASED_ABSOLUTE = 0x00,
IMAGE_REL_BASED_HIGHLOW = 0x03,
+ IMAGE_REL_BASED_THUMB_MOV32 = 0x07,
IMAGE_REL_BASED_DIR64 = 0x0A,
IMAGE_REL_BASED_REL32 = 0x10,
+ IMAGE_REL_BASED_THUMB_BRANCH24 = 0x13,
};
class ObjectWriter {
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 40bf545e832..d9725556b5a 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -48,6 +48,14 @@ public:
};
} // end anonymous namespace
+Optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const {
+ return StringSwitch<Optional<MCFixupKind>>(Name)
+ .Case("R_ARM_THM_MOVW_ABS_NC", (MCFixupKind)ARM::fixup_t2_movw_lo16)
+ .Case("R_ARM_THM_MOVT_ABS", (MCFixupKind)ARM::fixup_t2_movt_hi16)
+ .Case("R_ARM_THM_JUMP24", (MCFixupKind)ARM::fixup_arm_thumb_blx)
+ .Default(MCAsmBackend::getFixupKind(Name));
+}
+
const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = {
// This table *must* be in the order that the fixup_* kinds are defined in
@@ -369,6 +377,8 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case FK_Data_2:
case FK_Data_4:
return Value;
+ case FK_PCRel_4:
+ return Value;
case FK_SecRel_2:
return Value;
case FK_SecRel_4:
@@ -785,6 +795,9 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM::fixup_t2_movw_lo16:
return 4;
+ case FK_PCRel_4:
+ return 4;
+
case FK_SecRel_2:
return 2;
case FK_SecRel_4:
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
index 2ddedb5d610..7488ef3670a 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
@@ -36,6 +36,7 @@ public:
bool hasNOP() const { return STI->getFeatureBits()[ARM::HasV6T2Ops]; }
+ Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
/// processFixupValue - Target hook to process the literal value of a fixup
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index e1fa2457182..f0cd80a2d28 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -103,6 +103,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
break;
}
break;
+ case FK_PCRel_4:
+ Type = ELF::R_ARM_REL32;
+ break;
case ARM::fixup_arm_blx:
case ARM::fixup_arm_uncondbl:
switch (Modifier) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment