summaryrefslogtreecommitdiff
path: root/platform/linux/platform_linux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linux/platform_linux.cpp')
-rw-r--r--platform/linux/platform_linux.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/platform/linux/platform_linux.cpp b/platform/linux/platform_linux.cpp
new file mode 100644
index 00000000..1a4c9d93
--- /dev/null
+++ b/platform/linux/platform_linux.cpp
@@ -0,0 +1,305 @@
+#include "binaryninjaapi.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+class LinuxX86Platform: public Platform
+{
+public:
+ LinuxX86Platform(Architecture* arch): Platform(arch, "linux-x86")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("regparm");
+ if (cc)
+ RegisterCallingConvention(cc);
+
+ cc = arch->GetCallingConventionByName("stdcall");
+ if (cc)
+ RegisterStdcallCallingConvention(cc);
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+class LinuxPpc32Platform: public Platform
+{
+public:
+ LinuxPpc32Platform(Architecture* arch, const std::string& name): Platform(arch, name)
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("svr4");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+class LinuxPpc64Platform: public Platform
+{
+public:
+ LinuxPpc64Platform(Architecture* arch, const std::string& name): Platform(arch, name)
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("svr4");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+class LinuxX64Platform: public Platform
+{
+public:
+ LinuxX64Platform(Architecture* arch): Platform(arch, "linux-x86_64")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("sysv");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+
+class LinuxArmv7Platform: public Platform
+{
+public:
+ LinuxArmv7Platform(Architecture* arch, const std::string& name): Platform(arch, name)
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+
+class LinuxArm64Platform: public Platform
+{
+public:
+ LinuxArm64Platform(Architecture* arch): Platform(arch, "linux-aarch64")
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("cdecl");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+
+class LinuxMipsPlatform: public Platform
+{
+public:
+ LinuxMipsPlatform(Architecture* arch, const std::string& name): Platform(arch, name)
+ {
+ Ref<CallingConvention> cc;
+
+ cc = arch->GetCallingConventionByName("o32");
+ if (cc)
+ {
+ RegisterDefaultCallingConvention(cc);
+ RegisterCdeclCallingConvention(cc);
+ RegisterFastcallCallingConvention(cc);
+ RegisterStdcallCallingConvention(cc);
+ }
+
+ cc = arch->GetCallingConventionByName("linux-syscall");
+ if (cc)
+ SetSystemCallConvention(cc);
+ }
+};
+
+
+extern "C"
+{
+ BN_DECLARE_CORE_ABI_VERSION
+
+#ifndef DEMO_VERSION
+ BINARYNINJAPLUGIN void CorePluginDependencies()
+ {
+ AddOptionalPluginDependency("arch_x86");
+ AddOptionalPluginDependency("arch_armv7");
+ AddOptionalPluginDependency("arch_arm64");
+ AddOptionalPluginDependency("arch_mips");
+ AddOptionalPluginDependency("arch_ppc");
+ AddOptionalPluginDependency("view_elf");
+ }
+#endif
+
+#ifdef DEMO_VERSION
+ bool LinuxPluginInit()
+#else
+ BINARYNINJAPLUGIN bool CorePluginInit()
+#endif
+ {
+ Ref<Architecture> x86 = Architecture::GetByName("x86");
+ if (x86)
+ {
+ Ref<Platform> platform;
+
+ platform = new LinuxX86Platform(x86);
+ Platform::Register("linux", platform);
+ // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one
+ BinaryViewType::RegisterPlatform("ELF", 0, x86, platform);
+ BinaryViewType::RegisterPlatform("ELF", 3, x86, platform);
+ }
+
+ Ref<Architecture> x64 = Architecture::GetByName("x86_64");
+ if (x64)
+ {
+ Ref<Platform> platform;
+
+ 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, x64, platform);
+ BinaryViewType::RegisterPlatform("ELF", 3, x64, platform);
+ }
+
+ Ref<Architecture> armv7 = Architecture::GetByName("armv7");
+ Ref<Architecture> armv7eb = Architecture::GetByName("armv7eb");
+ Ref<Architecture> thumb2 = Architecture::GetByName("thumb2");
+ Ref<Architecture> thumb2eb = Architecture::GetByName("thumb2eb");
+ if (armv7 && armv7eb && thumb2 && thumb2eb)
+ {
+ Ref<Platform> armPlatform, armebPlatform, thumbPlatform, thumbebPlatform;
+
+ armPlatform = new LinuxArmv7Platform(armv7, "linux-armv7");
+ armebPlatform = new LinuxArmv7Platform(armv7eb, "linux-armv7eb");
+ thumbPlatform = new LinuxArmv7Platform(thumb2, "linux-thumb2");
+ thumbebPlatform = new LinuxArmv7Platform(thumb2eb, "linux-thumb2eb");
+ armPlatform->AddRelatedPlatform(thumb2, thumbPlatform);
+ armebPlatform->AddRelatedPlatform(thumb2eb, thumbebPlatform);
+ thumbPlatform->AddRelatedPlatform(armv7, armPlatform);
+ thumbebPlatform->AddRelatedPlatform(armv7eb, armebPlatform);
+ Platform::Register("linux", armPlatform);
+ Platform::Register("linux", thumbPlatform);
+ Platform::Register("linux", armebPlatform);
+ Platform::Register("linux", thumbebPlatform);
+ // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one
+ BinaryViewType::RegisterPlatform("ELF", 0, armv7, armPlatform);
+ BinaryViewType::RegisterPlatform("ELF", 3, armv7, armPlatform);
+ BinaryViewType::RegisterPlatform("ELF", 0, armv7eb, armebPlatform);
+ BinaryViewType::RegisterPlatform("ELF", 3, armv7eb, armebPlatform);
+ }
+
+ Ref<Architecture> arm64 = Architecture::GetByName("aarch64");
+ if (arm64)
+ {
+ Ref<Platform> platform;
+
+ platform = new LinuxArm64Platform(arm64);
+ Platform::Register("linux", platform);
+ // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one
+ BinaryViewType::RegisterPlatform("ELF", 0, arm64, platform);
+ BinaryViewType::RegisterPlatform("ELF", 3, arm64, platform);
+ }
+
+ Ref<Architecture> ppc = Architecture::GetByName("ppc");
+ Ref<Architecture> ppcle = Architecture::GetByName("ppc_le");
+ if (ppc && ppcle)
+ {
+ Ref<Platform> platform;
+ Ref<Platform> platformle;
+
+ platform = new LinuxPpc32Platform(ppc, "linux-ppc32");
+ platformle = new LinuxPpc32Platform(ppcle, "linux-ppc32_le");
+ Platform::Register("linux", platform);
+ Platform::Register("linux", platformle);
+ // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one
+ BinaryViewType::RegisterPlatform("ELF", 0, ppc, platform);
+ BinaryViewType::RegisterPlatform("ELF", 3, ppc, platform);
+ BinaryViewType::RegisterPlatform("ELF", 0, ppcle, platformle);
+ BinaryViewType::RegisterPlatform("ELF", 3, ppcle, platformle);
+ }
+
+ Ref<Architecture> ppc64 = Architecture::GetByName("ppc64");
+ Ref<Architecture> ppc64le = Architecture::GetByName("ppc64_le");
+ if (ppc64 && ppc64le)
+ {
+ Ref<Platform> platform;
+ Ref<Platform> platformle;
+
+ platform = new LinuxPpc64Platform(ppc64, "linux-ppc64");
+ platformle = new LinuxPpc64Platform(ppc64le, "linux-ppc64_le");
+ Platform::Register("linux", platform);
+ Platform::Register("linux", platformle);
+ // Linux binaries sometimes have an OS identifier of zero, even though 3 is the correct one
+ BinaryViewType::RegisterPlatform("ELF", 0, ppc64, platform);
+ BinaryViewType::RegisterPlatform("ELF", 3, ppc64, platform);
+ BinaryViewType::RegisterPlatform("ELF", 0, ppc64le, platformle);
+ BinaryViewType::RegisterPlatform("ELF", 3, ppc64le, platformle);
+ }
+
+ Ref<Architecture> mipsel = Architecture::GetByName("mipsel32");
+ Ref<Architecture> mipseb = Architecture::GetByName("mips32");
+ if (mipsel && mipseb)
+ {
+ Ref<Platform> platformLE, platformBE;
+
+ platformLE = new LinuxMipsPlatform(mipsel, "linux-mipsel");
+ platformBE = new LinuxMipsPlatform(mipseb, "linux-mips");
+ Platform::Register("linux", platformLE);
+ Platform::Register("linux", platformBE);
+ // 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", 3, mipsel, platformLE);
+ BinaryViewType::RegisterPlatform("ELF", 3, mipseb, platformBE);
+ }
+
+ return true;
+ }
+}