Prepare stack for the translated program

* Create 3 constant global variables (`phdr_address`, `e_phentsize` and
  `e_phnum`) in the IR which will be used to populate the auxiliary
  vectors at run-time.
* Update compile options for `support.c` to ignore useless warnings and
  enable debug information
* Implement in `support.c` some functions required by QEMU run-time and
  other cleanups to make it compatible with programs translated from
  `_start`, not `root`
* Implement in `support.c` the `prepare_stack` function, which
  initializes the base of the stack with environment variables,
  arguments and auxiliary vectors
* Improve syscall support
This commit is contained in:
Alessandro Di Federico
2016-01-30 11:07:47 +01:00
parent e59edd4109
commit 32b756510f
3 changed files with 190 additions and 32 deletions
+33 -10
View File
@@ -80,11 +80,6 @@ CodeGenerator::CodeGenerator(std::string Input,
BinaryHandle = std::move(BinaryOrErr.get());
// Provide an abort declaration
TheModule->getOrInsertFunction("abort",
FunctionType::get(Type::getVoidTy(Context),
false));
// We only support ELF for now
auto *TheBinary = cast<object::ObjectFile>(BinaryHandle.getBinary());
@@ -148,6 +143,23 @@ void CodeGenerator::parseELF(object::ObjectFile *TheBinary,
ElfHeaderHelper->setAlignment(1);
ElfHeaderHelper->setSection(".elfheaderhelper");
auto *RegisterType = Type::getIntNTy(Context, T::Is64Bits ? 64 : 32);
auto createConstGlobal = [this, &RegisterType] (const Twine &Name,
uint64_t Value) {
return new GlobalVariable(*TheModule,
RegisterType,
true,
GlobalValue::ExternalLinkage,
ConstantInt::get(RegisterType, Value),
Name);
};
// These values will be used to populate the auxiliary vectors
auto PhdrAddress = reinterpret_cast<uint64_t>(TheELF.base()
+ ElfHeader->e_phoff);
createConstGlobal("phdr_address", PhdrAddress);
createConstGlobal("e_phentsize", ElfHeader->e_phentsize);
createConstGlobal("e_phnum", ElfHeader->e_phnum);
// Loop over the program headers looking for PT_LOAD segments, read them out
// and create a global variable for each one of them (writable or read-only),
@@ -521,6 +533,21 @@ bool CpuLoopExitPass::runOnModule(llvm::Module& M) {
void CodeGenerator::translate(uint64_t VirtualAddress,
std::string Name) {
// Declare useful functions
TheModule->getOrInsertFunction("abort",
FunctionType::get(Type::getVoidTy(Context),
false));
auto *TargetSetBrkFunction = HelpersModule->getFunction("target_set_brk");
TheModule->getOrInsertFunction("target_set_brk",
TargetSetBrkFunction->getFunctionType());
Function *CpuLoop = HelpersModule->getFunction("cpu_loop");
assert(CpuLoop != nullptr);
TheModule->getOrInsertFunction("cpu_loop", CpuLoop->getFunctionType());
TheModule->getOrInsertFunction("syscall_init",
FunctionType::get(Type::getVoidTy(Context),
{ },
false));
IRBuilder<> Builder(Context);
if (VirtualAddress == 0)
@@ -676,16 +703,11 @@ void CodeGenerator::translate(uint64_t VirtualAddress,
std::tie(VirtualAddress, Entry) = JumpTargets.peek();
} // End translations loop
Function *CpuLoop = HelpersModule->getFunction("cpu_loop");
assert(CpuLoop != nullptr);
legacy::FunctionPassManager CpuLoopPM(TheModule.get());
CpuLoopPM.add(new LoopInfoWrapperPass());
CpuLoopPM.add(new CpuLoopFunctionPass());
CpuLoopPM.run(*CpuLoop);
// Force linking of cpu_loop
TheModule->getOrInsertFunction("cpu_loop", CpuLoop->getFunctionType());
// CpuLoopFunctionPass expects a variable name exception_index to exist
Variables.getByEnvOffset(ptc.exception_index, "exception_index");
@@ -711,6 +733,7 @@ void CodeGenerator::translate(uint64_t VirtualAddress,
// syscall.c
"print_syscall",
"print_syscall_ret",
"do_ioctl_dm",
// ARM cpu_loop
"EmulateAll",
"cpu_abort",