diff options
| -rw-r--r-- | arch/mips/arch_mips.cpp | 59 | ||||
| -rw-r--r-- | arch/mips/mips/test.c | 158 | ||||
| -rw-r--r-- | platform/linux/platform_linux.cpp | 14 |
3 files changed, 181 insertions, 50 deletions
diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp index 4079519a..ddb78e42 100644 --- a/arch/mips/arch_mips.cpp +++ b/arch/mips/arch_mips.cpp @@ -181,20 +181,25 @@ class MipsArchitecture: public Architecture protected: size_t m_bits; BNEndianness m_endian; + MipsVersion version_overwrite; uint32_t m_decomposeFlags; virtual bool Disassemble(const uint8_t* data, uint64_t addr, size_t maxLen, Instruction& result) { + MipsVersion version = version_overwrite; + memset(&result, 0, sizeof(result)); - if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_decomposeFlags) != 0) + if (m_bits == 64) + { + version = MIPS_64; + } + + if (mips_decompose((uint32_t*)data, maxLen, &result, version, addr, m_endian, m_decomposeFlags) != 0) return false; return true; } - virtual size_t GetAddressSize() const override - { - return m_bits / 8; - } + virtual size_t GetAddressSize() const override { return m_bits / 8; } size_t InstructionHasBranchDelay(const Instruction& instr) { @@ -402,8 +407,8 @@ protected: } public: - MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, uint32_t decomposeFlags = 0) - : Architecture(name), m_bits(bits), m_endian(endian), m_decomposeFlags(decomposeFlags) + MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, MipsVersion version_in, uint32_t decomposeFlags = 0) + : Architecture(name), m_bits(bits), m_endian(endian), version_overwrite(version_in), m_decomposeFlags(decomposeFlags) { Ref<Settings> settings = Settings::Instance(); uint32_t flag_pseudo_ops = settings->Get<bool>("arch.mips.disassembly.pseudoOps") ? DECOMPOSE_FLAGS_PSEUDO_OP : 0; @@ -3258,14 +3263,18 @@ extern "C" { InitMipsSettings(); - Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32); - Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32); - Architecture* mips64el = new MipsArchitecture("mipsel64", LittleEndian, 64); - Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64); - Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, DECOMPOSE_FLAGS_CAVIUM); + Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32, MIPS_32); + Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32, MIPS_32); + Architecture* mips3 = new MipsArchitecture("mips3", BigEndian, 32, MIPS_3); + Architecture* mips3el = new MipsArchitecture("mipsel3", LittleEndian, 32, MIPS_3); + Architecture* mips64el = new MipsArchitecture("mipsel64", LittleEndian, 64, MIPS_64); + Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64, MIPS_64); + Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, MIPS_64, DECOMPOSE_FLAGS_CAVIUM); - Architecture::Register(mipsel); Architecture::Register(mipseb); + Architecture::Register(mipsel); + Architecture::Register(mips3); + Architecture::Register(mips3el); Architecture::Register(mips64el); Architecture::Register(mips64eb); Architecture::Register(cnmips64eb); @@ -3277,10 +3286,14 @@ extern "C" MipsN64CallingConvention* n64BE = new MipsN64CallingConvention(mips64eb); MipsN64CallingConvention* n64BEc = new MipsN64CallingConvention(cnmips64eb); - mipsel->RegisterCallingConvention(o32LE); mipseb->RegisterCallingConvention(o32BE); - mipsel->SetDefaultCallingConvention(o32LE); mipseb->SetDefaultCallingConvention(o32BE); + mipsel->RegisterCallingConvention(o32LE); + mipsel->SetDefaultCallingConvention(o32LE); + mips3->RegisterCallingConvention(o32BE); + mips3->SetDefaultCallingConvention(o32BE); + mips3->RegisterCallingConvention(o32LE); + mips3->SetDefaultCallingConvention(o32LE); mips64el->RegisterCallingConvention(n64LE); mips64el->SetDefaultCallingConvention(n64LE); mips64eb->RegisterCallingConvention(n64BE); @@ -3290,21 +3303,29 @@ extern "C" MipsLinuxSyscallCallingConvention* linuxSyscallLE = new MipsLinuxSyscallCallingConvention(mipsel); MipsLinuxSyscallCallingConvention* linuxSyscallBE = new MipsLinuxSyscallCallingConvention(mipseb); - mipsel->RegisterCallingConvention(linuxSyscallLE); mipseb->RegisterCallingConvention(linuxSyscallBE); + mipsel->RegisterCallingConvention(linuxSyscallLE); + mips3->RegisterCallingConvention(linuxSyscallBE); + mips3el->RegisterCallingConvention(linuxSyscallLE); - mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel)); mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb)); + mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel)); + mips3->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3)); + mips3el->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3el)); mips64el->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64el)); mips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64eb)); cnmips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(cnmips64eb)); /* function recognizers */ - mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); mipseb->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); + mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); + mips3->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); + mips3el->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); - mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mipseb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); + mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); + mips3->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); + mips3el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mips64el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); cnmips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); diff --git a/arch/mips/mips/test.c b/arch/mips/mips/test.c index c2bf6333..df009043 100644 --- a/arch/mips/mips/test.c +++ b/arch/mips/mips/test.c @@ -5,13 +5,14 @@ b mips_decompose b mips_disassemble */ +#include <errno.h> #include <stdio.h> #include <stdint.h> #include <inttypes.h> #include "mips.h" -int disassemble(uint32_t insword, uint64_t address, enum MipsVersion version, char *result) +int disassemble(uint32_t insword, uint64_t address, MipsVersion version, int flags, char *result) { int rc; Instruction instr; @@ -35,47 +36,146 @@ int disassemble(uint32_t insword, uint64_t address, enum MipsVersion version, ch } #define ASSERT(X) \ - if(!(X)) { \ + do { if(!(X)) { \ printf("failed assert() at %s:%d\n", __FILE__, __LINE__); \ exit(-1); \ - } + } } while(0) + + +void usage(char** av) +{ + printf("usage:\n"); + printf("\t%s [-mips32|-mips64|-mips1|-mips2|-mips3|-mips4|-cavium] [-a BASEADDR] [instruction_words]+\n", av[0]); + printf("\t\tdisassemble for the given MIPS version (MIPS32 by default)\n"); + printf("\t\tBASEADDR must be an unsigned 32-bit integer in hexadecimal\n"); + printf("\t%s test\n", av[0]); + printf("example:\n"); + printf("\t%s 0c1001dc 8ca40000 2c410020 10200013\n", av[0]); + printf("\t%s test\n", av[0]); + exit(-1); +} int main(int ac, char **av) { char instxt[4096]; + uint32_t insword = 0; + uint64_t baseaddr = 0; + int instindex = 1; + int c = 0; + int version = -1; + int flags = 0; + int result = 0; - if(ac == 1) { - printf("usage:\n"); - printf("\t%s [<address>] <instruction_word>\n", av[0]); - printf("\t%s <instruction_word>\n", av[0]); - printf("\t%s test\n", av[0]); - printf("examples:\n"); - printf("\t%s 0 14E00003\n", av[0]); - printf("\t%s 00405A58 14E00003\n", av[0]); - printf("\t%s test\n", av[0]); - exit(-1); + if (ac > 1) { + if (!strcmp("-mips64", av[1])) + version = MIPS_64; + else if (!strcmp("-mips32", av[1])) + version = MIPS_32; + else if (!strcmp("-mips1", av[1])) + version = MIPS_1; + else if (!strcmp("-mips2", av[1])) + version = MIPS_2; + else if (!strcmp("-mips3", av[1])) + version = MIPS_3; + else if (!strcmp("-mips4", av[1])) + version = MIPS_4; + else if (!strcmp("-cavium", av[1])) + { + version = MIPS_64; + flags = DECOMPOSE_FLAGS_CAVIUM; + } + else if (!strcmp("-a", av[1])) + ; + else if (av[1][0] == '-') + { + usage(av); + goto cleanup; + } + if (version != -1) + { + instindex++; + } } + if (version == -1) + version = MIPS_32; - if(ac == 2 && !strcmp(av[1], "test")) { - disassemble(0x14E00003, 0, MIPS_32, instxt); - ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x10")); - disassemble(0x14E00003, 0x405a58, MIPS_32, instxt); - ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x405a68")); + if (instindex < ac && !strcmp(av[instindex], "test")) + { + insword = 0x14E00003; + baseaddr = 0; + if (0 == disassemble(insword, baseaddr, version, flags, instxt)) + { + printf("%08llX: %08X %s\n", baseaddr, insword, instxt); + } + else + { + printf("%08llX: %08X ??\n", baseaddr, insword); + } + // disassemble(0x14E00003, 0, version, flags, instxt); + if (version < MIPS_32) + ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x10")); + else + ASSERT(!strcmp(instxt, "bnez\t$a3, 0x10")); + baseaddr = 0x405a58; + if (0 == disassemble(insword, baseaddr, version, flags, instxt)) + { + printf("%08llX: %08X %s\n", baseaddr, insword, instxt); + } + else + { + printf("%08llX: %08X ??\n", baseaddr, insword); + } + // disassemble(0x14E00003, 4, version, flags, instxt); + if (version < MIPS_32) + ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x405a68")); + else + ASSERT(!strcmp(instxt, "bnez\t$a3, 0x405a68")); exit(0); } - uint64_t address = 0; - uint32_t insword = 0; - if(ac == 2) { - address = 0; - insword = strtoul(av[1], NULL, 16); - } - else if(ac == 3) { - address = strtoul(av[1], NULL, 16); - insword = strtoul(av[2], NULL, 16); + if (instindex < ac && !strcmp(av[instindex], "-a")) { + if (ac <= ++instindex) { + printf("ERROR: Missing argument for -a\n"); + usage(av); + result = -1; + goto cleanup; + } + errno = 0; + char *endptr; + char *addr = av[instindex]; + if (addr[0] == '0' && addr[1] == 'x') + addr += 2; + baseaddr = strtoul(addr, &endptr, 16); + if (errno == EINVAL || errno == ERANGE || (addr[0] != '\0' && (*(void **) endptr) == addr)) { + printf("ERROR: Invalid argument for -a: \"%s\"\n", av[instindex]); + usage(av); + result = -1; + goto cleanup; + } + if (ac <= ++instindex) { + usage(av); + result = -1; + goto cleanup; + } } - if(0 == disassemble(insword, address, MIPS_32, instxt)) { - printf("%08" PRIX64 ": %08X %s\n", address, insword, instxt); + while (instindex < ac) + { + insword = strtoul(av[instindex], NULL, 16); + + if (0 == disassemble(insword, baseaddr, version, flags, instxt)) + { + printf("%08llX: %08X %s\n", baseaddr, insword, instxt); + } + else + { + printf("%08llX: %08X ??\n", baseaddr, insword); + } + + baseaddr += 4; + instindex++; } + +cleanup: + return result; } diff --git a/platform/linux/platform_linux.cpp b/platform/linux/platform_linux.cpp index 9a57c430..0a70f5b5 100644 --- a/platform/linux/platform_linux.cpp +++ b/platform/linux/platform_linux.cpp @@ -352,27 +352,37 @@ extern "C" Ref<Architecture> mipsel = Architecture::GetByName("mipsel32"); Ref<Architecture> mipseb = Architecture::GetByName("mips32"); + Ref<Architecture> mips3el = Architecture::GetByName("mipsel3"); + Ref<Architecture> mips3eb = Architecture::GetByName("mips3"); Ref<Architecture> mips64eb = Architecture::GetByName("mips64"); Ref<Architecture> cnmips64eb = Architecture::GetByName("cavium-mips64"); - if (mipsel && mipseb && mips64eb && cnmips64eb) + if (mipsel && mipseb && mips64eb && cnmips64eb && mips3el && mips3eb) { - Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn; + Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn, platform3LE, platform3BE; platformLE = new LinuxMipsPlatform(mipsel, "linux-mipsel"); platformBE = new LinuxMipsPlatform(mipseb, "linux-mips"); + platform3LE = new LinuxMipsPlatform(mips3el, "linux-mipsel3"); + platform3BE = new LinuxMipsPlatform(mips3eb, "linux-mips3"); platformBE64 = new LinuxMips64Platform(mips64eb, "linux-mips64"); platformBE64cn = new LinuxMips64Platform(cnmips64eb, "linux-cnmips64"); Platform::Register("linux", platformLE); Platform::Register("linux", platformBE); + Platform::Register("linux", platform3LE); + Platform::Register("linux", platform3BE); Platform::Register("linux", platformBE64); Platform::Register("linux", platformBE64cn); // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one BinaryViewType::RegisterPlatform("ELF", 0, mipsel, platformLE); BinaryViewType::RegisterPlatform("ELF", 0, mipseb, platformBE); + BinaryViewType::RegisterPlatform("ELF", 0, mips3el, platform3LE); + BinaryViewType::RegisterPlatform("ELF", 0, mips3eb, platform3BE); BinaryViewType::RegisterPlatform("ELF", 0, mips64eb, platformBE64); BinaryViewType::RegisterPlatform("ELF", 0, cnmips64eb, platformBE64cn); BinaryViewType::RegisterPlatform("ELF", 3, mipsel, platformLE); BinaryViewType::RegisterPlatform("ELF", 3, mipseb, platformBE); + BinaryViewType::RegisterPlatform("ELF", 3, mips3el, platform3LE); + BinaryViewType::RegisterPlatform("ELF", 3, mips3eb, platform3BE); BinaryViewType::RegisterPlatform("ELF", 3, mips64eb, platformBE64); BinaryViewType::RegisterPlatform("ELF", 3, cnmips64eb, platformBE64cn); } |
