Commit 7cd5351c by Qining Lu

Function Layout, Global Variable Layout and Pooled Constants Layout Reordering

PURPOSE: The purpose of function layout reordering is to defend against code-reuse attacks as the location of code blocks will be various among different binaries. The layout reordering for global variables and pooled constants can be considered as static data randomization. This is to stop memory corruption attacks by randomizing the locations of the static data. After function layout reordering, the order of function blocks in TEXT section will be randomized. Global variable reordering randomize the order of global variables, and pooled constant reordering randomize the order of pooled constants. Note the order of constant pools won’t be affected and all pooled constants will remain in their original constant pools. USAGE: -reorder-functions: bool type command line option, enables function layout shuffling in TEXT section. Note when -threads=0 is set, function reordering will be forced off. -reorder-functions-window-size: uint32 type command line option, specify the length of the shuffling queue. Note -reorder-functions-window-size=0 or 1 means no shuffling applied to functions. -reorder-global-variables: bool type command line option, enables global variables shuffling. -reorder-pooled-constants: bool type command line option, enables pooled constants shuffling. APPROACH: Randomization is introduced at the code emission time. We use a shuffling method to randomize the emission of function code, global variables and pooled constants. For function code emission, we also introduce “window size” as a parameter to control the size of the function holding buffer for shuffling. Window size 1 and 0 mean no shuffling applied, and a value higher than the number of translated functions means holding all the functions and shuffling them before emitting any of them. IMPLEMENTATION: Function reordering: GlobalContext::emitItems(): Call RandomShuffle() routine to shuffle a specific part of the Pending vector. Global variable reorder: GlobalContext::lowerGlobals(const IceString &SectionSuffix): Call RandomShuffle() routine upon declaration list: Globals. Pooled constant reordering: TargetDataX8632::emitConstantPool(GlobalContext *Ctx): Add call to RandomShuffle() to shuffle the constant pool to be emitted. This is for asm output. ELFObjectWriter::writeConstantPool(Type Tu): Add call to RandomShuffle() to shuffle the constant pool before emitting it. This is only for elf output. ISSUES: The initialization of global variables are emitted along with function code, all of them are considered as EmitterWorkItem. However, we do need to first emit global variables to keep the block profiling workflow untouched. To fulfill this, a “kind” check is added in the while loop of GlobalContext::emitItems(). The “if” statement at line 480 shows the workaround of this issue. BUG= R=jpp@chromium.org, jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1206723003.
parent 67f8de9a
...@@ -279,6 +279,32 @@ cl::opt<uint32_t> RandomizeAndPoolImmediatesThreshold( ...@@ -279,6 +279,32 @@ cl::opt<uint32_t> RandomizeAndPoolImmediatesThreshold(
cl::desc("The threshold for immediates randomization and pooling"), cl::desc("The threshold for immediates randomization and pooling"),
cl::init(0xffff)); cl::init(0xffff));
// Command line option for turning on function layout reordering.
cl::opt<bool> ReorderFunctions(
"reorder-functions",
cl::desc("Reorder the layout of functions in TEXT section"),
cl::init(false));
// Command line option for the shuffling window size for function reordering.
// The default size is 8.
cl::opt<uint32_t> ReorderFunctionsWindowSize(
"reorder-functions-window-size",
cl::desc("The shuffling window size for function reordering. 1 or 0 means "
"no effective shuffling."),
cl::init(8));
// Command line option for turning on global variable layout reordering.
cl::opt<bool> ReorderGlobalVariables(
"reorder-global-variables",
cl::desc("Reorder the layout of global variables in NON TEXT section"),
cl::init(false));
// Command line option for turning on layout reordering in constant pools.
cl::opt<bool> ReorderPooledConstants(
"reorder-pooled-constants",
cl::desc("Reorder the layout of constants in constant pools"),
cl::init(false));
} // end of anonymous namespace } // end of anonymous namespace
namespace Ice { namespace Ice {
...@@ -304,6 +330,9 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) { ...@@ -304,6 +330,9 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) {
OutFlags.PhiEdgeSplit = false; OutFlags.PhiEdgeSplit = false;
OutFlags.RandomNopInsertion = false; OutFlags.RandomNopInsertion = false;
OutFlags.RandomRegAlloc = false; OutFlags.RandomRegAlloc = false;
OutFlags.ReorderFunctions = false;
OutFlags.ReorderGlobalVariables = false;
OutFlags.ReorderPooledConstants = false;
OutFlags.SkipUnimplemented = false; OutFlags.SkipUnimplemented = false;
OutFlags.SubzeroTimingEnabled = false; OutFlags.SubzeroTimingEnabled = false;
OutFlags.TimeEachFunction = false; OutFlags.TimeEachFunction = false;
...@@ -313,6 +342,9 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) { ...@@ -313,6 +342,9 @@ void ClFlags::resetClFlags(ClFlags &OutFlags) {
OutFlags.OutFileType = FT_Iasm; OutFlags.OutFileType = FT_Iasm;
OutFlags.RandomMaxNopsPerInstruction = 0; OutFlags.RandomMaxNopsPerInstruction = 0;
OutFlags.RandomNopProbabilityAsPercentage = 0; OutFlags.RandomNopProbabilityAsPercentage = 0;
OutFlags.RandomizeAndPoolImmediatesOption = RPI_None;
OutFlags.RandomizeAndPoolImmediatesThreshold = 0xffff;
OutFlags.ReorderFunctionsWindowSize = 8;
OutFlags.TArch = TargetArch_NUM; OutFlags.TArch = TargetArch_NUM;
OutFlags.VMask = IceV_None; OutFlags.VMask = IceV_None;
// IceString fields. // IceString fields.
...@@ -372,11 +404,21 @@ void ClFlags::getParsedClFlags(ClFlags &OutFlags) { ...@@ -372,11 +404,21 @@ void ClFlags::getParsedClFlags(ClFlags &OutFlags) {
OutFlags.setNopProbabilityAsPercentage(::NopProbabilityAsPercentage); OutFlags.setNopProbabilityAsPercentage(::NopProbabilityAsPercentage);
OutFlags.setVerbose(VMask); OutFlags.setVerbose(VMask);
// set for immediates randomization or pooling option // Set for immediates randomization or pooling option.
OutFlags.setRandomizeAndPoolImmediatesOption( OutFlags.setRandomizeAndPoolImmediatesOption(
::RandomizeAndPoolImmediatesOption); ::RandomizeAndPoolImmediatesOption);
OutFlags.setRandomizeAndPoolImmediatesThreshold( OutFlags.setRandomizeAndPoolImmediatesThreshold(
::RandomizeAndPoolImmediatesThreshold); ::RandomizeAndPoolImmediatesThreshold);
// Set for function reordering options.
OutFlags.setShouldReorderFunctions(::ReorderFunctions);
OutFlags.setReorderFunctionsWindowSize(::ReorderFunctionsWindowSize);
// Set for global variable reordering option.
OutFlags.setShouldReorderGlobalVariables(::ReorderGlobalVariables);
// Set for pooled constant reordering option.
OutFlags.setShouldReorderPooledConstants(::ReorderPooledConstants);
} }
void ClFlags::getParsedClFlagsExtra(ClFlagsExtra &OutFlagsExtra) { void ClFlags::getParsedClFlagsExtra(ClFlagsExtra &OutFlagsExtra) {
......
...@@ -141,7 +141,6 @@ public: ...@@ -141,7 +141,6 @@ public:
setRandomizeAndPoolImmediatesOption(RandomizeAndPoolImmediatesEnum Option) { setRandomizeAndPoolImmediatesOption(RandomizeAndPoolImmediatesEnum Option) {
RandomizeAndPoolImmediatesOption = Option; RandomizeAndPoolImmediatesOption = Option;
} }
RandomizeAndPoolImmediatesEnum getRandomizeAndPoolImmediatesOption() const { RandomizeAndPoolImmediatesEnum getRandomizeAndPoolImmediatesOption() const {
return RandomizeAndPoolImmediatesOption; return RandomizeAndPoolImmediatesOption;
} }
...@@ -153,6 +152,26 @@ public: ...@@ -153,6 +152,26 @@ public:
return RandomizeAndPoolImmediatesThreshold; return RandomizeAndPoolImmediatesThreshold;
} }
void setShouldReorderFunctions(bool Option) { ReorderFunctions = Option; }
bool shouldReorderFunctions() const { return ReorderFunctions; }
void setReorderFunctionsWindowSize(uint32_t Size) {
ReorderFunctionsWindowSize = Size;
}
uint32_t getReorderFunctionsWindowSize() const {
return ReorderFunctionsWindowSize;
}
void setShouldReorderGlobalVariables(bool Option) {
ReorderGlobalVariables = Option;
}
bool shouldReorderGlobalVariables() const { return ReorderGlobalVariables; }
void setShouldReorderPooledConstants(bool Option) {
ReorderPooledConstants = Option;
}
bool shouldReorderPooledConstants() const { return ReorderPooledConstants; }
// IceString accessors. // IceString accessors.
const IceString &getDefaultFunctionPrefix() const { const IceString &getDefaultFunctionPrefix() const {
...@@ -209,6 +228,9 @@ private: ...@@ -209,6 +228,9 @@ private:
bool PhiEdgeSplit; bool PhiEdgeSplit;
bool RandomNopInsertion; bool RandomNopInsertion;
bool RandomRegAlloc; bool RandomRegAlloc;
bool ReorderFunctions;
bool ReorderGlobalVariables;
bool ReorderPooledConstants;
bool SkipUnimplemented; bool SkipUnimplemented;
bool SubzeroTimingEnabled; bool SubzeroTimingEnabled;
bool TimeEachFunction; bool TimeEachFunction;
...@@ -216,8 +238,11 @@ private: ...@@ -216,8 +238,11 @@ private:
OptLevel Opt; OptLevel Opt;
FileType OutFileType; FileType OutFileType;
RandomizeAndPoolImmediatesEnum RandomizeAndPoolImmediatesOption;
uint32_t RandomizeAndPoolImmediatesThreshold;
int RandomMaxNopsPerInstruction; int RandomMaxNopsPerInstruction;
int RandomNopProbabilityAsPercentage; int RandomNopProbabilityAsPercentage;
uint32_t ReorderFunctionsWindowSize;
TargetArch TArch; TargetArch TArch;
TargetInstructionSet TInstrSet; TargetInstructionSet TInstrSet;
VerboseMask VMask; VerboseMask VMask;
...@@ -229,10 +254,6 @@ private: ...@@ -229,10 +254,6 @@ private:
IceString TranslateOnly; IceString TranslateOnly;
IceString VerboseFocusOn; IceString VerboseFocusOn;
// Immediates Randomization and Pooling options
RandomizeAndPoolImmediatesEnum RandomizeAndPoolImmediatesOption;
uint32_t RandomizeAndPoolImmediatesThreshold;
size_t NumTranslationThreads; // 0 means completely sequential size_t NumTranslationThreads; // 0 means completely sequential
uint64_t RandomSeed; uint64_t RandomSeed;
}; };
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
// TODO(kschimpf): Remove two namespaces being visible at once. // TODO(kschimpf): Remove two namespaces being visible at once.
using namespace llvm; using namespace llvm;
......
...@@ -390,7 +390,7 @@ void ELFObjectWriter::writeDataOfType(SectionType ST, ...@@ -390,7 +390,7 @@ void ELFObjectWriter::writeDataOfType(SectionType ST,
Var->getInitializers()) { Var->getInitializers()) {
switch (Init->getKind()) { switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: { case VariableDeclaration::Initializer::DataInitializerKind: {
const auto Data = const auto &Data =
llvm::cast<VariableDeclaration::DataInitializer>(Init.get()) llvm::cast<VariableDeclaration::DataInitializer>(Init.get())
->getContents(); ->getContents();
Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); Section->appendData(Str, llvm::StringRef(Data.data(), Data.size()));
...@@ -508,6 +508,13 @@ template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { ...@@ -508,6 +508,13 @@ template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
const SizeT SymbolSize = 0; const SizeT SymbolSize = 0;
Section->setFileOffset(alignFileOffset(Align)); Section->setFileOffset(alignFileOffset(Align));
// If the -reorder-pooled-constant option is set to true, we should shuffle
// the constants before we emit them.
auto *CtxPtr = &Ctx;
if (Ctx.getFlags().shouldReorderPooledConstants())
RandomShuffle(Pool.begin(), Pool.end(), [CtxPtr](uint64_t N) {
return (uint32_t)CtxPtr->getRNG().next(N);
});
// Write the data. // Write the data.
for (Constant *C : Pool) { for (Constant *C : Pool) {
if (!C->getShouldBePooled()) if (!C->getShouldBePooled())
......
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
#include "IceTypes.h" #include "IceTypes.h"
#include "llvm/Support/Timer.h" #include "llvm/Support/Timer.h"
#include <ctype.h> // isdigit(), isupper() #include <algorithm> // max()
#include <cctype> // isdigit(), isupper()
#include <locale> // locale #include <locale> // locale
#include <unordered_map> #include <unordered_map>
namespace std { namespace std {
template <> struct hash<Ice::RelocatableTuple> { template <> struct hash<Ice::RelocatableTuple> {
size_t operator()(const Ice::RelocatableTuple &Key) const { size_t operator()(const Ice::RelocatableTuple &Key) const {
...@@ -395,6 +395,12 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) { ...@@ -395,6 +395,12 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
return; return;
addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl); addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl);
// If we need to shuffle the layout of global variables, shuffle them now.
if (getFlags().shouldReorderGlobalVariables()) {
auto *RNGPtr = &RNG;
RandomShuffle(Globals.begin(), Globals.end(),
[RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); });
}
DataLowering->lowerGlobals(Globals, SectionSuffix); DataLowering->lowerGlobals(Globals, SectionSuffix);
for (VariableDeclaration *Var : Globals) { for (VariableDeclaration *Var : Globals) {
Var->discardInitializers(); Var->discardInitializers();
...@@ -428,68 +434,118 @@ void GlobalContext::emitItems() { ...@@ -428,68 +434,118 @@ void GlobalContext::emitItems() {
// after it is processed. // after it is processed.
std::vector<EmitterWorkItem *> Pending; std::vector<EmitterWorkItem *> Pending;
uint32_t DesiredSequenceNumber = getFirstSequenceNumber(); uint32_t DesiredSequenceNumber = getFirstSequenceNumber();
while (true) { uint32_t ShuffleStartIndex = DesiredSequenceNumber;
uint32_t ShuffleEndIndex = DesiredSequenceNumber;
bool EmitQueueEmpty = false;
const uint32_t ShuffleWindowSize =
std::max(1u, getFlags().getReorderFunctionsWindowSize());
bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
while (!EmitQueueEmpty) {
resizePending(Pending, DesiredSequenceNumber); resizePending(Pending, DesiredSequenceNumber);
// See if Pending contains DesiredSequenceNumber. // See if Pending contains DesiredSequenceNumber.
EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber]; EmitterWorkItem *RawItem = Pending[DesiredSequenceNumber];
if (RawItem == nullptr) if (RawItem == nullptr) {
// We need to fetch an EmitterWorkItem from the queue.
RawItem = emitQueueBlockingPop(); RawItem = emitQueueBlockingPop();
if (RawItem == nullptr) if (RawItem == nullptr) {
break; // This is the notifier for an empty queue.
uint32_t ItemSeq = RawItem->getSequenceNumber(); EmitQueueEmpty = true;
if (Threaded && ItemSeq != DesiredSequenceNumber) { } else {
resizePending(Pending, ItemSeq); // We get an EmitterWorkItem, we need to add it to Pending.
Pending[ItemSeq] = RawItem; uint32_t ItemSeq = RawItem->getSequenceNumber();
continue; if (Threaded && ItemSeq != DesiredSequenceNumber) {
// Not the desired one, add it to Pending but do not increase
// DesiredSequenceNumber. Continue the loop, do not emit the item.
resizePending(Pending, ItemSeq);
Pending[ItemSeq] = RawItem;
continue;
}
// ItemSeq == DesiredSequenceNumber, we need to check if we should
// emit it or not. If !Threaded, we're OK with ItemSeq !=
// DesiredSequenceNumber.
Pending[DesiredSequenceNumber] = RawItem;
}
}
// We have the desired EmitterWorkItem or nullptr as the end notifier.
// If the emitter queue is not empty, increase DesiredSequenceNumber and
// ShuffleEndIndex.
if (!EmitQueueEmpty) {
DesiredSequenceNumber++;
ShuffleEndIndex++;
} }
std::unique_ptr<EmitterWorkItem> Item(RawItem); if (Shuffle) {
++DesiredSequenceNumber; // Continue fetching EmitterWorkItem if function reordering is turned on,
switch (Item->getKind()) { // and emit queue is not empty, and the number of consecutive pending
case EmitterWorkItem::WI_Nop: // items is smaller than the window size, and RawItem is not a
break; // WI_GlobalInits kind. Emit WI_GlobalInits kind block first to avoid
case EmitterWorkItem::WI_GlobalInits: { // holding an arbitrarily large GlobalDeclarationList.
accumulateGlobals(Item->getGlobalInits()); if (!EmitQueueEmpty &&
} break; ShuffleEndIndex - ShuffleStartIndex < ShuffleWindowSize &&
case EmitterWorkItem::WI_Asm: { RawItem->getKind() != EmitterWorkItem::WI_GlobalInits)
lowerGlobalsIfNoCodeHasBeenSeen(); continue;
accumulateGlobals(Item->getGlobalInits());
// Emit the EmitterWorkItem between Pending[ShuffleStartIndex] to
std::unique_ptr<Assembler> Asm = Item->getAsm(); // Pending[ShuffleEndIndex]. If function reordering turned on, shuffle the
Asm->alignFunction(); // pending items from Pending[ShuffleStartIndex] to
IceString MangledName = mangleName(Asm->getFunctionName()); // Pending[ShuffleEndIndex].
switch (getFlags().getOutFileType()) { RandomShuffle(Pending.begin() + ShuffleStartIndex,
case FT_Elf: Pending.begin() + ShuffleEndIndex,
getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(), [this](uint64_t N) { return (uint32_t)RNG.next(N); });
Asm.get()); }
// Emit the item from ShuffleStartIndex to ShuffleEndIndex.
for (uint32_t I = ShuffleStartIndex; I < ShuffleEndIndex; I++) {
std::unique_ptr<EmitterWorkItem> Item(Pending[I]);
switch (Item->getKind()) {
case EmitterWorkItem::WI_Nop:
break; break;
case FT_Iasm: { case EmitterWorkItem::WI_GlobalInits: {
OstreamLocker L(this); accumulateGlobals(Item->getGlobalInits());
Cfg::emitTextHeader(MangledName, this, Asm.get()); } break;
Asm->emitIASBytes(this); case EmitterWorkItem::WI_Asm: {
lowerGlobalsIfNoCodeHasBeenSeen();
accumulateGlobals(Item->getGlobalInits());
std::unique_ptr<Assembler> Asm = Item->getAsm();
Asm->alignFunction();
IceString MangledName = mangleName(Asm->getFunctionName());
switch (getFlags().getOutFileType()) {
case FT_Elf:
getObjectWriter()->writeFunctionCode(MangledName, Asm->getInternal(),
Asm.get());
break;
case FT_Iasm: {
OstreamLocker L(this);
Cfg::emitTextHeader(MangledName, this, Asm.get());
Asm->emitIASBytes(this);
} break;
case FT_Asm:
llvm::report_fatal_error("Unexpected FT_Asm");
break;
}
} break;
case EmitterWorkItem::WI_Cfg: {
if (!BuildDefs::dump())
llvm::report_fatal_error("WI_Cfg work item created inappropriately");
lowerGlobalsIfNoCodeHasBeenSeen();
accumulateGlobals(Item->getGlobalInits());
assert(getFlags().getOutFileType() == FT_Asm);
std::unique_ptr<Cfg> Func = Item->getCfg();
// Unfortunately, we have to temporarily install the Cfg in TLS
// because Variable::asType() uses the allocator to create the
// differently-typed copy.
Cfg::setCurrentCfg(Func.get());
Func->emit();
Cfg::setCurrentCfg(nullptr);
dumpStats(Func->getFunctionName());
} break; } break;
case FT_Asm:
llvm::report_fatal_error("Unexpected FT_Asm");
break;
} }
} break;
case EmitterWorkItem::WI_Cfg: {
if (!BuildDefs::dump())
llvm::report_fatal_error("WI_Cfg work item created inappropriately");
lowerGlobalsIfNoCodeHasBeenSeen();
accumulateGlobals(Item->getGlobalInits());
assert(getFlags().getOutFileType() == FT_Asm);
std::unique_ptr<Cfg> Func = Item->getCfg();
// Unfortunately, we have to temporarily install the Cfg in TLS
// because Variable::asType() uses the allocator to create the
// differently-typed copy.
Cfg::setCurrentCfg(Func.get());
Func->emit();
Cfg::setCurrentCfg(nullptr);
dumpStats(Func->getFunctionName());
} break;
} }
// Update the start index for next shuffling queue
ShuffleStartIndex = ShuffleEndIndex;
} }
// In case there are no code to be generated, we invoke the conditional // In case there are no code to be generated, we invoke the conditional
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/Value.h" #include "llvm/IR/Value.h"
namespace { namespace {
char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; } char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; }
......
...@@ -239,6 +239,14 @@ void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { ...@@ -239,6 +239,14 @@ void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
<< "\n"; << "\n";
Str << "\t.align\t" << Align << "\n"; Str << "\t.align\t" << Align << "\n";
// If reorder-pooled-constants option is set to true, we need to shuffle the
// constant pool before emitting it.
if (Ctx->getFlags().shouldReorderPooledConstants())
RandomShuffle(Pool.begin(), Pool.end(), [Ctx](uint64_t N) {
return (uint32_t)Ctx->getRNG().next(N);
});
for (Constant *C : Pool) { for (Constant *C : Pool) {
if (!C->getShouldBePooled()) if (!C->getShouldBePooled())
continue; continue;
......
...@@ -444,7 +444,6 @@ template <class Machine> void TargetX86Base<Machine>::translateOm1() { ...@@ -444,7 +444,6 @@ template <class Machine> void TargetX86Base<Machine>::translateOm1() {
Func->dump("After Phi lowering"); Func->dump("After Phi lowering");
Func->doArgLowering(); Func->doArgLowering();
Func->genCode(); Func->genCode();
if (Func->hasError()) if (Func->hasError())
return; return;
......
; This is a smoke test of function reordering.
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: | FileCheck %s --check-prefix=DEFAULTWINDOWSIZE
; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: | FileCheck %s --check-prefix=DEFAULTWINDOWSIZE
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -reorder-functions-window-size=1 \
; RUN: | FileCheck %s --check-prefix=WINDOWSIZE1
; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -reorder-functions-window-size=1 \
; RUN: | FileCheck %s --check-prefix=WINDOWSIZE1
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -threads=0 \
; RUN: | FileCheck %s --check-prefix=SEQUENTIAL
; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -threads=0 \
; RUN: | FileCheck %s --check-prefix=SEQUENTIAL
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -reorder-functions-window-size=0xffffffff \
; RUN: | FileCheck %s --check-prefix=WINDOWSIZEMAX
; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
; RUN: -sz-seed=1 -reorder-functions \
; RUN: -reorder-functions-window-size=0xffffffff \
; RUN: | FileCheck %s --check-prefix=WINDOWSIZEMAX
define void @func1() {
ret void
}
define void @func2() {
ret void
}
define void @func3() {
ret void
}
define void @func4() {
ret void
}
define void @func5() {
ret void
}
define void @func6() {
ret void
}
; DEFAULTWINDOWSIZE-LABEL: func4
; DEFAULTWINDOWSIZE-LABEL: func1
; DEFAULTWINDOWSIZE-LABEL: func3
; DEFAULTWINDOWSIZE-LABEL: func6
; DEFAULTWINDOWSIZE-LABEL: func5
; DEFAULTWINDOWSIZE-LABEL: func2
; WINDOWSIZE1-LABEL: func1
; WINDOWSIZE1-LABEL: func2
; WINDOWSIZE1-LABEL: func3
; WINDOWSIZE1-LABEL: func4
; WINDOWSIZE1-LABEL: func5
; WINDOWSIZE1-LABEL: func6
; SEQUENTIAL-LABEL: func1
; SEQUENTIAL-LABEL: func2
; SEQUENTIAL-LABEL: func3
; SEQUENTIAL-LABEL: func4
; SEQUENTIAL-LABEL: func5
; SEQUENTIAL-LABEL: func6
; WINDOWSIZEMAX-LABEL: func4
; WINDOWSIZEMAX-LABEL: func1
; WINDOWSIZEMAX-LABEL: func3
; WINDOWSIZEMAX-LABEL: func6
; WINDOWSIZEMAX-LABEL: func5
; WINDOWSIZEMAX-LABEL: func2
; Test of global variable reordering.
; REQUIRES: allow_dump
; Test x8632 asm output
; RUN: %if --need=target_X8632 --command %p2i --filetype=asm --target x8632 \
; RUN: -i %s --assemble --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables -O2 \
; RUN: | %if --need=target_X8632 --command FileCheck %s
; RUN: %if --need=target_X8632 --command %p2i --filetype=asm --target x8632 \
; RUN: -i %s --assemble --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables -Om1 \
; RUN: | %if --need=target_X8632 --command FileCheck %s
; Test x8632 elf output
; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --target x8632 \
; RUN: -i %s --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables -O2 \
; RUN: | %if --need=target_X8632 --command FileCheck %s
; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --target x8632 \
; RUN: -i %s --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables -Om1 \
; RUN: | %if --need=target_X8632 --command FileCheck %s
; Test arm output
; IAS is not implemented yet.
; RUN: %if --need=target_ARM32 --command %p2i --filetype=asm --target arm32 \
; RUN: -i %s --assemble --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables \
; RUN: --skip-unimplemented -O2 \
; RUN: | %if --need=target_ARM32 --command FileCheck %s
; RUN: %if --need=target_ARM32 --command %p2i --filetype=asm --target arm32 \
; RUN: -i %s --assemble --disassemble --dis-flags=-rD \
; RUN: --args -sz-seed=1 -reorder-global-variables \
; RUN: --skip-unimplemented -Om1 \
; RUN: | %if --need=target_ARM32 --command FileCheck %s
@PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
@PrimitiveInitConst = internal constant [4 x i8] c"\0D\00\00\00", align 4
@ArrayInit = internal global [20 x i8] c"\0A\00\00\00\14\00\00\00\1E\00\00\00(\00\00\002\00\00\00", align 4
@ArrayInitPartial = internal global [40 x i8] c"<\00\00\00F\00\00\00P\00\00\00Z\00\00\00d\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 4
@PrimitiveInitStatic = internal global [4 x i8] zeroinitializer, align 4
@PrimitiveUninit = internal global [4 x i8] zeroinitializer, align 4
@ArrayUninit = internal global [20 x i8] zeroinitializer, align 4
@ArrayUninitConstDouble = internal constant [200 x i8] zeroinitializer, align 8
@ArrayUninitConstInt = internal constant [20 x i8] zeroinitializer, align 4
;@__init_array_start = internal constant [0 x i8] zeroinitializer, align 4
;@__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
;@__tls_template_start = internal constant [0 x i8] zeroinitializer, align 8
;@__tls_template_alignment = internal constant [4 x i8] c"\01\00\00\00", align 4
; Make sure the shuffled order is correct.
; CHECK-LABEL: ArrayInitPartial
; CHECK-LABEL: PrimitiveInit
; CHECK-LABEL: ArrayInit
; CHECK-LABEL: PrimitiveUninit
; CHECK-LABEL: ArrayUninit
; CHECK-LABEL: PrimitiveInitStatic
; CHECK-LABEL: ArrayUninitConstDouble
; CHECK-LABEL: ArrayUninitConstInt
; CHECK-LABEL: PrimitiveInitConst
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment