static void call_constructors(unsigned long *start, unsigned long *end) { unsigned long *i; void (*funcptr)(); for ( i = start; i < end; i++) { funcptr=(void (*)())(*i); funcptr(); } }
/* * call ( ... function-ptr -- ??? ) */ static void call(void) { #ifdef FCOMPILER printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n"); exit(1); #else void (*funcptr) (void); funcptr=(void *)cell2pointer(POP()); dbg_interp_printk("call: %x", funcptr); funcptr(); #endif }
static void call_constructors(unsigned long *start, unsigned long *end) { unsigned long *i; void (*funcptr)(); for ( i = start; i < end; i++) { debug_print("call constr:"); debug_printhex_int32((int)i);dln; funcptr=(void (*)())(*i); funcptr(); } }
Result load_hblauncher() { Result ret = 0; u8 region=0; u8 new3dsflag = 0; OS_VersionBin nver_versionbin; OS_VersionBin cver_versionbin; u32 payloadsize = 0, payloadsize_aligned = 0; u32 payload_src = 0; char payload_sysver[32]; char payloadurl[0x80]; char payload_sdpath[0x80]; void (*funcptr)(u32*, u32*) = NULL; u32 *paramblk = NULL; memset(&nver_versionbin, 0, sizeof(OS_VersionBin)); memset(&cver_versionbin, 0, sizeof(OS_VersionBin)); memset(payload_sysver, 0, sizeof(payload_sysver)); memset(payloadurl, 0, sizeof(payloadurl)); memset(payload_sdpath, 0, sizeof(payload_sdpath)); printf("Getting system-version/system-info etc...\n"); ret = cfguInit(); if(ret!=0) { printf("Failed to init cfgu: 0x%08x.\n", (unsigned int)ret); return ret; } ret = CFGU_SecureInfoGetRegion(®ion); if(ret!=0) { printf("Failed to get region from cfgu: 0x%08x.\n", (unsigned int)ret); return ret; } if(region>=7) { printf("Region value from cfgu is invalid: 0x%02x.\n", (unsigned int)region); ret = -9; return ret; } cfguExit(); APT_CheckNew3DS(&new3dsflag); ret = osGetSystemVersionData(&nver_versionbin, &cver_versionbin); if(ret!=0) { printf("Failed to load the system-version: 0x%08x.\n", (unsigned int)ret); return ret; } snprintf(payload_sysver, sizeof(payload_sysver)-1, "%s-%d-%d-%d-%d-%s", new3dsflag?"NEW":"OLD", cver_versionbin.mainver, cver_versionbin.minor, cver_versionbin.build, nver_versionbin.mainver, regionids_table[region]); snprintf(payloadurl, sizeof(payloadurl)-1, "http://smea.mtheall.com/get_payload.php?version=%s", payload_sysver); snprintf(payload_sdpath, sizeof(payload_sdpath)-1, "sdmc:/hblauncherloader_otherapp_payload_%s.bin", payload_sysver); printf("Detected system-version: %s %d.%d.%d-%d %s\n", new3dsflag?"New3DS":"Old3DS", cver_versionbin.mainver, cver_versionbin.minor, cver_versionbin.build, nver_versionbin.mainver, regionids_table[region]); memset(filebuffer, 0, filebuffer_maxsize); hidScanInput(); if((hidKeysHeld() & KEY_X) == 0) { printf("Since the X button isn't pressed, this will now check for the otherapp payload on SD, with the following filepath: %s\n", payload_sdpath); ret = loadsd_payload(payload_sdpath, &payloadsize); } else { printf("Skipping SD payload load-attempt since the X button is pressed.\n"); ret = 1; } if(ret==0) { printf("The otherapp payload for this app already exists on SD, that will be used instead of downloading the payload via HTTP.\n"); payload_src = 0; } else { printf("Requesting the actual payload URL with HTTP...\n"); ret = http_getactual_payloadurl(payloadurl, payloadurl, sizeof(payloadurl)); if(ret!=0) { printf("Failed to request the actual payload URL: 0x%08x.\n", (unsigned int)ret); printf("If the server isn't down, and the HTTP request was actually done, this may mean your system-version or region isn't supported by the hblauncher-payload currently.\n"); return ret; } printf("Downloading the actual payload with HTTP...\n"); ret = http_download_payload(payloadurl, &payloadsize); if(ret!=0) { printf("Failed to download the actual payload with HTTP: 0x%08x.\n", (unsigned int)ret); printf("If the server isn't down, and the HTTP request was actually done, this may mean your system-version or region isn't supported by the hblauncher-payload currently.\n"); return ret; } if(ret==0)payload_src = 1; } printf("Initializing payload data etc...\n"); payloadsize_aligned = (payloadsize + 0xfff) & ~0xfff; if(payloadsize_aligned > PAYLOAD_TEXTMAXSIZE) { printf("Invalid payload size: 0x%08x.\n", (unsigned int)payloadsize); ret = -3; return ret; } if(payload_src) { hidScanInput(); if(hidKeysHeld() & KEY_Y) { printf("Saving the downloaded payload to SD since the Y button is pressed...\n"); ret = savesd_payload(payload_sdpath, payloadsize); if(ret!=0) { printf("Payload saving failed: 0x%08x.\n", (unsigned int)ret); } else { printf("Payload saving was successful.\n"); } } else { printf("Skipping saving the downloaded payload to SD since the Y button isn't pressed.\n"); } } memcpy(PAYLOAD_TEXTADDR, filebuffer, payloadsize_aligned); memset(filebuffer, 0, filebuffer_maxsize); ret = svcFlushProcessDataCache(0xffff8001, PAYLOAD_TEXTADDR, payloadsize_aligned);//Flush dcache for the payload which was copied into .text. Since that area was never executed, icache shouldn't be an issue. if(ret!=0) { printf("svcFlushProcessDataCache failed: 0x%08x.\n", (unsigned int)ret); return ret; } paramblk = linearMemAlign(0x10000, 0x1000); if(paramblk==NULL) { ret = 0xfe; printf("Failed to alloc the paramblk.\n"); return ret; } httpcExit(); memset(paramblk, 0, 0x10000); paramblk[0x1c>>2] = (u32)gxlowcmd_4; paramblk[0x20>>2] = (u32)gsp_flushdcache; paramblk[0x48>>2] = 0x8d;//flags paramblk[0x58>>2] = (u32)&gspGpuHandle; printf("Jumping into the payload...\n"); funcptr = (void*)PAYLOAD_TEXTADDR; funcptr(paramblk, (u32*)(0x10000000-0x1000)); ret = 0xff; printf("The payload returned back into the app, this should *never* happen with the actual hblauncher-payload.\n"); return ret; }
node *func (node* (*fn)(node*, node*), enum ltype type) { node *ptr = newnode(type); funcptr(ptr) = fn; return ptr; }
int test1() { // Get global context - not sure what the impact is of sharing // the global context llvm::LLVMContext &context = llvm::getGlobalContext(); // Module is the translation unit std::unique_ptr<llvm::Module> theModule = std::unique_ptr<llvm::Module>(new llvm::Module("ravi", context)); llvm::Module *module = theModule.get(); llvm::IRBuilder<> builder(context); #if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MINOR < 7) // On Windows we get error saying incompatible object format // Reading posts on mailining lists I found that the issue is that COEFF // format is not supported and therefore we need to set -elf as the object // format auto triple = llvm::sys::getProcessTriple(); // module->setTargetTriple("x86_64-pc-win32-elf"); module->setTargetTriple(triple + "-elf"); #endif // create a GCObject structure as defined in lobject.h llvm::StructType *structType = llvm::StructType::create(context, "RaviGCObject"); llvm::PointerType *pstructType = llvm::PointerType::get(structType, 0); // pointer to RaviGCObject std::vector<llvm::Type *> elements; elements.push_back(pstructType); elements.push_back(llvm::Type::getInt8Ty(context)); elements.push_back(llvm::Type::getInt8Ty(context)); structType->setBody(elements); structType->dump(); // Create printf declaration std::vector<llvm::Type *> args; args.push_back(llvm::Type::getInt8PtrTy(context)); // accepts a char*, is vararg, and returns int llvm::FunctionType *printfType = llvm::FunctionType::get(builder.getInt32Ty(), args, true); llvm::Constant *printfFunc = module->getOrInsertFunction("printf", printfType); // Create the testfunc() args.clear(); args.push_back(pstructType); llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getInt32Ty(), args, false); llvm::Function *mainFunc = llvm::Function::Create( funcType, llvm::Function::ExternalLinkage, "testfunc", module); llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunc); builder.SetInsertPoint(entry); // printf format string llvm::Value *formatStr = builder.CreateGlobalStringPtr("value = %d\n"); // Get the first argument which is RaviGCObject * auto argiter = mainFunc->arg_begin(); llvm::Value *arg1 = argiter++; arg1->setName("obj"); // Now we need a GEP for the second field in RaviGCObject std::vector<llvm::Value *> values; llvm::APInt zero(32, 0); llvm::APInt one(32, 1); // This is the array offset into RaviGCObject* values.push_back( llvm::Constant::getIntegerValue(llvm::Type::getInt32Ty(context), zero)); // This is the field offset values.push_back( llvm::Constant::getIntegerValue(llvm::Type::getInt32Ty(context), one)); // Create the GEP value llvm::Value *arg1_a = builder.CreateGEP(arg1, values, "ptr"); // Now retrieve the data from the pointer address llvm::Value *tmp1 = builder.CreateLoad(arg1_a, "a"); // As the retrieved value is a byte - convert to int i llvm::Value *tmp2 = builder.CreateZExt(tmp1, llvm::Type::getInt32Ty(context), "i"); // Call the printf function values.clear(); values.push_back(formatStr); values.push_back(tmp2); builder.CreateCall(printfFunc, values); // return i builder.CreateRet(tmp2); module->dump(); // Lets create the MCJIT engine std::string errStr; #if LLVM_VERSION_MINOR > 5 std::unique_ptr<llvm::Module> module_(module); auto engine = llvm::EngineBuilder(std::move(module_)) .setErrorStr(&errStr) .setEngineKind(llvm::EngineKind::JIT) .create(); #else auto engine = llvm::EngineBuilder(module) .setErrorStr(&errStr) .setEngineKind(llvm::EngineKind::JIT) .setUseMCJIT(true) .create(); #endif if (!engine) { std::cerr << "Failed to construct MCJIT ExecutionEngine: " << errStr << "\n"; return 1; } // Now lets compile our function into machine code std::string funcname = "testfunc"; myfunc_t funcptr = (myfunc_t)engine->getFunctionAddress(funcname); if (funcptr == nullptr) { std::cerr << "Failed to obtain compiled function\n"; return 1; } // Run the function and test results. RaviGCObject obj = {NULL, 42, 65}; int ans = funcptr(&obj); printf("The answer is %d\n", ans); return ans == 42 ? 0 : 1; }
// This version of the test calls mytest() rather than // printf() as in test1(). Also we use RaviJITState and related // infrastructure int test2() { auto jitStatePtr = ravi::RaviJITStateFactory::newJITState(); ravi::RaviJITState &jitState = *jitStatePtr.get(); jitState.dump(); llvm::LLVMContext &context = jitState.context(); llvm::IRBuilder<> builder(context); // create a GCObject structure as defined in lobject.h llvm::StructType *structType = llvm::StructType::create(context, "RaviGCObject"); llvm::PointerType *pstructType = llvm::PointerType::get(structType, 0); // pointer to RaviGCObject std::vector<llvm::Type *> elements; elements.push_back(pstructType); elements.push_back(llvm::Type::getInt8Ty(context)); elements.push_back(llvm::Type::getInt8Ty(context)); structType->setBody(elements); structType->dump(); // Create declaration for mytest // int mytest(RaviGCObject *obj) std::vector<llvm::Type *> args; args.push_back(pstructType); llvm::FunctionType *mytestFuncType = llvm::FunctionType::get(builder.getInt32Ty(), args, false); // Create the testfunc() args.clear(); args.push_back(pstructType); llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getInt32Ty(), args, false); ravi::RaviJITFunction *func = jitState.createFunction( funcType, llvm::Function::ExternalLinkage, "testfunc"); llvm::Function *mainFunc = func->function(); llvm::BasicBlock *entry = llvm::BasicBlock::Create(context, "entrypoint", mainFunc); builder.SetInsertPoint(entry); // Get the first argument which is RaviGCObject * auto argiter = mainFunc->arg_begin(); llvm::Value *arg1 = argiter++; arg1->setName("obj"); // Add an extern int mytest(RaviGCObject *obj) and link this // to mytest() llvm::Constant *mytestFunc = func->addExternFunction(mytestFuncType, reinterpret_cast<void *>(&mytest), "mytest"); // Call the mytest() function std::vector<llvm::Value *> values; values.push_back(arg1); llvm::Value *tmp2 = builder.CreateCall(mytestFunc, values, "i"); // return i builder.CreateRet(tmp2); func->dump(); // Now lets compile our function into machine code myfunc_t funcptr = (myfunc_t)func->compile(); if (funcptr == nullptr) { std::cerr << "Failed to obtain compiled function\n"; return 1; } // Run the function and test results. RaviGCObject obj = {NULL, 42, 65}; int ans = funcptr(&obj); printf("The answer is %d\n", ans); return ans == 42 ? 0 : 1; }
int func() { return *funcptr(1L, 2); }