summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/mips/arch_mips.cpp59
-rw-r--r--arch/mips/mips/test.c158
-rw-r--r--platform/linux/platform_linux.cpp14
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);
}