Skip to content

Commit 6bc36d9

Browse files
committed
Better MIPS n32 support.
1 parent c1b0eb7 commit 6bc36d9

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

arch/mips/arch_mips.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ using namespace std;
2020
#endif
2121

2222
#define E_MIPS_MACH_5900 0x00920000
23+
#define EF_MIPS_ABI2 0x00000020
2324

2425
uint32_t bswap32(uint32_t x)
2526
{
@@ -2867,7 +2868,7 @@ class MipsPS2CallingConvention: public CallingConvention
28672868
class MipsN64CallingConvention: public CallingConvention
28682869
{
28692870
public:
2870-
MipsN64CallingConvention(Architecture* arch): CallingConvention(arch, "n64")
2871+
MipsN64CallingConvention(Architecture* arch, const std::string& name = "n64"): CallingConvention(arch, name)
28712872
{
28722873
}
28732874

@@ -3690,6 +3691,9 @@ static Ref<Platform> ElfFlagsRecognize(BinaryView* view, Metadata* metadata)
36903691
}
36913692

36923693
uint64_t flagsValue = flagsMetadata->GetUnsignedInteger();
3694+
if (flagsValue & EF_MIPS_ABI2)
3695+
return Platform::GetByName(endianness == BigEndian ? "linux-mipsn32" : "linux-mipsn32el");
3696+
36933697
uint8_t machineVariant = (flagsValue >> 16) & 0xff;
36943698

36953699
switch (machineVariant)
@@ -3749,6 +3753,8 @@ extern "C"
37493753
/* calling conventions */
37503754
MipsO32CallingConvention* o32LE = new MipsO32CallingConvention(mipsel);
37513755
MipsO32CallingConvention* o32BE = new MipsO32CallingConvention(mipseb);
3756+
MipsN64CallingConvention* n32LE = new MipsN64CallingConvention(mips64el, "n32");
3757+
MipsN64CallingConvention* n32BE = new MipsN64CallingConvention(mips64eb, "n32");
37523758
MipsN64CallingConvention* n64LE = new MipsN64CallingConvention(mips64el);
37533759
MipsN64CallingConvention* n64BE = new MipsN64CallingConvention(mips64eb);
37543760
MipsN64CallingConvention* n64BEc = new MipsN64CallingConvention(cnmips64eb);
@@ -3764,6 +3770,8 @@ extern "C"
37643770
mips3->SetDefaultCallingConvention(o32BE);
37653771
mips3el->RegisterCallingConvention(o32LE);
37663772
mips3el->SetDefaultCallingConvention(o32LE);
3773+
mips64el->RegisterCallingConvention(n32LE);
3774+
mips64eb->RegisterCallingConvention(n32BE);
37673775
mips64el->RegisterCallingConvention(n64LE);
37683776
mips64el->SetDefaultCallingConvention(n64LE);
37693777
mips64eb->RegisterCallingConvention(n64BE);
@@ -3842,7 +3850,8 @@ extern "C"
38423850
{
38433851
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS64, LittleEndian, ElfFlagsRecognize);
38443852
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS64, BigEndian, ElfFlagsRecognize);
3845-
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, LittleEndian, ElfFlagsRecognize); // R5900
3853+
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, LittleEndian, ElfFlagsRecognize); // n32, R5900
3854+
elf->RegisterPlatformRecognizer(ARCH_ID_MIPS32, BigEndian, ElfFlagsRecognize); // n32
38463855
}
38473856

38483857
BinaryViewType::RegisterArchitecture("PE", 0x166, LittleEndian, mipsel);

platform/linux/platform_linux.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,16 @@ class LinuxMipsPlatform: public Platform
275275

276276
class LinuxMips64Platform: public Platform
277277
{
278+
private:
279+
size_t m_addressSize;
280+
278281
public:
279-
LinuxMips64Platform(Architecture* arch, const std::string& name): Platform(arch, name)
282+
LinuxMips64Platform(Architecture* arch, const std::string& name, const std::string& callingConventionName = "n64", size_t addressSize = 0):
283+
Platform(arch, name), m_addressSize(addressSize)
280284
{
281285
Ref<CallingConvention> cc;
282286

283-
cc = arch->GetCallingConventionByName("n64");
287+
cc = arch->GetCallingConventionByName(callingConventionName);
284288
if (cc)
285289
{
286290
RegisterDefaultCallingConvention(cc);
@@ -293,6 +297,13 @@ class LinuxMips64Platform: public Platform
293297
if (cc)
294298
SetSystemCallConvention(cc);
295299
}
300+
301+
virtual size_t GetAddressSize() const override
302+
{
303+
if (m_addressSize)
304+
return m_addressSize;
305+
return GetArchitecture()->GetAddressSize();
306+
}
296307
};
297308

298309

@@ -543,24 +554,30 @@ extern "C"
543554
Ref<Architecture> mipseb = Architecture::GetByName("mips32");
544555
Ref<Architecture> mips3el = Architecture::GetByName("mipsel3");
545556
Ref<Architecture> mips3eb = Architecture::GetByName("mips3");
557+
Ref<Architecture> mips64el = Architecture::GetByName("mipsel64");
546558
Ref<Architecture> mips64eb = Architecture::GetByName("mips64");
547559
Ref<Architecture> cnmips64eb = Architecture::GetByName("cavium-mips64");
548560
Ref<Architecture> cnmips64el = Architecture::GetByName("cavium-mipsel64");
549-
if (mipsel && mipseb && mips64eb && cnmips64eb && cnmips64el && mips3el && mips3eb)
561+
if (mipsel && mipseb && mips64el && mips64eb && cnmips64eb && cnmips64el && mips3el && mips3eb)
550562
{
551-
Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn, platformLE64cn, platform3LE, platform3BE;
563+
Ref<Platform> platformLE, platformBE, platformBE64, platformBE64cn, platformLE64cn, platform3LE, platform3BE,
564+
platformN32LE, platformN32BE;
552565

553566
platformLE = new LinuxMipsPlatform(mipsel, "linux-mipsel");
554567
platformBE = new LinuxMipsPlatform(mipseb, "linux-mips");
555568
platform3LE = new LinuxMipsPlatform(mips3el, "linux-mipsel3");
556569
platform3BE = new LinuxMipsPlatform(mips3eb, "linux-mips3");
570+
platformN32LE = new LinuxMips64Platform(mips64el, "linux-mipsn32el", "n32", 4);
571+
platformN32BE = new LinuxMips64Platform(mips64eb, "linux-mipsn32", "n32", 4);
557572
platformBE64 = new LinuxMips64Platform(mips64eb, "linux-mips64");
558573
platformBE64cn = new LinuxMips64Platform(cnmips64eb, "linux-cnmips64");
559574
platformLE64cn = new LinuxMips64Platform(cnmips64el, "linux-cnmipsel64");
560575
Platform::Register("linux", platformLE);
561576
Platform::Register("linux", platformBE);
562577
Platform::Register("linux", platform3LE);
563578
Platform::Register("linux", platform3BE);
579+
Platform::Register("linux", platformN32LE);
580+
Platform::Register("linux", platformN32BE);
564581
Platform::Register("linux", platformBE64);
565582
Platform::Register("linux", platformBE64cn);
566583
Platform::Register("linux", platformLE64cn);

0 commit comments

Comments
 (0)