// check if addr falls into a data section, and is at least minAddr. // the minAddr check exists for times when we are not sure if an address // is a data reference or an immediate value; in some cases data is mapped // at 0x0 and determining this could be tricky static bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0 ) { list<DataSection> §ions = m->getData(); list<DataSection>::iterator it = sections.begin(); // sanity check: // assume no data references before minAddr. if (addr < minAddr) { return false; } if(sections.size() == 0) { llvm::dbgs() << __FUNCTION__ << ": WARNING: no data sections!\n"; return false; } while( it != sections.end() ) { DataSection &curSec = *it; VA low = curSec.getBase(); VA high = low+curSec.getSize(); if( addr >= low && addr < high ) { base = low; return true; } ++it; } return false; }
static bool InsertDataSections(NativeModulePtr natMod, llvm::Module *M) { auto &globaldata = natMod->getData(); //insert all global data before we insert the CFG std::vector<DataSectionVar> gvars; // pre-create references to all data sections // as later we may have data references that are // from one section into another for (auto &dt : globaldata) { std::stringstream ss; ss << "data_" << std::hex << dt.getBase(); std::string bufferName = ss.str(); //report << "inserting global data section named "; //report << bufferName << "\n"; std::cout << "inserting global data section named "; std::cout << bufferName << std::endl; auto st_opaque = llvm::StructType::create(M->getContext()); // Used to be PrivateLinkage, but that emitted // .objs that would not link with MSVC auto g = new llvm::GlobalVariable( *M, st_opaque, dt.isReadOnly(), llvm::GlobalVariable::InternalLinkage, nullptr, bufferName); gvars.push_back({&dt, st_opaque, g}); } // actually populate the data sections for (auto &var : gvars) { //data we use to create LLVM values for this section // secContents is the actual values we will be inserting std::vector<llvm::Constant *> secContents; // data_section_types is their types, which are needed to initialize // the global variable std::vector<llvm::Type *> data_section_types; dataSectionToTypesContents(globaldata, *var.section, M, secContents, data_section_types, true); // fill in the opaque structure with actual members var.opaque_type->setBody(data_section_types, true); // create an initializer list using the now filled in opaque // structure type auto cst = llvm::ConstantStruct::get(var.opaque_type, secContents); // align on pointer size boundary, max needed by SSE instructions var.var->setAlignment(ArchPointerSize(M)); var.var->setInitializer(cst); } return true; }
static bool addTableDataSection(NativeModulePtr natMod, Module *M, VA &newVA, const T& table) { list<DataSection> &globaldata = natMod->getData(); list<DataSection>::const_iterator git = globaldata.begin(); // ensure we make this the last data section newVA = 0; while( git != globaldata.end() ) { const DataSection &dt = *git; uint64_t extent = dt.getBase() + dt.getSize(); if(newVA < extent) { newVA = extent; } git++; } // skip a few newVA += 4; // create a new data section from the table DataSection *ds = tableToDataSection(newVA, table); // add to global data section list globaldata.push_back(*ds); // create the GlobalVariable string bufferName = "data_0x" + to_string<VA>(newVA, hex); StructType *st_opaque = StructType::create(M->getContext()); GlobalVariable *gv = new GlobalVariable(*M, st_opaque, true, GlobalVariable::InternalLinkage, NULL, bufferName); vector<Type*> data_section_types; vector<Constant*> secContents; dataSectionToTypesContents(globaldata, *ds, M, secContents, data_section_types, false); st_opaque->setBody(data_section_types, true); Constant *cst = ConstantStruct::get(st_opaque, secContents); gv->setAlignment(4); gv->setInitializer(cst); return true; }