#include #include #include #include namespace FxOS { OS::OS(File &file): m_target() { /* OS files are all at least 1 MB large */ if(file.size() < 1000000) throw std::runtime_error("OS files cannot be < 1MB"); /* Bind the given file to the internal analysis target */ m_target.bind_region(MemoryRegion::ROM, file); m_target.bind_region(MemoryRegion::ROM_P2, file); parse_version(); parse_syscall_table(); // parse_footer(); } void OS::parse_version() { /* Extract the version string at 0x10020 */ Target &t = m_target; char *version = (char *)t.translate(0x80010020, 10); m_version = std::string(version, 10); } //--- // Syscalle resolution //--- int OS::syscall_count() const noexcept { return m_syscall_table.size(); } uint32_t OS::syscall(int id) const { return m_syscall_table[id]; } int OS::find_syscall(uint32_t entry) const noexcept { try { return m_syscall_addresses.at(entry); } catch(std::out_of_range &e) { return -1; } } void OS::parse_syscall_table() { Target &t = m_target; /* Traverse the syscall table */ uint32_t syscall_table = t.read_u32(0x8001007c); int id = 0; while(1) { uint32_t entry = t.read_u32(syscall_table + 4 * id); MemoryRegion const *r = MemoryRegion::region_for(entry); if(!r) break; m_syscall_table.push_back(entry); m_syscall_addresses[entry] = id; id++; } } //--- // Footer search //--- uint32_t OS::footer() const noexcept { return m_footer; } void OS::parse_footer() { /* Find the footer address (last occurrence of "CASIOABSLangdata") */ uint32_t start = MemoryRegion::ROM.start; uint32_t end = MemoryRegion::ROM.end; m_target.search(start, end, "CASIOABSLangdata", 16); #if 0 char const *signature = "CASIOABSLangdata"; void *occ = NULL, *next = memmem(os->data, os->len, signature, 16); void *end = os->data + os->len; while(next) { occ = next; next = memmem(next + 1, end - (next + 1), signature, 16); } os->footer = (occ) ? (occ - os->data) : (uint32_t)-1; #endif } } /* namespace FxOS */