TEST_FIXTURE(MemoryMapTestFixture, CreateWriteRead) { if (!fileName.isEmpty()) { fs::remove(fileName.getString()); { vector<uint8_t> data(length); for (size_t i = 0; i < length; ++i) { data[i] = uint8_t(i%256); } File fwrite(fileName.getString(), File::Write|File::Create); CHECK(fwrite.isOk()); CHECK(fwrite.write(&data[0], length)); } { File file(fileName.getString(), File::Read); MemoryMap mread; CHECK(mread.map(file.getDescriptor(), length, MemoryMap::Read, MemoryMap::Private)); uint8_t *data = static_cast<uint8_t *>(mread.getMemory()); for (size_t i = 0; i < length; ++i) { CHECK_EQUAL(uint8_t(i%256), data[i]); } } } }
Partitioner::RegionStats * Partitioner::region_statistics() { MemoryMap mymap = *map; mymap.prune(MemoryMap::MM_PROT_EXEC); return region_statistics(mymap.va_extents()); }
int main(int argc, char *argv[]) { Diagnostics::initialize(); mlog = Sawyer::Message::Facility("tool", Diagnostics::destination); Diagnostics::mfacilities.insertAndAdjust(mlog); // Parse command line Settings settings; std::vector<std::string> args = parseCommandLine(argc, argv, settings).unreachedArgs(); if (args.size()!=2) throw std::runtime_error("invalid usage; see --help"); // Load the CSV files FunctionByAddress code1, data1, code2, data2; readCsvFile(args[0], code1 /*out*/, data1 /*out*/); readCsvFile(args[1], code2 /*out*/, data2 /*out*/); showStats(FileSystem::Path(args[0]).filename().string(), code1, data1, FileSystem::Path(args[1]).filename().string(), code2, data2); std::cout <<"\n"; // Parse the specimen if (!settings.specimenName.empty()) { P2::Engine engine; MemoryMap map = engine.loadSpecimens(settings.specimenName); InstructionProvider::Ptr insns = InstructionProvider::instance(engine.obtainDisassembler(), map); map.dump(std::cout); listInstructions(insns, map, code1, code2); } }
int main(int argc, char *argv[]) { Diagnostics::initialize(); ::mlog = Diagnostics::Facility("tool", Diagnostics::destination); Diagnostics::mfacilities.insertAndAdjust(::mlog); // Parse the command-line Partitioner2::Engine engine; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine); if (specimenNames.empty()) throw std::runtime_error("no specimen specified; see --help"); // Load specimen into memory MemoryMap map = engine.loadSpecimens(specimenNames); // Configure instruction semantics Partitioner2::Partitioner partitioner = engine.createPartitioner(); Disassembler *disassembler = engine.obtainDisassembler(); const RegisterDictionary *regdict = disassembler->get_registers(); if (disassembler->dispatcher() == NULL) throw std::runtime_error("no instruction semantics for this architecture"); BaseSemantics::RiscOperatorsPtr ops = InstructionSemantics2::ConcreteSemantics::RiscOperators::instance(regdict); BaseSemantics::DispatcherPtr cpu = disassembler->dispatcher()->create(ops); ConcreteSemantics::MemoryState::promote(ops->currentState()->memoryState())->memoryMap(map); // Find starting address rose_addr_t va = 0; if (settings.startVa) { va = *settings.startVa; } else if (engine.isaName() == "coldfire") { // Use the interrupt vector to initialize the stack pointer and instruction pointer. uint32_t sp, ip; if (4 != map.at(0).limit(4).read((uint8_t*)&sp).size()) throw std::runtime_error("cannot read stack pointer at address 0x00000000"); ops->writeRegister(disassembler->stackPointerRegister(), ops->number_(32, ByteOrder::be_to_host(sp))); if (4 != map.at(4).limit(4).read((uint8_t*)&ip).size()) throw std::runtime_error("cannot read instruction pointer at address 0x00000004"); va = ByteOrder::be_to_host(ip); } else if (!map.atOrAfter(0).require(MemoryMap::EXECUTABLE).next().assignTo(va)) { throw std::runtime_error("no starting address specified and none marked executable"); } ops->writeRegister(disassembler->instructionPointerRegister(), ops->number_(32, va)); // Execute map.dump(::mlog[INFO]); while (1) { va = ops->readRegister(disassembler->instructionPointerRegister())->get_number(); SgAsmInstruction *insn = partitioner.instructionProvider()[va]; SAWYER_MESG(::mlog[TRACE]) <<unparseInstructionWithAddress(insn, NULL, regdict) <<"\n"; try { cpu->processInstruction(insn); } catch (const BaseSemantics::Exception &e) { ::mlog[WARN] <<e <<"\n"; } } // std::cout <<"Final state:\n"; // std::cout <<*ops->currentState(); }
static void listInstructions(const InstructionProvider::Ptr &insns, const MemoryMap &map, const FunctionByAddress &code1, FunctionByAddress &code2) { std::ostream &out = std::cout; static const size_t insnWidth = 110; rose_addr_t va1 = code1.hull().least(); rose_addr_t va2 = code2.hull().least(); rose_addr_t va = std::min(va1, va2); rose_addr_t expectedVa = va; AsmUnparser unparser; while (va<=code1.hull().greatest() || va<=code2.hull().greatest()) { // Address and contents if (va != expectedVa) out <<"\n"; // visual cue that addresses are not sequential here std::ostringstream ss; size_t size; if (!map.at(va).require(MemoryMap::EXECUTABLE).exists()) { ss <<StringUtility::addrToString(va) <<": " <<(map.at(va).exists() ? "not executable" : "not mapped"); size = 1; } else if (SgAsmInstruction *insn = (*insns)[va]) { unparser.unparse(ss, insn); size = insn->get_size(); } else { ss <<StringUtility::addrToString(va) <<": bad instruction"; size = 1; } std::vector<std::string> lines = StringUtility::split('\n', ss.str()); while (lines.size()>0 && lines[lines.size()-1]=="") lines.pop_back(); for (size_t i=0; i<lines.size(); ++i) { if (i+1 < lines.size()) { out <<lines[i] <<"\n"; } else { out <<std::setw(insnWidth) <<std::left <<lines[i]; } } // Functions owning Sawyer::Optional<rose_addr_t> f1 = code1.getOptional(va); Sawyer::Optional<rose_addr_t> f2 = code2.getOptional(va); out <<"\t" <<std::setw(10) <<std::left <<(f1 ? StringUtility::addrToString(*f1) : std::string("none")); out <<"\t" <<std::setw(10) <<std::left <<(f2 ? StringUtility::addrToString(*f2) : std::string("none")); out <<" " <<(f1.isEqual(f2) ? "" : "<---") <<"\n"; // Advance address pointer rose_addr_t next = va + size; expectedVa = next; FunctionByAddress::ConstIntervalIterator i1 = code1.upperBound(va); if (i1!=code1.nodes().end() && i1->least() < next) next = i1->least(); FunctionByAddress::ConstIntervalIterator i2 = code2.upperBound(va); if (i2!=code2.nodes().end() && i2->least() < next) next = i2->least(); if (!map.atOrAfter(next).next().assignTo(va)) break; } }
int main(int argc, char *argv[]) { // Parse command-line int argno=1; for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) { if (!strcmp(argv[argno], "--")) { ++argno; break; } else { std::cerr <<argv[0] <<": unrecognized switch: " <<argv[argno] <<"\n"; exit(1); } } if (argno+1!=argc) { std::cerr <<"usage: " <<argv[0] <<" [SWITCHES] [--] SPECIMEN\n"; exit(1); } std::string specimen_name = argv[argno++]; // Open the file rose_addr_t start_va = 0; MemoryMap map; size_t file_size = map.insertFile(specimen_name, start_va); map.at(start_va).limit(file_size).changeAccess(MemoryMap::EXECUTABLE, 0); // Try to disassemble every byte, and print the CALL/FARCALL targets InstructionMap insns; size_t nerrors=0; Disassembler *disassembler = new DisassemblerX86(4); for (rose_addr_t offset=0; offset<file_size; ++offset) { try { rose_addr_t insn_va = start_va + offset; if (SgAsmX86Instruction *insn = isSgAsmX86Instruction(disassembler->disassembleOne(&map, insn_va))) insns[insn_va] = insn; } catch (const Disassembler::Exception &e) { ++nerrors; } } // Partition those instructions into basic blocks and functions Partitioner partitioner; SgAsmBlock *gblock = partitioner.partition(NULL, insns, &map); // Print addresses of functions struct T1: AstSimpleProcessing { void visit(SgNode *node) { if (SgAsmFunction *func = isSgAsmFunction(node)) std::cout <<StringUtility::addrToString(func->get_entry_va()) <<"\n"; } }; T1().traverse(gblock, preorder); std::cerr <<specimen_name <<": " <<insns.size() <<" instructions; " <<nerrors <<" errors\n"; return 0; }
TEST(MemoryMap, Values) { const size_t NUM_BANKS = 11; const size_t BANK_SIZE = 17; MemoryMap<uint8_t> memMap; for (size_t ii = 0; ii < NUM_BANKS; ++ii) { std::shared_ptr<RAM<uint8_t> > bank(new RAM<uint8_t>(BANK_SIZE)); memMap.setMemoryBank(ii * BANK_SIZE, bank); } memMap.lockLookUpTable(); for (size_t ii = 0; ii < NUM_BANKS * BANK_SIZE; ++ii) { memMap.writeWord(ii, ii); } for (size_t ii = 0; ii < NUM_BANKS * BANK_SIZE; ++ii) { EXPECT_EQ(ii, memMap.readWord(ii)); } // Test a few long values EXPECT_EQ(static_cast<uint16_t>(0x0201), memMap.readLong(1)); EXPECT_EQ(static_cast<uint16_t>(0x0302), memMap.readLong(2)); EXPECT_EQ(static_cast<uint16_t>(0x0908), memMap.readLong(8)); EXPECT_EQ(static_cast<uint16_t>(0x0B0A), memMap.readLong(10)); EXPECT_EQ(static_cast<uint16_t>(0x0C0B), memMap.readLong(11)); EXPECT_EQ(static_cast<uint16_t>(0x0D0C), memMap.readLong(12)); EXPECT_EQ(static_cast<uint16_t>(0x0E0D), memMap.readLong(13)); }
// class method rose_addr_t SRecord::load(const std::vector<SRecord> &srecs, MemoryMap &map, bool createSegments, unsigned accessPerms) { if (createSegments) { // We want to minimize the number of buffers in the map, so the first step is to discover what addresses are covered by // the data S-records Sawyer::Container::IntervalSet<AddressInterval> addressesUsed; BOOST_FOREACH (const SRecord &srec, srecs) { switch (srec.type()) { case SREC_DATA16: case SREC_DATA24: case SREC_DATA32: addressesUsed.insert(AddressInterval::baseSize(srec.address(), srec.data().size())); break; default: break; } } // Create buffers for the data and insert them into the memory map BOOST_FOREACH (const AddressInterval &interval, addressesUsed.intervals()) { ASSERT_forbid(interval.isWhole()); // not practically possible since S-Record file would be >2^65 bytes map.insert(interval, MemoryMap::Segment::anonymousInstance(interval.size(), accessPerms, "S-Records")); } } // Populate the map by writing the S-Record data into it. rose_addr_t startingAddr = 0; BOOST_FOREACH (const SRecord &srec, srecs) { switch (srec.type()) { case SREC_DATA16: case SREC_DATA24: case SREC_DATA32: { if (!srec.data().empty()) { size_t nwritten = map.at(srec.address()).write(srec.data()).size(); if (nwritten != srec.data().size()) throw MemoryMap::NotMapped("S-Record destination is not mapped for " + StringUtility::plural(srec.data().size(), "bytes"), &map, srec.address()); } break; } case SREC_START16: case SREC_START24: case SREC_START32: startingAddr = srec.address(); break; default: break; } } return startingAddr; }
VirtualAddressRange findFreeVirtualAddressInRange(VirtualAddressRange range, uint32_t size, uint32_t align) { return sMemoryMap.findFreeVirtualAddressInRange(range, size, align); }
std::string MagicNumber::identify(const MemoryMap &map, rose_addr_t va) const { uint8_t buf[256]; size_t nBytes = map.at(va).limit(std::min(maxBytes_, sizeof buf)).read(buf).size(); if (0==nBytes) return "empty"; #ifdef ROSE_HAVE_LIBMAGIC return magic_buffer(details_->cookie, buf, nBytes); #elif defined(BOOST_WINDOWS) throw std::runtime_error("magic number identification is not supported on Microsoft Windows"); #elif BOOST_FILESYSTEM_VERSION == 2 throw std::runtime_error("MagicNumber::identify must have either libmagic or boost::filesystem version 3"); #else // We can maybe still do it, but this will be much, much slower. We copy some specimen memory into a temporary file, then // run the unix file(1) command on it, then delete the temp file. static int ncalls = 0; if (1 == ++ncalls) mlog[WARN] <<"libmagic is not available on this system; using slow method instead\n"; FileSystem::Path tmpFile = boost::filesystem::unique_path("/tmp/ROSE-%%%%-%%%%-%%%%-%%%%"); std::ofstream(tmpFile.c_str()).write((const char*)buf, nBytes); std::string cmd = "file " + tmpFile.string(); std::string magic; if (FILE *f = popen(cmd.c_str(), "r")) { char line[1024]; if (fgets(line, sizeof line, f)) magic = boost::trim_right_copy(std::string(line).substr(tmpFile.string().size()+2)); // filename + ": " pclose(f); } else { boost::filesystem::remove(tmpFile); throw std::runtime_error("command file: " + tmpFile.string()); } boost::filesystem::remove(tmpFile); return magic; #endif }
virtual void populateCache(const Fingerprint &fileId, const DenseDataPtr &respondData) { { MemoryMap::write_iterator writer(mData); if (mData.alloc(respondData->length(), writer)) { bool newentry = writer.insert(fileId, respondData->length()); if (newentry) { SILOG(transfer,debug,fileId << " created " << *respondData); CacheData *cdata = new CacheData; *writer = cdata; cdata->mSparse.addValidData(respondData); writer.use(); } else { CacheData *cdata = static_cast<CacheData*>(*writer); cdata->mSparse.addValidData(respondData); if (SILOGP(transfer,debug)) { SILOGNOCR(transfer,debug,fileId << " already exists: "); std::stringstream rangeListStream; Range::printRangeList(rangeListStream,cdata->mSparse, (Range)(*respondData)); SILOGNOCR(transfer,debug,rangeListStream.str()); } writer.update(cdata->mSparse.getSpaceUsed()); } } } CacheLayer::populateParentCaches(fileId, respondData); }
int main(int argc, char *argv[]) { // Parse command-line int argno=1; for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) { if (!strcmp(argv[argno], "--")) { ++argno; break; } else { std::cerr <<argv[0] <<": unrecognized switch: " <<argv[argno] <<"\n"; exit(1); } } if (argno+1!=argc) { std::cerr <<"usage: " <<argv[0] <<" [SWITCHES] [--] SPECIMEN\n"; exit(1); } std::string specimen_name = argv[argno++]; // Open the file rose_addr_t start_va = 0; MemoryMap map; size_t file_size = map.insertFile(specimen_name, start_va); map.at(start_va).limit(file_size).changeAccess(MemoryMap::EXECUTABLE, 0); // Try to disassemble every byte, and print the CALL/FARCALL targets size_t ninsns=0, nerrors=0; Disassembler *disassembler = new DisassemblerX86(4); for (rose_addr_t offset=0; offset<file_size; ++offset) { try { rose_addr_t insn_va = start_va + offset; SgAsmX86Instruction *insn = isSgAsmX86Instruction(disassembler->disassembleOne(&map, insn_va)); if (insn && (x86_call==insn->get_kind() || x86_farcall==insn->get_kind())) { ++ninsns; rose_addr_t target_va; if (insn->getBranchTarget(&target_va)) std::cout <<StringUtility::addrToString(insn_va) <<": " <<StringUtility::addrToString(target_va) <<"\n"; } } catch (const Disassembler::Exception &e) { ++nerrors; } } std::cerr <<specimen_name <<": " <<ninsns <<" instructions; " <<nerrors <<" errors\n"; return 0; }
bool mapMemory(VirtualAddress virtualAddress, PhysicalAddress physicalAddress, uint32_t size, MapPermission permission) { return sMemoryMap.mapMemory(virtualAddress, physicalAddress, size, permission); }
// Get all the functions defined for this process image. We do this by disassembling the entire process executable memory // and using CFG analysis to figure out where the functions are located. Functions find_functions(RTS_Message *m, RSIM_Process *proc) { m->mesg("%s triggered; disassembling entire specimen image...\n", name); MemoryMap *map = disassembly_map(proc); std::ostringstream ss; map->dump(ss, " "); m->mesg("%s: using this memory map for disassembly:\n%s", name, ss.str().c_str()); SgAsmBlock *gblk = proc->disassemble(false/*take no shortcuts*/, map); delete map; map=NULL; std::vector<SgAsmFunction*> functions = SageInterface::querySubTree<SgAsmFunction>(gblk); #if 0 /*DEBUGGING [Robb P. Matzke 2013-02-12]*/ // Prune the function list to contain only what we want. for (std::vector<SgAsmFunction*>::iterator fi=functions.begin(); fi!=functions.end(); ++fi) { if ((*fi)->get_name().compare("_Z1fRi")!=0) *fi = NULL; } functions.erase(std::remove(functions.begin(), functions.end(), (SgAsmFunction*)NULL), functions.end()); #endif return Functions(functions.begin(), functions.end()); }
int main(int argc, char *argv[]) { ROSE_INITIALIZE; Diagnostics::initAndRegister(mlog, "tool"); Sawyer::ProgressBarSettings::minimumUpdateInterval(0.2); // more fluid spinner // Parse command-line P2::Engine engine; Settings settings; std::vector<std::string> args = parseCommandLine(argc, argv, engine, settings); ASSERT_always_require2(args.size() >= 2, "incorrect usage; see --help"); // Parse file containing instruction addresses std::string addrFileName = args[0]; std::set<rose_addr_t> knownVas = parseAddressFile(addrFileName); mlog[INFO] <<"parsed " <<plural(knownVas.size(), "unique addresses") <<"\n"; // Load specimen natively and attach debugger std::vector<std::string> specimen_cmd(args.begin()+1, args.end()); BinaryDebugger debugger(specimen_cmd); debugger.setBreakpoint(AddressInterval::whole()); ASSERT_always_require(debugger.isAttached()); ASSERT_always_forbid(debugger.isTerminated()); pid_t pid = debugger.isAttached(); mlog[INFO] <<"child PID " <<pid <<"\n"; // Get memory map. MemoryMap map; if (MAP_ROSE==settings.mapSource) { map = engine.loadSpecimens(specimen_cmd[0]); } else { map.insertProcess(":noattach:" + numberToString(pid)); } map.dump(mlog[INFO]); // The addresses specified in the instruction address file must all be in memory that is mapped. BOOST_FOREACH (rose_addr_t va, knownVas) { ASSERT_always_require2(map.at(va).require(MemoryMap::EXECUTABLE).exists(), "given address " + addrToString(va) + " is not mapped or lacks execute permission"); }
int main(int argc, char *argv[]) { //! [commandline] ROSE_INITIALIZE; // see rose::initialize std::string purpose = "finds static strings in a binary specimen"; std::string description = "This tool disassembles a binary specimen and then scans the " "read-only parts of memory to find static strings. It looks for " "C-style NUL-termianted printable ASCII strings, zero-terminated " "UTF-16 little-endian strings, two-byte little-endian length-encoded " "ASCII strings, and some other common formats."; Partitioner2::Engine engine; std::vector<std::string> specimen = engine.parseCommandLine(argc, argv, purpose, description).unreachedArgs(); //! [commandline] //! [load] MemoryMap map = engine.loadSpecimens(specimen); ByteOrder::Endianness sex = engine.obtainDisassembler()->get_sex(); //! [load] //! [analysis] Strings::StringFinder finder; // the string analyzer finder.settings().minLength = 5; // no strings shorter than 5 characters finder.settings().maxLength = 8192; // no strings longer than 8k characters finder.insertCommonEncoders(sex); // match common encodings of strings finder.find(map.require(MemoryMap::READABLE).prohibit(MemoryMap::WRITABLE)); //! [analysis] //! [output] // Output, or just do "std::cout <<finder" if you're not picky. BOOST_FOREACH (const Strings::EncodedString &string, finder.strings()) { std::cout <<"string at " <<string.address() <<" for " <<string.size() <<" bytes\n"; std::cout <<"encoding: " <<string.encoder()->name() <<"\n"; std::cout <<"narrow value: \"" <<StringUtility::cEscape(string.narrow()) <<"\"\n"; } //! [output] }
MMPainter::FStreamRecorder::FStreamRecorder( const char* fname, const MemoryMap& mm ) #ifdef MEMMON_DEBUG : _fname( fname ) , _count( 0 ) #endif { _buf.open( fname, std::ios_base::out | std::ios_base::binary ); if( !_buf.is_open() ) throw MemMon::ConstructorFailure< FStreamRecorder >(); std::streambuf* bufptr = &_buf; mm.Write( bufptr ); }
// Obtain a memory map for disassembly MemoryMap *disassembly_map(RSIM_Process *proc) { MemoryMap *map = new MemoryMap(proc->get_memory(), MemoryMap::COPY_SHALLOW); map->prune(MemoryMap::MM_PROT_READ); // don't let the disassembler read unreadable memory, else it will segfault // Removes execute permission for any segment whose debug name does not contain the name of the executable. When // comparing two different executables for clones, we probably don't need to compare code that came from dynamically // linked libraries since they will be identical in both executables. struct Pruner: MemoryMap::Visitor { std::string exename; Pruner(const std::string &exename): exename(exename) {} virtual bool operator()(const MemoryMap*, const Extent&, const MemoryMap::Segment &segment_) { MemoryMap::Segment *segment = const_cast<MemoryMap::Segment*>(&segment_); if (segment->get_name().find(exename)==std::string::npos) { unsigned p = segment->get_mapperms(); p &= ~MemoryMap::MM_PROT_EXEC; segment->set_mapperms(p); } return true; } } pruner(proc->get_exename()); map->traverse(pruner); return map; }
int main(int argc, char *argv[]) { Diagnostics::initialize(); BinaryAnalysis::Partitioner2::Engine engine; Settings settings; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine, settings /*in,out*/); BinaryAnalysis::MagicNumber analyzer; analyzer.maxBytesToCheck(settings.maxBytes); MemoryMap map = engine.loadSpecimens(specimenNames); map.dump(mlog[INFO]); size_t step = std::max(size_t(1), settings.step); AddressInterval limits = settings.limits.isEmpty() ? map.hull() : (settings.limits & map.hull()); Sawyer::Container::IntervalSet<AddressInterval> addresses(map); addresses.intersect(limits); size_t nPositions = addresses.size() / step; mlog[INFO] <<"approximately " <<StringUtility::plural(nPositions, "positions") <<" to check\n"; { Sawyer::ProgressBar<size_t> progress(nPositions, mlog[INFO], "positions"); for (rose_addr_t va=limits.least(); va<=limits.greatest() && map.atOrAfter(va).next().assignTo(va); va+=step, ++progress) { std::string magicString = analyzer.identify(map, va); if (magicString!="data") { // runs home to Momma when it gets confused uint8_t buf[8]; size_t nBytes = map.at(va).limit(sizeof buf).read(buf).size(); std::cout <<StringUtility::addrToString(va) <<" |" <<leadingBytes(buf, nBytes) <<" | " <<magicString <<"\n"; } if (va==limits.greatest()) break; // prevent overflow at top of address space } } }
// class method size_t SRecord::dump(const MemoryMap &map, std::ostream &out, size_t addrSize) { ASSERT_require(2==addrSize || 3==addrSize || 4==addrSize); SRecord::Type type = SREC_NONE; switch (addrSize) { case 2: type = SREC_DATA16; break; case 3: type = SREC_DATA24; break; case 4: type = SREC_DATA32; break; } size_t nRecords = 0; rose_addr_t va = 0; static const size_t maxBytesPerRecord = 28; // common value so each S-Record fits on an 80-character screen uint8_t buffer[maxBytesPerRecord]; while (map.atOrAfter(va).next().assignTo(va)) { size_t nread = map.at(va).limit(maxBytesPerRecord).read(buffer).size(); ASSERT_require(nread>0); // since map.next() returned true SRecord srec(type, va, buffer, nread); out <<srec <<"\n"; va += nread; ++nRecords; } return nRecords; }
void GenomeSequence::sanityCheck(MemoryMap &fasta) const { unsigned int i; unsigned int genomeIndex = 0; for (i=0; i<fasta.length(); i++) { switch (fasta[i]) { case '>': while (fasta[i]!='\n' && fasta[i]!='\r') i++; break; case '\n': case '\r': break; default: assert(BaseAsciiMap::base2int[(int)(*this)[genomeIndex]] == BaseAsciiMap::base2int[(int) fasta[i]]); genomeIndex++; break; } } }
/* Looks at the RVA/Size pairs in the PE header and creates an SgAsmGenericSection object for each one. This must be done * after we build the mapping from virtual addresses to file offsets. */ void SgAsmPEFileHeader::create_table_sections() { /* First, only create the sections. */ for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) { SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i]; if (0==pair->get_e_size()) continue; /* Table names come from PE file specification and are hard coded by RVA/Size pair index */ const char *tabname_short; std::string tabname = rvasize_pair_name((PairPurpose)i, &tabname_short); /* Find the starting offset in the file. * FIXME: We have a potential problem here in that ROSE sections are always contiguous in the file but a section created * from an RVA/Size pair is not necessarily contiguous in the file. Normally such sections are in fact * contiguous and we'll just ignore this for now. In any case, as long as these sections only ever read their * data via the same MemoryMap that we use here, everything should be fine. [RPM 2009-08-17] */ MemoryMap *map = get_loader_map(); ROSE_ASSERT(map!=NULL); const MemoryMap::MapElement *elmt = map->find(get_base_va() + pair->get_e_rva()); if (!elmt) { fprintf(stderr, "SgAsmPEFileHeader::create_table_sections: warning: pair-%zu, rva=0x%08"PRIx64", size=%"PRIu64 " bytes \"%s\": unable to find a mapping for the virtual address (skipping)\n", i, pair->get_e_rva().get_rva(), pair->get_e_size(), tabname.c_str()); continue; } rose_addr_t file_offset = elmt->is_anonymous() ? 0 : elmt->get_va_offset(get_base_va() + pair->get_e_rva(), 1); /* Create the new section */ SgAsmGenericSection *tabsec = NULL; switch (i) { case 0: { /* Sometimes export sections are represented by a ".edata" section, and sometimes they're represented by an * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the exports duplicated * in the AST, so we only create this table as exports if we haven't already seen some other export section. */ SgAsmGenericSectionPtrList §ions = get_sections()->get_sections(); bool seen_exports = false; for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_exports && si!=sections.end(); ++si) seen_exports = isSgAsmPEExportSection(*si); if (seen_exports) { tabsec = new SgAsmGenericSection(get_file(), this); } else { tabsec = new SgAsmPEExportSection(this); } break; } case 1: { /* Sometimes import sections are represented by a ".idata" section, and sometimes they're represented by an * RVA/Size pair, and sometimes both point to the same part of the file. We don't want the imports duplicated * in the AST, so we only create this table as imports if we haven't already seen some other import section. */ SgAsmGenericSectionPtrList §ions = get_sections()->get_sections(); bool seen_imports = false; for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_imports && si!=sections.end(); ++si) seen_imports = isSgAsmPEImportSection(*si); if (seen_imports) { tabsec = new SgAsmGenericSection(get_file(), this); } else { tabsec = new SgAsmPEImportSection(this); } break; } default: { tabsec = new SgAsmGenericSection(get_file(), this); break; } } tabsec->set_name(new SgAsmBasicString(tabname)); tabsec->set_short_name(tabname_short); tabsec->set_synthesized(true); tabsec->set_purpose(SP_HEADER); tabsec->set_offset(file_offset); tabsec->set_size(pair->get_e_size()); tabsec->set_file_alignment(1); tabsec->set_mapped_alignment(1); tabsec->set_mapped_preferred_rva(pair->get_e_rva().get_rva()); tabsec->set_mapped_actual_va(pair->get_e_rva().get_rva()+get_base_va()); /*FIXME: not sure this is correct. [RPM 2009-09-11]*/ tabsec->set_mapped_size(pair->get_e_size()); tabsec->set_mapped_rperm(true); tabsec->set_mapped_wperm(false); tabsec->set_mapped_xperm(false); pair->set_section(tabsec); pair->set_e_rva(pair->get_e_rva().set_section(tabsec)); } /* Now parse the sections */ for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) { SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i]; SgAsmGenericSection *tabsec = pair->get_section(); if (tabsec) tabsec->parse(); } }
bool virtualToPhysicalAddress(VirtualAddress virtualAddress, PhysicalAddress &out) { return sMemoryMap.virtualToPhysicalAddress(virtualAddress, out); }
bool initialiseMemory() { return sMemoryMap.reserve(); }
static void ProcessMultibootInfo(multiboot_info const * const mbi) { // Add multiboot data header g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mbi, sizeof(*mbi)); if (mbi->flags & MULTIBOOT_MEMORY_INFO) { // Add memory map itself g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, mbi->mmap_addr, mbi->mmap_length); const multiboot_mmap_entry* entry = (multiboot_mmap_entry*)mbi->mmap_addr; const multiboot_mmap_entry* end = (multiboot_mmap_entry*)(mbi->mmap_addr + mbi->mmap_length); while (entry < end) { MemoryType type; uint32_t flags; switch (entry->type) { case MULTIBOOT_MEMORY_AVAILABLE: type = MemoryType_Available; flags = 0; break; case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: type = MemoryType_AcpiReclaimable; flags = 0; break; case MULTIBOOT_MEMORY_NVS: type = MemoryType_AcpiNvs; flags = 0; break; case MULTIBOOT_MEMORY_BADRAM: type = MemoryType_Unusable; flags = 0; break; case MULTIBOOT_MEMORY_RESERVED: default: type = MemoryType_Reserved; flags = 0; break; } g_memoryMap.AddBytes(type, flags, entry->addr, entry->len); // Go to next entry entry = (multiboot_mmap_entry*) ((uintptr_t)entry + entry->size + sizeof(entry->size)); } } else if (mbi->flags & MULTIBOOT_INFO_MEMORY) { g_memoryMap.AddBytes(MemoryType_Available, 0, 0, (uint64_t)mbi->mem_lower * 1024); g_memoryMap.AddBytes(MemoryType_Available, 0, 1024*1024, (uint64_t)mbi->mem_upper * 1024); } if (mbi->flags & MULTIBOOT_INFO_MODS) { const multiboot_module* modules = (multiboot_module*)mbi->mods_addr; for (uint32_t i = 0; i != mbi->mods_count; ++i) { const multiboot_module* module = &modules[i]; if (strcmp(module->string, "initrd")==0) { g_bootInfo.initrdAddress = module->mod_start; g_bootInfo.initrdSize = module->mod_end - module->mod_start; } g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, module->mod_start, module->mod_end - module->mod_start); } } if (mbi->flags & MULTIBOOT_INFO_FRAMEBUFFER_INFO) { switch (mbi->framebuffer_type) { case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: { const auto redMask = ((1 << mbi->framebuffer_red_mask_size) - 1) << mbi->framebuffer_red_field_position; const auto greenMask = ((1 << mbi->framebuffer_green_mask_size) - 1) << mbi->framebuffer_green_field_position; const auto blueMask = ((1 << mbi->framebuffer_blue_mask_size) - 1) << mbi->framebuffer_blue_field_position; const auto pixelMask = mbi->framebuffer_bpp < 32 ? (1 << mbi->framebuffer_bpp) - 1 : -1; const auto reservedMask = pixelMask ^ redMask ^ greenMask ^ blueMask; g_frameBuffer.width = mbi->framebuffer_width; g_frameBuffer.height = mbi->framebuffer_height; g_frameBuffer.pitch = mbi->framebuffer_pitch; g_frameBuffer.pixels = (void*)mbi->framebuffer_addr; g_frameBuffer.format = DeterminePixelFormat(redMask, greenMask, blueMask, reservedMask); } break; case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: { // OK to initialize VgaConsole here since it doesn't allocate any memory // g_vgaConsole.Initialize((void*)mbi->framebuffer_addr, mbi->framebuffer_width, mbi->framebuffer_height); // g_console = &g_vgaConsole; } break; } } }
void* AllocatePages(size_t pageCount, physaddr_t maxAddress) { const physaddr_t memory = g_memoryMap.AllocatePages(MemoryType_Bootloader, pageCount, maxAddress); return memory == MEMORY_ALLOC_FAILED ? nullptr : (void*)memory; }
extern "C" void multiboot_main(unsigned int magic, void* mbi) { // 0x00000000 - 0x000003FF - Interrupt Vector Table // 0x00000400 - 0x000004FF - BIOS Data Area (BDA) // 0x00000500 - 0x000005FF - ROM BASIC (still used / reclaimed by some BIOS) g_memoryMap.AddBytes(MemoryType_Bootloader, 0, 0, 0x600); // Process multiboot info bool gotMultibootInfo = false; // Add bootloader (ourself) to memory map extern const char ImageBase[]; extern const char ImageEnd[]; const physaddr_t start = (physaddr_t)&ImageBase; const physaddr_t end = (physaddr_t)&ImageEnd; g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, start, end - start); if (magic == MULTIBOOT_BOOTLOADER_MAGIC && mbi) { ProcessMultibootInfo(static_cast<multiboot_info*>(mbi)); gotMultibootInfo = true; } else if (magic== MULTIBOOT2_BOOTLOADER_MAGIC && mbi) { ProcessMultibootInfo(static_cast<multiboot2_info*>(mbi)); gotMultibootInfo = true; } // Now that the memory allocator is initialized, we can create GraphicsConsole if (gotMultibootInfo) { if (g_frameBuffer.format != PIXFMT_UNKNOWN) { g_graphicsConsole.Initialize(&g_frameBuffer); g_console = &g_graphicsConsole; Framebuffer* fb = &g_bootInfo.framebuffers[g_bootInfo.framebufferCount]; fb->width = g_frameBuffer.width; fb->height = g_frameBuffer.height; fb->pitch = g_frameBuffer.pitch; fb->format = g_frameBuffer.format; fb->pixels = (uintptr_t)g_frameBuffer.pixels; g_bootInfo.framebufferCount += 1; } else if (!g_console) { // // Assume a standard VGA card at 0xB8000 // g_vgaConsole.Initialize((void*)0x000B8000, 80, 25); // g_console = &g_vgaConsole; } } g_console->Rainbow(); Log(" BIOS Bootloader (" STRINGIZE(KERNEL_ARCH) ")\n\n"); if (gotMultibootInfo) { // InstallBiosTrampoline(); // g_display.Initialize(); // for (int i = 0; i != g_display.GetModeCount(); ++i) // { // DisplayMode mode; // g_display.GetMode(i, &mode); // if (mode.format == PIXFMT_X8R8G8B8) // { // //Log("Mode %d: %d x %d - %d\n", i, mode.width, mode.height, mode.format); // } // } // Boot! Boot((void*)g_bootInfo.initrdAddress, g_bootInfo.initrdSize); } else { Fatal(" No multiboot information!\n"); } }
static void ProcessMultibootInfo(multiboot2_info const * const mbi) { // Add multiboot data header g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mbi, mbi->total_size); const multiboot2_tag_basic_meminfo* meminfo = NULL; const multiboot2_tag_mmap* mmap = NULL; for (multiboot2_tag* tag = (multiboot2_tag*)(mbi + 1); tag->type != MULTIBOOT2_TAG_TYPE_END; tag = (multiboot2_tag*) align_up((uintptr_t)tag + tag->size, MULTIBOOT2_TAG_ALIGN)) { switch (tag->type) { case MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO: meminfo = (multiboot2_tag_basic_meminfo*)tag; break; case MULTIBOOT2_TAG_TYPE_MMAP: mmap = (multiboot2_tag_mmap*)tag; break; case MULTIBOOT2_TAG_TYPE_MODULE: { const multiboot2_module* module = (multiboot2_module*)tag; if (strcmp(module->string, "initrd")==0) { g_bootInfo.initrdAddress = module->mod_start; g_bootInfo.initrdSize = module->mod_end - module->mod_start; } g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, module->mod_start, module->mod_end - module->mod_start); } break; case MULTIBOOT2_TAG_TYPE_FRAMEBUFFER: { const multiboot2_tag_framebuffer* mbi = (multiboot2_tag_framebuffer*)tag; switch (mbi->common.framebuffer_type) { case MULTIBOOT2_FRAMEBUFFER_TYPE_RGB: { const auto redMask = ((1 << mbi->framebuffer_red_mask_size) - 1) << mbi->framebuffer_red_field_position; const auto greenMask = ((1 << mbi->framebuffer_green_mask_size) - 1) << mbi->framebuffer_green_field_position; const auto blueMask = ((1 << mbi->framebuffer_blue_mask_size) - 1) << mbi->framebuffer_blue_field_position; const auto pixelMask = mbi->common.framebuffer_bpp < 32 ? (1 << mbi->common.framebuffer_bpp) - 1 : -1; const auto reservedMask = pixelMask ^ redMask ^ greenMask ^ blueMask; g_frameBuffer.width = mbi->common.framebuffer_width; g_frameBuffer.height = mbi->common.framebuffer_height; g_frameBuffer.pitch = mbi->common.framebuffer_pitch; g_frameBuffer.pixels = (void*)mbi->common.framebuffer_addr; g_frameBuffer.format = DeterminePixelFormat(redMask, greenMask, blueMask, reservedMask); } break; case MULTIBOOT2_FRAMEBUFFER_TYPE_EGA_TEXT: { // OK to initialize VgaConsole here since it doesn't allocate any memory // g_vgaConsole.Initialize((void*)mbi->common.framebuffer_addr, mbi->common.framebuffer_width, mbi->common.framebuffer_height); // g_console = &g_vgaConsole; } break; } } break; } } if (mmap) { // Add memory map itself g_memoryMap.AddBytes(MemoryType_Bootloader, MemoryFlag_ReadOnly, (uintptr_t)mmap->entries, mmap->size); const multiboot2_mmap_entry* entry = mmap->entries; const multiboot2_mmap_entry* end = (multiboot2_mmap_entry*) ((uintptr_t)mmap + mmap->size); while (entry < end) { MemoryType type; uint32_t flags; switch (entry->type) { case MULTIBOOT2_MEMORY_AVAILABLE: type = MemoryType_Available; flags = 0; break; case MULTIBOOT2_MEMORY_ACPI_RECLAIMABLE: type = MemoryType_AcpiReclaimable; flags = 0; break; case MULTIBOOT2_MEMORY_NVS: type = MemoryType_AcpiNvs; flags = 0; break; case MULTIBOOT2_MEMORY_BADRAM: type = MemoryType_Unusable; flags = 0; break; case MULTIBOOT2_MEMORY_RESERVED: default: type = MemoryType_Reserved; flags = 0; break; } g_memoryMap.AddBytes(type, flags, entry->addr, entry->len); // Go to next entry entry = (multiboot2_mmap_entry*) ((uintptr_t)entry + mmap->entry_size); } } else if (meminfo) { g_memoryMap.AddBytes(MemoryType_Available, 0, 0, (uint64_t)meminfo->mem_lower * 1024); g_memoryMap.AddBytes(MemoryType_Available, 0, 1024*1024, (uint64_t)meminfo->mem_upper * 1024); } }
MemoryCacheLayer(CachePolicy *policy, CacheLayer *tryNext) : CacheLayer(tryNext), mData(NULL, policy) { mData.setOwner(this);//to avoid warning in visual studio }
static inline bool isGoodAddr(const std::set<rose_addr_t> &goodVas, const MemoryMap &map, rose_addr_t va) { return !map.at(va).exists() || goodVas.find(va)!=goodVas.end(); }