/* Destructor must remove section/header link */ SgAsmGenericSection::~SgAsmGenericSection() { SgAsmGenericFile* ef = get_file(); SgAsmGenericHeader *hdr = get_header(); /* See constructor comment. This deletes both halves of the header/section link. */ if (hdr) { hdr->remove_section(this); set_header(NULL); } /* See comment in ROSETTA/src/binaryInstruction.C. We need to explicitly delete the section name. */ if (p_name) { SageInterface::deleteAST(p_name); p_name = NULL; } /* FIXME: holes should probably be their own class, which would make the file/hole bidirectional linking more like the * header/section bidirectional links (RPM 2008-09-02) */ ef->remove_hole(this); /* Delete children */ p_file = NULL; // deleted by SageInterface::deleteAST() /* If the section has allocated its own local pool for the p_data member (rather than pointing into the SgAsmGenericFile) * then free that now. */ if (local_data_pool!=NULL) { free(local_data_pool); local_data_pool = NULL; } }
int RSIM_Simulator::exec(int argc, char **argv) { assert(argc>0); create_process(); SgAsmGenericHeader *fhdr = process->load(argv[0]); entry_va = fhdr->get_base_va() + fhdr->get_entry_rva(); RSIM_Thread *main_thread = process->get_thread(getpid()); assert(main_thread!=NULL); process->initialize_stack(fhdr, argc, argv); process->binary_trace_start(); if ((process->get_tracing_flags() & tracingFacilityBit(TRACE_MMAP))) { fprintf(process->get_tracing_file(), "memory map after program load:\n"); process->get_memory()->dump(process->get_tracing_file(), " "); } main_thread->tracing(TRACE_STATE)->mesg("Initial state:\n"); main_thread->policy.dump_registers(main_thread->tracing(TRACE_STATE)); return 0; }
std::string btorTranslate(BtorTranslationPolicy& policy, SgProject* proj, FILE* outfile, bool initialConditionsAreUnknown, bool bogusIpIsError) { std::vector<SgNode*> headers = NodeQuery::querySubTree(proj, V_SgAsmGenericHeader); ROSE_ASSERT (headers.size() == 1); SgAsmGenericHeader* header = isSgAsmGenericHeader(headers[0]); rose_addr_t entryPoint = header->get_entry_rva() + header->get_base_va(); X86InstructionSemantics<BtorTranslationPolicy, BtorWordType> t(policy); std::vector<SgNode*> instructions = NodeQuery::querySubTree(proj, V_SgAsmX86Instruction); for (size_t i = 0; i < instructions.size(); ++i) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(instructions[i]); ROSE_ASSERT (insn); try { t.processInstruction(insn); } catch (const X86InstructionSemantics<BtorTranslationPolicy, BtorWordType>::Exception &e) { fprintf(stderr, "%s: %s\n", e.mesg.c_str(), unparseInstructionWithAddress(e.insn).c_str()); } } policy.setInitialState(entryPoint, initialConditionsAreUnknown); // Add "bogus IP" error policy.newRegisterMap.errorFlag[bmc_error_bogus_ip] = policy.invert(policy.isValidIp); for (size_t i = 0; i < numBmcErrors; ++i) { if (i == bmc_error_bogus_ip && !bogusIpIsError) continue; // For testing policy.problem.computations.push_back(policy.problem.build_op_root(policy.problem.build_op_and(policy.errorsEnabled, policy.newRegisterMap.errorFlag[i]))); } policy.addNexts(); return policy.problem.unparse(); }
BinaryLoader::MappingContribution BinaryLoader::align_values(SgAsmGenericSection *section, MemoryMap *map, rose_addr_t *malign_lo_p, rose_addr_t *malign_hi_p, rose_addr_t *va_p, rose_addr_t *mem_size_p, rose_addr_t *offset_p, rose_addr_t *file_size_p, bool *map_private_p, rose_addr_t *va_offset_p, bool *anon_lo_p, bool *anon_hi_p, ConflictResolution *resolve_p) { ASSERT_not_null(section); ASSERT_require2(section->is_mapped(), "section must be mapped to virtual memory"); SgAsmGenericHeader *header = isSgAsmGenericHeader(section); if (!header) header = section->get_header(); ASSERT_not_null(header); /* Initial guesses */ rose_addr_t malign_lo = std::max(section->get_mapped_alignment(), (rose_addr_t)1); rose_addr_t malign_hi = std::min(std::max(section->get_mapped_alignment(), (rose_addr_t)1), (rose_addr_t)4096); rose_addr_t va = header->get_base_va() + section->get_mapped_preferred_rva(); rose_addr_t mem_size = section->get_mapped_size(); rose_addr_t falign_lo = std::max(section->get_file_alignment(), (rose_addr_t)1); rose_addr_t offset = section->get_offset(); rose_addr_t file_size = section->get_size(); /* Align lower end of mapped region to satisfy both memory and file alignment constraints. */ rose_addr_t va_offset = bialign(va, malign_lo, offset, falign_lo); if (va_offset>va || va_offset>offset) { mlog[TRACE] <<" Adjustment " <<va_offset <<" exceeds va or offset (va=" <<va <<", offset=" <<offset <<")\n"; throw Exception("no solutions to memory/file alignment constraints"); } ASSERT_require((va - va_offset) % malign_lo == 0); ASSERT_require((offset - va_offset) % falign_lo == 0); va -= va_offset; mem_size += va_offset; offset -= va_offset; file_size += va_offset; /* Extend mapped region to satisfy high alignment; but do not extend the file region */ if ((va + mem_size) % malign_hi != 0) { uint64_t extend_by = alignUp(va+mem_size, malign_hi) - (va+mem_size); mem_size += extend_by; } /* Return values */ *malign_lo_p = malign_lo; *malign_hi_p = malign_hi; *va_p = va; *mem_size_p = mem_size; *offset_p = offset; *file_size_p = file_size; *map_private_p = false; *va_offset_p = va_offset; *anon_lo_p = true; *anon_hi_p = true; *resolve_p = RESOLVE_THROW; return CONTRIBUTE_ADD; }
/** Returns base virtual address for a section, or zero if the section is not associated with a header. */ rose_addr_t SgAsmGenericSection::get_base_va() const { ROSE_ASSERT(this != NULL); if (isSgAsmGenericHeader(this)) return isSgAsmGenericHeader(this)->get_base_va(); SgAsmGenericHeader *hdr = get_header(); return hdr ? hdr->get_base_va() : 0; }
/* once called loadInterpLibraries */ void BinaryLoader::link(SgAsmInterpretation* interp) { ASSERT_not_null(interp); SgBinaryComposite *composite = SageInterface::getEnclosingNode<SgBinaryComposite>(interp); ASSERT_not_null(composite); /* Make sure the pre-load objects are parsed and linked into the AST. */ for (std::vector<std::string>::const_iterator pi=preloads.begin(); pi!=preloads.end(); ++pi) { mlog[TRACE] <<"preload object " <<*pi <<"\n"; std::string filename = find_so_file(*pi); if (is_linked(composite, filename)) { mlog[TRACE] <<filename <<" is already parsed.\n"; } else { Stream m1(mlog[TRACE] <<"parsing " <<filename); createAsmAST(composite, filename); m1 <<"... done.\n"; } } /* Bootstrap */ std::list<SgAsmGenericHeader*> unresolved_hdrs; unresolved_hdrs.insert(unresolved_hdrs.end(), interp->get_headers()->get_headers().begin(), interp->get_headers()->get_headers().end()); /* Process unresolved headers from the beginning of the queue and push new ones onto the end. */ while (!unresolved_hdrs.empty()) { SgAsmGenericHeader *header = unresolved_hdrs.front(); unresolved_hdrs.pop_front(); std::string header_name = header->get_file()->get_name(); std::vector<std::string> deps = dependencies(header); for (std::vector<std::string>::iterator di=deps.begin(); di!=deps.end(); ++di) { mlog[TRACE] <<"library " <<*di <<" needed by " <<header_name <<"\n"; std::string filename = find_so_file(*di); if (is_linked(composite, filename)) { mlog[TRACE] <<filename <<" is already parsed.\n"; } else { Stream m1(mlog[TRACE] <<"parsing " <<filename); SgAsmGenericFile *new_file = createAsmAST(composite, filename); m1 <<"... done.\n"; ASSERT_not_null2(new_file, "createAsmAST failed"); SgAsmGenericHeaderPtrList new_hdrs = findSimilarHeaders(header, new_file->get_headers()->get_headers()); unresolved_hdrs.insert(unresolved_hdrs.end(), new_hdrs.begin(), new_hdrs.end()); } } } }
/* This algorithm was implemented based on an e-mail from Cory Cohen at CERT and inspection of PE::ConvertRvaToFilePosition() * as defined in "PE.cpp 2738 2009-06-05 15:09:11Z murawski_dev". [RPM 2009-08-17] */ BinaryLoader::MappingContribution BinaryLoaderPe::align_values(SgAsmGenericSection *section, MemoryMap *map, rose_addr_t *malign_lo_p, rose_addr_t *malign_hi_p, rose_addr_t *va_p, rose_addr_t *mem_size_p, rose_addr_t *offset_p, rose_addr_t *file_size_p, bool *map_private_p, rose_addr_t *va_offset_p, bool *anon_lo_p, bool *anon_hi_p, ConflictResolution *resolve_p) { SgAsmGenericHeader *header = isSgAsmPEFileHeader(section); if (!header) header = section->get_header(); ROSE_ASSERT(header!=NULL); if (!section->is_mapped()) return CONTRIBUTE_NONE; /* File and memory alignment must be between 1 and 0x200 (512), inclusive */ rose_addr_t file_alignment = section->get_file_alignment(); if (file_alignment>0x200 || 0==file_alignment) file_alignment = 0x200; rose_addr_t mapped_alignment = section->get_mapped_alignment(); if (0==mapped_alignment) mapped_alignment = 0x200; /* Align file size upward even before we align the file offset downward. */ rose_addr_t file_size = ALIGN_UP(section->get_size(), file_alignment); /* Map the entire section's file content (aligned) or the requested map size, whichever is larger. */ rose_addr_t mapped_size = std::max(section->get_mapped_size(), file_size); /* Align file offset downward but do not adjust file size. */ rose_addr_t file_offset = ALIGN_DN(section->get_offset(), file_alignment); /* Align the preferred relative virtual address downward without regard for the base virtual address, and do not adjust * mapped size. */ rose_addr_t mapped_va = header->get_base_va() + ALIGN_DN(section->get_mapped_preferred_rva(), mapped_alignment); *malign_lo_p = mapped_alignment; *malign_hi_p = 1; *va_p = mapped_va; *mem_size_p = mapped_size; *offset_p = file_offset; *file_size_p = file_size; *map_private_p = false; *va_offset_p = 0; *anon_lo_p = *anon_hi_p = true; *resolve_p = RESOLVE_OVERMAP; return CONTRIBUTE_ADD; }
/* class method */ SgAsmGenericFile* BinaryLoader::createAsmAST(SgBinaryComposite* binaryFile, std::string filePath) { ASSERT_forbid(filePath.empty()); SgAsmGenericFile* file = SgAsmExecutableFileFormat::parseBinaryFormat(filePath.c_str()); ASSERT_not_null(file); // TODO do I need to attach here - or can I do after return binaryFile->get_genericFileList()->get_files().push_back(file); file->set_parent(binaryFile->get_genericFileList()); /* Add a new interpretation to the SgBinaryComposite object for each header of the newly parsed * SgAsmGenericFile for which a suitable interpretation does not already exist. */ const SgAsmGenericHeaderPtrList &headers = file->get_headers()->get_headers(); SgAsmInterpretationPtrList &interps = binaryFile->get_interpretations()->get_interpretations(); for (size_t i = 0; i < headers.size(); ++i) { SgAsmGenericHeader* header = headers[i]; SgAsmInterpretation* interp = NULL; for (size_t j = 0; j < interps.size(); ++j) { ASSERT_forbid(interps[j]->get_headers()->get_headers().empty()); SgAsmGenericHeader* interpHeader = interps[j]->get_headers()->get_headers().front(); if (isHeaderSimilar(header, interpHeader)) { interp = interps[j]; break; } } if (!interp) { interp = new SgAsmInterpretation(); interps.push_back(interp); interp->set_parent(binaryFile->get_interpretations()); if (const RegisterDictionary *registers = RegisterDictionary::dictionary_for_isa(header->get_isa())) interp->set_registers(registers); } interp->get_headers()->get_headers().push_back(header); } #if USE_ROSE_DWARF_SUPPORT /* Parse Dwarf info and add it to the SgAsmGenericFile. */ readDwarf(file); #endif return file; }
void VirtualTableSection::printOutVirtualFunctionTableInformation ( VirtualFunctionTableAddress vTableAddress ) { ROSE_ASSERT(virtualFunctionTable != NULL); size_t section_address_base = virtualFunctionTable->get_mapped_preferred_rva(); size_t offset = vTableAddress - section_address_base; size_t size = virtualFunctionTable->get_size(); ROSE_ASSERT(offset < size); printf ("In printOutVirtualFunctionTableInformation(%p): offset = %p (size = %p) \n",(void*)vTableAddress,(void*)offset,(void*)size); printf ("START -- Virtual function table: \n"); SgAsmGenericHeader *hdr = virtualFunctionTable->get_header(); SgAsmGenericFormat::ByteOrder sex = hdr->get_sex(); size_t wordsize = hdr->get_word_size(); size_t virtualTableSize = (size-offset) / wordsize; printf ("size = %zu offset = %zu wordsize = %zu virtualTableSize = %zu \n",size,offset,wordsize,virtualTableSize); for (size_t i=0; i < virtualTableSize; i++) { uint64_t functionPointer; /*type must support 64-bit specimen pointers in a 32-bit ROSE library*/ // printf ("i = %zu \n",i); switch (wordsize) { case 4: { uint32_t ptr_disk; // virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); // virtualFunctionTable->read_content_local(i*wordsize, &ptr_disk, sizeof ptr_disk); virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); functionPointer = SgAsmExecutableFileFormat::disk_to_host(sex, ptr_disk); break; } case 8: { uint64_t ptr_disk; // virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); // virtualFunctionTable->read_content_local(i*wordsize, &ptr_disk, sizeof ptr_disk); virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); functionPointer = SgAsmExecutableFileFormat::disk_to_host(sex, ptr_disk); break; } default: ROSE_ASSERT(!"unsupported word size"); } string sectionName; SgAsmElfSection* asmElfSection = getSection(project,functionPointer); if (asmElfSection != NULL) { sectionName = asmElfSection->get_name()->get_string(); } else { sectionName = "NOT CONTAINED IN EXECUTABLE"; // At the first sign of a pointer that is not in the executable then quit, this should be the end of the table. // Alternatively it appears that the end of the table has a code 0x4231 (for the first table). break; } printf ("Pointer 0x%"PRIx64" is to data in the %s section \n",functionPointer,sectionName.c_str()); } printf ("END -- Virtual function table: \n"); }
// Constructor VirtualFunctionTable::VirtualFunctionTable ( SgProject* project, SgAsmElfSection* virtualFunctionTable, size_t vTableAddress ) : virtualFunctionTablePosition(vTableAddress) { printf ("Building virtual function table for position %p \n",(void*)virtualFunctionTablePosition); // Get the boundaries of the section where the virtual function tables are located. ROSE_ASSERT(virtualFunctionTable != NULL); size_t section_address_base = virtualFunctionTable->get_mapped_preferred_rva(); // Compute the offset for the input virtual function table into the section. size_t offset = vTableAddress - section_address_base; // This is the upper bound on the size of the table (stay within the section) size_t size = virtualFunctionTable->get_size(); ROSE_ASSERT(offset < size); printf ("In printOutVirtualFunctionTableInformation(%p): offset = %p (size = %p) \n",(void*)vTableAddress,(void*)offset,(void*)size); printf ("START -- Virtual function table: \n"); // Get the architecture specifici information required to the raw data in the section. SgAsmGenericHeader *hdr = virtualFunctionTable->get_header(); SgAsmGenericFormat::ByteOrder sex = hdr->get_sex(); size_t wordsize = hdr->get_word_size(); size_t virtualTableSize = (size-offset) / wordsize; printf ("size = %zu offset = %zu wordsize = %zu virtualTableSize = %zu \n",size,offset,wordsize,virtualTableSize); for (size_t i=0; i < virtualTableSize; i++) { uint64_t functionPointer; /*type must support 64-bit specimen pointers in a 32-bit ROSE library*/ // printf ("i = %zu \n",i); switch (wordsize) { case 4: { uint32_t ptr_disk; // virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); // virtualFunctionTable->read_content_local(i*wordsize, &ptr_disk, sizeof ptr_disk); virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); functionPointer = SgAsmExecutableFileFormat::disk_to_host(sex, ptr_disk); break; } case 8: { uint64_t ptr_disk; // virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); // virtualFunctionTable->read_content_local(i*wordsize, &ptr_disk, sizeof ptr_disk); virtualFunctionTable->read_content_local(offset+i*wordsize, &ptr_disk, sizeof ptr_disk); functionPointer = SgAsmExecutableFileFormat::disk_to_host(sex, ptr_disk); break; } default: ROSE_ASSERT(!"unsupported word size"); } string sectionName; SgAsmElfSection* asmElfSection = getSection(project,functionPointer); if (asmElfSection != NULL) { sectionName = asmElfSection->get_name()->get_string(); } else { sectionName = "NOT CONTAINED IN EXECUTABLE"; // At the first sign of a pointer that is not in the executable then quit, this should be the end of the table. // Alternatively it appears that the end of the table has a code 0x4231 (for the first table). break; } printf ("Pointer 0x%"PRIx64" is to data in the %s section \n",functionPointer,sectionName.c_str()); string name = "virtual_function_" + StringUtility::numberToString(i); VirtualFunction* virtualFunction = new VirtualFunction(name,functionPointer); ROSE_ASSERT(virtualFunction != NULL); virtualFunctionList.push_back(virtualFunction); } printf ("END -- Virtual function table: \n"); #if 0 printf ("Exiting in VirtualFunctionTable constructor \n"); ROSE_ASSERT(false); #endif }
int main(int argc, char *argv[]) { SgProject *project = frontend(argc, argv); SgAsmInterpretation *interp = SageInterface::querySubTree<SgAsmInterpretation>(project).back(); AllInstructions insns(interp); SgAsmGenericHeader *header = interp->get_headers()->get_headers().front(); rose_addr_t start_va = header->get_base_va() + header->get_entry_rva(); #if SEMANTIC_API == OLD_API MyPolicy operators; X86InstructionSemantics<MyPolicy, MyValueType> dispatcher(operators); #else BaseSemantics::RiscOperatorsPtr operators = make_ops(); BaseSemantics::DispatcherPtr dispatcher = DispatcherX86::instance(operators); #endif struct sigaction sa; sa.sa_handler = alarm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGALRM, &sa, NULL); alarm(timeout); struct timeval start_time; std::cout <<"test starting...\n"; gettimeofday(&start_time, NULL); size_t ninsns = 0; while (!had_alarm) { rose_addr_t va = start_va; while (SgAsmInstruction *insn = insns.fetch(va)) { //std::cerr <<unparseInstructionWithAddress(insn) <<"\n"; #if SEMANTIC_API == OLD_API dispatcher.processInstruction(isSgAsmx86Instruction(insn)); ++ninsns; #if SEMANTIC_DOMAIN == MULTI_DOMAIN // multi-semantics ValueType has no is_known() or get_known(). We need to invoke it on a specific subpolicy. PartialSymbolicSemantics::ValueType<32> ip = operators.readRegister<32>("eip") .get_subvalue(MyMultiSemanticsClass::SP0()); #else MyValueType<32> ip = operators.readRegister<32>("eip"); #endif if (!ip.is_known()) break; va = ip.known_value(); #else dispatcher->processInstruction(insn); ++ninsns; BaseSemantics::SValuePtr ip = operators->readRegister(dispatcher->findRegister("eip")); if (!ip->is_number()) break; va = ip->get_number(); #endif if (had_alarm) break; } } #if SEMANTIC_API == OLD_API MyValueType<32> eax = operators.readRegister<32>("eax"); std::cerr <<"eax = " <<eax <<"\n"; #else BaseSemantics::SValuePtr eax = operators->readRegister(dispatcher->findRegister("eax")); #if SEMANTIC_DOMAIN == MULTI_DOMAIN // This is entirely optional, but the output looks better if it has the names of the subdomains. std::cerr <<"eax = " <<(*eax + MultiSemantics::RiscOperators::promote(operators)->get_formatter()) <<"\n"; #else std::cerr <<"eax = " <<*eax <<"\n"; #endif #endif struct timeval stop_time; gettimeofday(&stop_time, NULL); double elapsed = ((double)stop_time.tv_sec-start_time.tv_sec) + 1e-6*((double)stop_time.tv_usec-start_time.tv_usec); if (elapsed < timeout/4.0) std::cout <<"warning: test did not run for a sufficiently long time; output may contain a high degree of error.\n"; std::cout <<"number of instructions: " <<ninsns <<"\n" <<"elapsed time: " <<elapsed <<" seconds\n" <<"semantic execution rate: " <<(ninsns/elapsed) <<" instructions/second\n"; return 0; }