From 6e4c00a80fa86bcfefba9630a1ea8e2a47bef2de Mon Sep 17 00:00:00 2001 From: Brandon Miller Date: Wed, 28 May 2025 08:33:30 -0400 Subject: Support for Linux x86-64 x32 ABI --- platform/linux/platform_linux.cpp | 63 +++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) (limited to 'platform/linux/platform_linux.cpp') diff --git a/platform/linux/platform_linux.cpp b/platform/linux/platform_linux.cpp index 0102fa42..20a258d6 100644 --- a/platform/linux/platform_linux.cpp +++ b/platform/linux/platform_linux.cpp @@ -3,6 +3,8 @@ using namespace BinaryNinja; using namespace std; +Ref g_linuxX32; +#define EM_X86_64 62 // AMD x86-64 architecture class LinuxX86Platform: public Platform { @@ -103,6 +105,50 @@ public: }; +class LinuxX32Platform: public Platform +{ + public: + LinuxX32Platform(Architecture* arch): Platform(arch, "linux-x32") + { + Ref cc; + cc = arch->GetCallingConventionByName("sysv"); + if (cc) + { + RegisterDefaultCallingConvention(cc); + RegisterCdeclCallingConvention(cc); + RegisterFastcallCallingConvention(cc); + RegisterStdcallCallingConvention(cc); + } + + cc = arch->GetCallingConventionByName("linux-syscall"); + if (cc) + SetSystemCallConvention(cc); + } + + virtual size_t GetAddressSize() const override + { + return 4; + } + + static Ref Recognize(BinaryView* view, Metadata* metadata) + { + Ref fileClass = metadata->Get("EI_CLASS"); + + if (!fileClass || !fileClass->IsUnsignedInteger()) + return nullptr; + + Ref machine = metadata->Get("e_machine"); + if (!machine || !machine->IsUnsignedInteger()) + return nullptr; + + if (fileClass->GetUnsignedInteger() == 1 && machine->GetUnsignedInteger() == EM_X86_64) + return g_linuxX32; + + return nullptr; + } +}; + + class LinuxArmv7Platform: public Platform { public: @@ -314,13 +360,20 @@ extern "C" Ref x64 = Architecture::GetByName("x86_64"); if (x64) { - Ref platform; + Ref x64Platform = new LinuxX64Platform(x64); + g_linuxX32 = new LinuxX32Platform(x64); + + Platform::Register("linux", x64Platform); + Platform::Register("linux", g_linuxX32); - platform = new LinuxX64Platform(x64); - Platform::Register("linux", platform); // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one - BinaryViewType::RegisterPlatform("ELF", 0, platform); - BinaryViewType::RegisterPlatform("ELF", 3, platform); + BinaryViewType::RegisterPlatform("ELF", 0, x64, x64Platform); + BinaryViewType::RegisterPlatform("ELF", 3, x64, x64Platform); + + + Ref elf = BinaryViewType::GetByName("ELF"); + if (elf) + elf->RegisterPlatformRecognizer(EM_X86_64, LittleEndian, LinuxX32Platform::Recognize); } Ref armv7 = Architecture::GetByName("armv7"); -- cgit v1.3.1