1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
// 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 <cinttypes>
#include <cstdio>
#include <cstring>
#include <map>
#include <functional>
#include <vector>
#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;
}
}
|