// This plugin renders 64-bit binary integer decimal floating point constants directly in the // decompilation. See the sample binary at `examples/bid64_constant/sample_binary` for an // example of a binary that uses this unusual format. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include "binaryninjaapi.h" using namespace BinaryNinja; using namespace std; static string Bid64ToString(bool sign, uint64_t magnitude, int exponent) { if (magnitude == 0) exponent = 0; string digits = to_string(magnitude); int intPartDigits = digits.length() + exponent; int displayedExponent = 0; if (intPartDigits > 10 || intPartDigits < -4) { int newExponent = 1 - (int)digits.length(); displayedExponent = exponent - newExponent; intPartDigits = digits.length() + newExponent; } string fracDigits; if (intPartDigits < 0) fracDigits = digits; else if (intPartDigits <= (int)digits.length()) fracDigits = digits.substr(intPartDigits); int trailingZeros = 0; for (size_t i = 0; i < fracDigits.length(); i++) { if (fracDigits[(fracDigits.length() - 1) - i] != '0') break; trailingZeros++; } int nonzeroFracDigits = (int)fracDigits.length() - trailingZeros; fracDigits = fracDigits.substr(0, nonzeroFracDigits); string result; if (sign) result = "-"; if (intPartDigits > 0) { for (size_t i = 0; i < intPartDigits; i++) { if (i >= digits.length()) result += "0"; else result += string(1, digits[i]); } } else { result += "0"; } if (intPartDigits < 0 && fracDigits.length() > 0) { result += "."; for (size_t i = 0; i < -intPartDigits; i++) result += "0"; result += fracDigits; } else if (fracDigits.length() > 0) { result += "."; result += fracDigits; } if (displayedExponent > 0) result += "E+" + to_string(displayedExponent); else if (displayedExponent < 0) result += "E" + to_string(displayedExponent); return result; } class Bid64ConstantRenderer : public ConstantRenderer { public: Bid64ConstantRenderer() : ConstantRenderer("bid64_constant") { } bool RenderConstant(const HighLevelILInstruction&, Type* type, int64_t val, HighLevelILTokenEmitter& tokens, DisassemblySettings* settings, BNOperatorPrecedence) override { // Typedefs have the final type, so make sure it is a 64 bit integer. The registered name // should be the typedef "BID_UINT64". if (!type || type->GetClass() != IntegerTypeClass) return false; if (type->GetWidth() != 8) return false; auto name = type->GetRegisteredName(); if (!name || name->GetName().GetString() != "BID_UINT64") return false; // Get sign bit and raw exponent bool sign = (val & (1LL << 63)) != 0; int rawExponent = (int)((val >> 53) & 0x3ff); if (rawExponent >= 0x300) { // Don't try and render NaN or infinity return false; } // Get magnitude and actual exponent constexpr uint64_t BIAS = 398; int exponent = rawExponent - BIAS; uint64_t magnitude = val & ((1LL << 53) - 1); tokens.Append(FloatingPointToken, Bid64ToString(sign, magnitude, exponent) + "_bid"); return true; } }; extern "C" { BN_DECLARE_CORE_ABI_VERSION BINARYNINJAPLUGIN void CorePluginDependencies() { } BINARYNINJAPLUGIN bool CorePluginInit() { ConstantRenderer::Register(new Bid64ConstantRenderer()); return true; } }