Skip to content

Commit 52a7dd7

Browse files
author
Prakhar Bahuguna
committed
[ARM] Implement execute-only support in CodeGen
This implements execute-only support for ARM code generation, which prevents the compiler from generating data accesses to code sections. The following changes are involved: * Add the CodeGen option "-arm-execute-only" to the ARM code generator. * Add the clang flag "-mexecute-only" as well as the GCC-compatible alias "-mpure-code" to enable this option. * When enabled, literal pools are replaced with MOVW/MOVT instructions, with VMOV used in addition for floating-point literals. As the MOVT instruction is required, execute-only support is only available in Thumb mode for targets supporting ARMv8-M baseline or Thumb2. * Jump tables are placed in data sections when in execute-only mode. * The execute-only text section is assigned section ID 0, and is marked as unreadable with the SHF_ARM_PURECODE flag with symbol 'y'. This also overrides selection of ELF sections for globals. llvm-svn: 289784
1 parent 342beeb commit 52a7dd7

27 files changed

+455
-20
lines changed

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace llvm {
3333

3434
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
3535
bool UseInitArray;
36-
mutable unsigned NextUniqueID = 0;
36+
mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections
3737

3838
protected:
3939
MCSymbolRefExpr::VariantKind PLTRelativeVariantKind =

llvm/include/llvm/MC/SectionKind.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class SectionKind {
2828
/// Text - Text section, used for functions and other executable code.
2929
Text,
3030

31+
/// ExecuteOnly, Text section that is not readable.
32+
ExecuteOnly,
33+
3134
/// ReadOnly - Data that is never written to at program runtime by the
3235
/// program or the dynamic linker. Things in the top-level readonly
3336
/// SectionKind are not mergeable.
@@ -112,7 +115,10 @@ class SectionKind {
112115
public:
113116

114117
bool isMetadata() const { return K == Metadata; }
115-
bool isText() const { return K == Text; }
118+
119+
bool isText() const { return K == Text || K == ExecuteOnly; }
120+
121+
bool isExecuteOnly() const { return K == ExecuteOnly; }
116122

117123
bool isReadOnly() const {
118124
return K == ReadOnly || isMergeableCString() ||
@@ -172,6 +178,7 @@ class SectionKind {
172178

173179
static SectionKind getMetadata() { return get(Metadata); }
174180
static SectionKind getText() { return get(Text); }
181+
static SectionKind getExecuteOnly() { return get(ExecuteOnly); }
175182
static SectionKind getReadOnly() { return get(ReadOnly); }
176183
static SectionKind getMergeable1ByteCString() {
177184
return get(Mergeable1ByteCString);

llvm/include/llvm/Support/ELF.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,9 @@ enum : unsigned {
804804
// Section data is string data by default.
805805
SHF_MIPS_STRING = 0x80000000,
806806

807+
// Make code section unreadable when in execute-only mode
808+
SHF_ARM_PURECODE = 0x20000000,
809+
807810
SHF_AMDGPU_HSA_GLOBAL = 0x00100000,
808811
SHF_AMDGPU_HSA_READONLY = 0x00200000,
809812
SHF_AMDGPU_HSA_CODE = 0x00400000,

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ static unsigned getELFSectionFlags(SectionKind K) {
181181
if (K.isText())
182182
Flags |= ELF::SHF_EXECINSTR;
183183

184+
if (K.isExecuteOnly())
185+
Flags |= ELF::SHF_ARM_PURECODE;
186+
184187
if (K.isWriteable())
185188
Flags |= ELF::SHF_WRITE;
186189

@@ -312,6 +315,9 @@ selectELFSectionForGlobal(MCContext &Ctx, const GlobalObject *GO,
312315
UniqueID = *NextUniqueID;
313316
(*NextUniqueID)++;
314317
}
318+
// Use 0 as the unique ID for execute-only text
319+
if (Kind.isExecuteOnly())
320+
UniqueID = 0;
315321
return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags,
316322
EntrySize, Group, UniqueID);
317323
}

llvm/lib/MC/MCContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,9 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
368368
StringRef CachedName = Entry.first.SectionName;
369369

370370
SectionKind Kind;
371-
if (Flags & ELF::SHF_EXECINSTR)
371+
if (Flags & ELF::SHF_ARM_PURECODE)
372+
Kind = SectionKind::getExecuteOnly();
373+
else if (Flags & ELF::SHF_EXECINSTR)
372374
Kind = SectionKind::getText();
373375
else
374376
Kind = SectionKind::getReadOnly();

llvm/lib/MC/MCParser/ELFAsmParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ static unsigned parseSectionFlags(StringRef flagsStr, bool *UseLastGroup) {
293293
case 'd':
294294
flags |= ELF::XCORE_SHF_DP_SECTION;
295295
break;
296+
case 'y':
297+
flags |= ELF::SHF_ARM_PURECODE;
298+
break;
296299
case 'G':
297300
flags |= ELF::SHF_GROUP;
298301
break;

llvm/lib/MC/MCSectionELF.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI,
110110
OS << 'c';
111111
if (Flags & ELF::XCORE_SHF_DP_SECTION)
112112
OS << 'd';
113+
if (Flags & ELF::SHF_ARM_PURECODE)
114+
OS << 'y';
113115

114116
OS << '"';
115117

llvm/lib/ObjectYAML/ELFYAML.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO,
423423
BCase(SHF_GROUP)
424424
BCase(SHF_TLS)
425425
switch(Object->Header.Machine) {
426+
case ELF::EM_ARM:
427+
BCase(SHF_ARM_PURECODE)
428+
break;
426429
case ELF::EM_AMDGPU:
427430
BCase(SHF_AMDGPU_HSA_GLOBAL)
428431
BCase(SHF_AMDGPU_HSA_READONLY)

llvm/lib/Target/ARM/ARMAsmPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
232232
break;
233233
}
234234
case MachineOperand::MO_ConstantPoolIndex:
235+
if (Subtarget->genExecuteOnly())
236+
llvm_unreachable("execute-only should not generate constant pools");
235237
GetCPISymbol(MO.getIndex())->print(O, MAI);
236238
break;
237239
}

llvm/lib/Target/ARM/ARMConstantIslandPass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
423423
MadeChange |= optimizeThumb2Branches();
424424

425425
// Optimize jump tables using TBB / TBH.
426-
if (GenerateTBB)
426+
if (GenerateTBB && !STI->genExecuteOnly())
427427
MadeChange |= optimizeThumb2JumpTables();
428428

429429
// After a while, this might be made debug-only, but it is not expensive.

0 commit comments

Comments
 (0)