summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/mips/arch_mips.cpp13
-rw-r--r--platform/linux/platform_linux.cpp25
2 files changed, 32 insertions, 6 deletions
diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp
index ea7c2fca..bb1873f2 100644
--- a/arch/mips/arch_mips.cpp
+++ b/arch/mips/arch_mips.cpp
@@ -20,6 +20,7 @@ using namespace std;
#endif
#define E_MIPS_MACH_5900 0x00920000
+#define EF_MIPS_ABI2 0x00000020
uint32_t bswap32(uint32_t x)
{
@@ -2867,7 +2868,7 @@ public:
class MipsN64CallingConvention: public CallingConvention
{
public:
- MipsN64CallingConvention(Architecture* arch): CallingConvention(arch, "n64")
+ MipsN64CallingConvention(Architecture* arch, const std::string& name = "n64"): CallingConvention(arch, name)
{
}
@@ -3690,6 +3691,9 @@ static Ref<Platform> ElfFlagsRecognize(BinaryView* view, Metadata* metadata)
}
uint64_t flagsValue = flagsMetadata->GetUnsignedInteger();
+ if (flagsValue & EF_MIPS_ABI2)
+ return Platform::GetByName(endianness == BigEndian ? "linux-mipsn32" : "linux-mipsn32el");
+
uint8_t machineVariant = (flagsValue >> 16) & 0xff;
switch (machineVariant)
@@ -3749,6 +3753,8 @@ extern "C"
/* calling conventions */
MipsO32CallingConvention* o32LE = new MipsO32CallingConvention(mipsel);
MipsO32CallingConvention* o32BE = new MipsO32CallingConvention(mipseb);
+ MipsN64CallingConvention* n32LE = new MipsN64CallingConvention(mips64el, "n32");
+ MipsN64CallingConvention* n32BE = new MipsN64CallingConvention(mips64eb, "n32");
MipsN64CallingConvention* n64LE = new MipsN64CallingConvention(mips64el);
MipsN64CallingConvention* n64BE = new MipsN64CallingConvention(mips64eb);
MipsN64CallingConvention* n64BEc = new MipsN64CallingConvention(cnmips64eb);
@@ -3764,6 +3770,8 @@ extern "C"
mips3->SetDefaultCallingConvention(o32BE);
mips3el->RegisterCallingConvention(o32LE);
mips3el->SetDefaultCallingConvention(o32LE);
+ mips64el->RegisterCallingConvention(n32LE);
+ mips64eb->RegisterCallingConvention(n32BE);
mips64el->RegisterCallingConvention(n64LE);
mips64el->SetDefaultCallingConvention(n64LE);
mips64eb->RegisterCallingConvention(n64BE);
@@ -3842,7 +3850,8 @@ extern "C"
{
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS64, LittleEndian, ElfFlagsRecognize);
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS64, BigEndian, ElfFlagsRecognize);
- elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, LittleEndian, ElfFlagsRecognize); // R5900
+ elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, LittleEndian, ElfFlagsRecognize); // n32, R5900
+ elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, BigEndian, ElfFlagsRecognize); // n32
}
BinaryViewType::RegisterArchitecture("PE", 0x166, LittleEndian, mipsel);
diff --git a/platform/linux/platform_linux.cpp b/platform/linux/platform_linux.cpp
index f2902068..ff8134f7 100644
--- a/platform/linux/platform_linux.cpp
+++ b/platform/linux/platform_linux.cpp
@@ -275,12 +275,16 @@ public:
class LinuxMips64Platform: public Platform
{
+private:
+ size_t m_addressSize;
+
public:
- LinuxMips64Platform(Architecture* arch, const std::string& name): Platform(arch, name)
+ LinuxMips64Platform(Architecture* arch, const std::string& name, const std::string& callingConventionName = "n64", size_t addressSize = 0):
+ Platform(arch, name), m_addressSize(addressSize)
{
Ref<CallingConvention> cc;
- cc = arch->GetCallingConventionByName("n64");
+ cc = arch->GetCallingConventionByName(callingConventionName);
if (cc)
{
RegisterDefaultCallingConvention(cc);
@@ -293,6 +297,13 @@ public:
if (cc)
SetSystemCallConvention(cc);
}
+
+ virtual size_t GetAddressSize() const override
+ {
+ if (m_addressSize)
+ return m_addressSize;
+ return GetArchitecture()->GetAddressSize();
+ }
};
@@ -543,17 +554,21 @@ extern "C"
Ref<Architecture> mipseb = Architecture::GetByName("mips32");
Ref<Architecture> mips3el = Architecture::GetByName("mipsel3");
Ref<Architecture> mips3eb = Architecture::GetByName("mips3");
+ Ref<Architecture> mips64el = Architecture::GetByName("mipsel64");
Ref<Architecture> mips64eb = Architecture::GetByName("mips64");
Ref<Architecture> cnmips64eb = Architecture::GetByName("cavium-mips64");
Ref<Architecture> cnmips64el = Architecture::GetByName("cavium-mipsel64");
- if (mipsel && mipseb && mips64eb && cnmips64eb && cnmips64el && mips3el && mips3eb)
+ if (mipsel && mipseb && mips64el && mips64eb && cnmips64eb && cnmips64el && mips3el && mips3eb)
{
- Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn, platformLE64cn, platform3LE, platform3BE;
+ Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn, platformLE64cn, platform3LE, platform3BE,
+ platformN32LE, platformN32BE;
platformLE = new LinuxMipsPlatform(mipsel, "linux-mipsel");
platformBE = new LinuxMipsPlatform(mipseb, "linux-mips");
platform3LE = new LinuxMipsPlatform(mips3el, "linux-mipsel3");
platform3BE = new LinuxMipsPlatform(mips3eb, "linux-mips3");
+ platformN32LE = new LinuxMips64Platform(mips64el, "linux-mipsn32el", "n32", 4);
+ platformN32BE = new LinuxMips64Platform(mips64eb, "linux-mipsn32", "n32", 4);
platformBE64 = new LinuxMips64Platform(mips64eb, "linux-mips64");
platformBE64cn = new LinuxMips64Platform(cnmips64eb, "linux-cnmips64");
platformLE64cn = new LinuxMips64Platform(cnmips64el, "linux-cnmipsel64");
@@ -561,6 +576,8 @@ extern "C"
Platform::Register("linux", platformBE);
Platform::Register("linux", platform3LE);
Platform::Register("linux", platform3BE);
+ Platform::Register("linux", platformN32LE);
+ Platform::Register("linux", platformN32BE);
Platform::Register("linux", platformBE64);
Platform::Register("linux", platformBE64cn);
Platform::Register("linux", platformLE64cn);