Skip to content

Commit

Permalink
[mips] Merging PR #6013: adding mips3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
galenbwill committed Feb 10, 2025
1 parent b4e75ef commit 840072d
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 50 deletions.
59 changes: 40 additions & 19 deletions arch/mips/arch_mips.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -402,8 +407,8 @@ class MipsArchitecture: public Architecture
}

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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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());
Expand Down
158 changes: 129 additions & 29 deletions arch/mips/mips/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
14 changes: 12 additions & 2 deletions platform/linux/platform_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit 840072d

Please sign in to comment.