Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: lib/Transforms/MinSFI/AllocateDataSegment.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/Transforms/Makefile ('k') | lib/Transforms/MinSFI/CMakeLists.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Transforms/MinSFI/AllocateDataSegment.cpp
diff --git a/lib/Transforms/MinSFI/AllocateDataSegment.cpp b/lib/Transforms/MinSFI/AllocateDataSegment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8212df0c39024f1338d614c9c356066101ae3279
--- /dev/null
+++ b/lib/Transforms/MinSFI/AllocateDataSegment.cpp
@@ -0,0 +1,134 @@
+//===- AllocateDataSegment.cpp - Create a template for the data segment ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Code sandboxed with MinSFI cannot access the memory containing its data
+// segment directly because it is located outside its address subspace. To
+// this end, this pass collates all of the global variables in the module
+// into an exported global struct named "__sfi_data_segment" and a corresponding
+// global integer holding the overall size. The runtime is expected to link
+// against these variables and to initialize the memory region of the sandbox
+// by copying the data segment template into a fixed address inside the region.
+//
+// This pass assumes that the base of the memory region of the sandbox is
+// aligned to at least 2^29 bytes (=512MB), which is the maximum global variable
+// alignment supported by LLVM.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Pass.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Transforms/MinSFI.h"
+
+using namespace llvm;
+
+static const char ExternalSymName_DataSegment[] = "__sfi_data_segment";
+static const char ExternalSymName_DataSegmentSize[] = "__sfi_data_segment_size";
+
+static const uint32_t DataSegmentBaseAddress = 0x10000;
+
+namespace {
+class AllocateDataSegment : public ModulePass {
+ public:
+ static char ID;
+ AllocateDataSegment() : ModulePass(ID) {
+ initializeAllocateDataSegmentPass(*PassRegistry::getPassRegistry());
+ }
+
+ virtual bool runOnModule(Module &M);
+};
+} // namespace
+
+static inline uint32_t getPadding(uint32_t Offset, const GlobalVariable *GV,
+ const DataLayout &DL) {
+ uint32_t Alignment = DL.getPreferredAlignment(GV);
+ if (Alignment <= 1)
+ return 0;
+ else
+ return OffsetToAlignment(Offset, Alignment);
+}
+
+bool AllocateDataSegment::runOnModule(Module &M) {
+ DataLayout DL(&M);
+ Type *I8 = Type::getInt8Ty(M.getContext());
+ Type *I32 = Type::getInt32Ty(M.getContext());
+ Type *IntPtrType = DL.getIntPtrType(M.getContext());
+
+ // First, we do a pass over the global variables, in which we compute
+ // the amount of required padding between them and consequently their
+ // addresses relative to the memory base of the sandbox. References to each
+ // global are then replaced with direct memory pointers.
+ uint32_t VarOffset = 0;
+ DenseMap<GlobalVariable*, uint32_t> VarPadding;
+ for (Module::global_iterator GV = M.global_begin(), E = M.global_end();
+ GV != E; ++GV) {
+ assert(GV->hasInitializer());
+
+ uint32_t Padding = getPadding(VarOffset, GV, DL);
+ VarPadding[GV] = Padding;
+ VarOffset += Padding;
+
+ GV->replaceAllUsesWith(
+ ConstantExpr::getIntToPtr(
+ ConstantInt::get(IntPtrType,
+ DataSegmentBaseAddress + VarOffset),
+ GV->getType()));
+
+ VarOffset += DL.getTypeStoreSize(GV->getType()->getPointerElementType());
+ }
+
+ // Using the offsets computed above, we prepare the layout and the contents
+ // of the desired data structure. After the type and initializer of each
+ // global is copied, the global is not needed any more and it is erased.
+ SmallVector<Type*, 10> TemplateLayout;
+ SmallVector<Constant*, 10> TemplateData;
+ for (Module::global_iterator It = M.global_begin(), E = M.global_end();
+ It != E; ) {
+ GlobalVariable *GV = It++;
+
+ uint32_t Padding = VarPadding[GV];
+ if (Padding > 0) {
+ Type *PaddingType = ArrayType::get(I8, Padding);
+ TemplateLayout.push_back(PaddingType);
+ TemplateData.push_back(ConstantAggregateZero::get(PaddingType));
+ }
+
+ TemplateLayout.push_back(GV->getType()->getPointerElementType());
+ TemplateData.push_back(GV->getInitializer());
+
+ GV->eraseFromParent();
+ }
+
+ // Finally, we create the struct and size global variables.
+ StructType *TemplateType =
+ StructType::create(M.getContext(), ExternalSymName_DataSegment);
+ TemplateType->setBody(TemplateLayout, /*isPacked=*/true);
+
+ Constant *Template = ConstantStruct::get(TemplateType, TemplateData);
+ new GlobalVariable(M, Template->getType(), /*isConstant=*/true,
+ GlobalVariable::ExternalLinkage, Template,
+ ExternalSymName_DataSegment);
+
+ Constant *TemplateSize =
+ ConstantInt::get(I32, DL.getTypeAllocSize(TemplateType));
+ new GlobalVariable(M, TemplateSize->getType(), /*isConstant=*/true,
+ GlobalVariable::ExternalLinkage, TemplateSize,
+ ExternalSymName_DataSegmentSize);
+
+ return true;
+}
+
+char AllocateDataSegment::ID = 0;
+INITIALIZE_PASS(AllocateDataSegment, "minsfi-allocate-data-segment",
+ "Create a template for the data segment", false, false)
+
+ModulePass *llvm::createAllocateDataSegmentPass() {
+ return new AllocateDataSegment();
+}
« no previous file with comments | « lib/Transforms/Makefile ('k') | lib/Transforms/MinSFI/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698