-
Notifications
You must be signed in to change notification settings - Fork 29
/
sleighinterface.h
393 lines (355 loc) · 13.9 KB
/
sleighinterface.h
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#pragma once
#include <string>
#include <vector>
#include <map>
typedef unsigned char uchar; ///< unsigned 8 bit value
struct DecompError {
std::string explain; ///< Explanatory string
/// Initialize the error with an explanatory string
DecompError(const std::string& s) { explain = s; }
};
struct LangInfo
{
std::string basePath;
std::string processor;
bool bigEndian;
int size;
std::string slafile;
std::string processorspec;
std::map<std::string, std::string> compilers;
};
//Ghidra/Features/Decompiler/src/decompile/cpp/options.hh
//top level: "extrapop", "defaultprototype", "inline", "noreturn", "structalign"
//"warning", "hideextensions", "allowcontextset", "errorunimplemented"
//"errorreinterpreted", "errortoomanyinstructions", "jumprule", "togglerule"
//Ghidra/Features/Decompiler/src/decompile/cpp/options.cc
//decompile currentaction options: "base", "protorecovery", "protorecovery_a", "deindirect", "localrecovery",
//"deadcode", "typerecovery", "stackptrflow",
//"blockrecovery", "stackvars", "deadcontrolflow", "switchnorm",
//"cleanup", "merge", "dynamic", "casts", "analysis",
//"fixateglobals", "fixateproto",
//"segment", "returnsplit", "nodejoin", "doubleload", "doubleprecis",
//"unreachable", "subvar", "floatprecision",
//"conditionalexe"
//jumptable currentaction options: "base", "noproto", "localrecovery", "deadcode", "stackptrflow",
//"stackvars", "analysis", "segment", "subvar", "conditionalexe"
//normalize currentaction options: "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery",
//"deadcode", "stackptrflow", "normalanalysis",
//"stackvars", "deadcontrolflow", "analysis", "fixateproto", "nodejoin",
//"unreachable", "subvar", "floatprecision", "normalizebranches",
//"conditionalexe"
//paramid currentaction options: "base", "protorecovery", "protorecovery_b", "deindirect", "localrecovery",
//"deadcode", "typerecovery", "stackptrflow", "siganalysis",
//"stackvars", "deadcontrolflow", "analysis", "fixateproto",
//"unreachable", "subvar", "floatprecision",
//"conditionalexe"
//register currentaction options: "base", "analysis", "subvar"
//firstpass currentaction options: "base"
struct Options
{
bool conditionalexe;
bool readonly;
bool decompileUnreachable;
bool decompileDoublePrecis;
bool ignoreUnimplemented;
bool inferConstPtr;
bool nullPrinting;
bool inPlaceOps;
bool conventionPrinting;
bool noCastPrinting;
int maxLineWidth;
int indentIncrement;
int commentIndent;
std::string commentStyle; //"c"
bool commentInstructionHeader;
bool commentUser2; //PRE
bool commentUser1; //EOL
bool commentUser3; //POST
bool commentWarning;
bool commentHeader;
bool commentWarningHeader;
std::string integerFormat; //"best"
std::string setLanguage; //"c-language" - also has "java-language"
std::string protoEval; //calling convention
};
struct SizedAddrInfo;
struct AddrInfo
{
std::string space;
unsigned long long offset;
std::vector<SizedAddrInfo> joins; //for join space only
};
struct SizedAddrInfo
{
AddrInfo addr;
unsigned long long size;
//std::string regName;
};
struct InitStateItem
{
AddrInfo addr1;
AddrInfo addr2;
SizedAddrInfo addr;
unsigned long long val;
};
struct DecMode
{
std::string actionname; // Name of simplification action - "decompile"
bool printSyntaxTree; // Whether syntax tree is returned
bool printCCode; // Whether C code is returned
bool sendParamMeasures; // Whether Parameter Measures are returned
bool jumpLoad; // Whether jumptable load information is returned
};
struct CoreType
{
std::string name;
int size;
std::string metaType;
bool isChar;
bool isUtf;
unsigned long long id; //Datatype::hashName
};
extern const Options defaultOptions;
extern const DecMode defaultDecMode;
extern CoreType defaultCoreTypes[];
extern const int numDefCoreTypes;
extern const char* szCoreTypeDefs[];
struct RangeInfo
{
std::string space;
unsigned long long beginoffset;
unsigned long long endoffset;
};
struct TypeInfo;
//name and argIndex not used for function return values
struct ParamInfo
{
std::string name;
std::vector<TypeInfo> ti;
};
struct SymInfo
{
ParamInfo pi;
SizedAddrInfo addr; //"ram", "stack", "join" but then need offsets for something like piece1="register:0x8:4" piece2="register:0x0:4"
int argIndex; //-1 if local variable
RangeInfo range; //for register space only with locals (for arguments, will automatically specify one less than the start address of the function)
};
struct FuncProtoInfo
{
bool isInline;
bool isNoReturn;
unsigned long long extraPop; //-1 for unknown
std::string model; //unknown, default, __fastcall, __stdcall, __cdecl, __thiscall, __vectorcall, __pascal
bool dotdotdot;
bool customStorage;
bool hasThis;
bool isConstruct;
bool isDestruct;
SymInfo retType;
std::vector<SymInfo> syminfo;
std::vector<SizedAddrInfo> killedByCall;
};
struct StructMemberInfo;
struct ParamInfo;
//either only a typeName is present for reference or if size != -1 then all fields are present
struct TypeInfo
{
std::string typeName;
unsigned long long size = 0;
std::string metaType;
//following are mutually exclusive fields - union?
bool isEnum = false; //uint
bool isUtf = false; //wchar*
bool isChar = false; //char
unsigned long long arraySize = 0; //array
std::vector<StructMemberInfo> structMembers; //struct
std::vector<std::pair<std::string, unsigned long long>> enumMembers; //enum
FuncProtoInfo funcInfo; //code
bool isReadOnly; //external use only for all except functions, structures, array - decompiler does not need - it tracks symbols not types better to create derived struct
};
struct StructMemberInfo
{
std::string name;
unsigned long long offset;
std::vector<TypeInfo> ti;
};
struct CommentInfo
{
AddrInfo addr;
std::string type;
std::string text;
};
enum MappedSymbolKinds
{
KIND_HOLE = -1,
KIND_FUNCTION = 0,
KIND_DATA = 1,
KIND_EXTERNALREFERENCE = 2,
KIND_LABEL = 3
};
struct MappedSymbolInfo
{
MappedSymbolKinds kind;
bool readonly; //data, label, hole
bool volatil; //data, label, hole
std::string name; //function, data, extref, symbol
std::vector<TypeInfo> typeChain; //data
unsigned long long entryPoint; //function
std::vector<RangeInfo> ranges; //function not at entry point
//function at entry point:
unsigned long long size; //minimally 1 or maximally must be contiguous block from entry point
FuncProtoInfo func;
};
enum CPoolTag
{
PRIMITIVE = 0, // Constant -value- of datatype -type-
STRING_LITERAL = 1, // Constant reference to string in -token-
CLASS_REFERENCE = 2, // Reference to (system level) class object
POINTER_METHOD = 3, // Pointer to a method, name in -token-, signature in -type-
POINTER_FIELD = 4, // Pointer to a field, name in -token-, datatype in -type-
ARRAY_LENGTH = 5, // Integer length, -token- is language specific indicator, -type- is integral type
INSTANCE_OF = 6, // boolean value, -token- is language specific indicator, -type- is boolean type
CHECK_CAST = 7 // Pointer to object, new name in -token-, new datatype in -type-
};
struct CPoolRecord
{
CPoolTag tag;
bool hasThis;
bool constructor;
unsigned long long value; //for PRIMITIVE
std::vector<uchar> data;
std::string token; //if and only if data empty
};
class DecompileCallback
{
public:
virtual int getBytes(unsigned char* ptr, int size, AddrInfo addr) = 0;
virtual void getMappedSymbol(AddrInfo addr, MappedSymbolInfo& msi) = 0;
virtual void getExternInfo(AddrInfo addr, std::string& callName, std::string& modName, FuncProtoInfo& func) = 0;
//type functions only needed if returned from the symbol queries
//metatypes are ptr, array and struct beyond the core ones: void, int, uint, bool, code, float, unknown
virtual void getMetaType(std::string typeName, std::vector<TypeInfo>& typeChain) = 0;
//4 P-code injection callbacks, along with C Pool Ref callbacks are not yet implemented
//valid types are "user1", "user2", "user3", "header", "warning", "warningheader"
virtual void getComments(AddrInfo addr, std::vector<CommentInfo> & comments) = 0;
virtual std::string getSymbol(AddrInfo addr) = 0;
virtual std::vector<uchar> getStringData(AddrInfo addr) = 0;
virtual std::string getPcodeInject(int type, std::string name, AddrInfo addr, std::string fixupbase, unsigned long long fixupoffset) = 0;
virtual void getCPoolRef(const std::vector<unsigned long long>& refs, CPoolRecord& rec) = 0;
//colors are Clang-based: "keyword", "comment", "type", "funcname", "var", "const", "param" and "global"
virtual std::string emit(std::string type, std::string color, std::string str) = 0;
virtual void getInits(std::vector<InitStateItem>& inits) = 0;
virtual void launchDecompiler() = 0;
virtual void protocolRecorder(std::string data, bool bWrite) {} //command, queryresponse, exception, buffereddata, packed bytes and packed pcode use packedBytes({}) and packedPcode("XmlEncodedPcode")
virtual size_t readDec(void* Buf, size_t MaxCharCount) = 0;
virtual size_t writeDec(void const* Buf, size_t MaxCharCount) = 0;
virtual void terminate() = 0;
};
class Sleigh;
class ContextInternal;
class Element;
class VarnodeTpl;
class XmlPcodeEmit;
class CallbackLoadImage;
class DecompInterface
{
DecompileCallback* callback;
bool statusGood; // true if decompiler process is running
int archId = -1; // architecture id for decomp process
int maxResultSizeMBYtes = 50; // maximum result size in MBytes to allow from decompiler
bool showNamespace; // whether to show namespaces for functions
// Initialization state
DecMode lastdm = { "decompile", true, true, false, false };
std::string xmlOptions; // Current decompiler options
std::string callStyle;
std::map<std::string, unsigned long long> callStyles;
std::map<std::string, unsigned long long> symbolIds;
std::string stackPointerReg;
//std::string stackPointerSpace;
//std::map<std::string, std::string> registers;
//std::map<int, std::string> userOpNames;
//std::string procSpaces;
//uint8 uniqBase;
//bool bigEndian;
AddrInfo startOffs;
CallbackLoadImage* loader = nullptr;
ContextInternal* context = nullptr;
Sleigh* trans = nullptr;
std::string lastsleighfile;
std::string pspecxml;
std::string tspecxml;
std::string cspecxml;
std::string coretypesxml;
int toutSecs;
unsigned long long uniqueBase;
std::map<std::string, XmlPcodeEmit*> callFixupMap;
std::map<std::string, XmlPcodeEmit*> callFixupOtherMap;
std::map<std::string, XmlPcodeEmit*> callMechMap;
std::map<std::string, XmlPcodeEmit*> callExecPcodeMap;
std::map<std::string, std::string> fixupTargetMap;
void processPcodeInject(int type, std::map<std::string, XmlPcodeEmit*>& map);
uchar read();
void write(void const* Buf, size_t MaxCharCount);
uchar readToBurst();
uchar readToBuffer(std::vector<uchar>& buf);
std::string readQueryString();
void generateException();
void readToResponse();
void writeString(std::string msg);
void writeBytes(const uchar out[], int outlen);
std::vector<uchar> readResponse();
std::vector<uchar> sendCommand(std::string command);
std::vector<uchar> sendCommand1ParamTimeout(std::string command, std::string param,
int timeoutSecs);
std::vector<uchar> sendCommand2Params(std::string command, std::string param1, std::string param2);
std::vector<uchar> sendCommand1Param(std::string command, std::string param1);
std::string convertSourceDoc(Element* el, std::string& displayXml,
std::string& funcProto, std::string& funcColorProto,
std::vector<std::tuple<std::vector<unsigned int>, std::string, unsigned int>>& blockGraph);
std::string getOptions(Options opt);
void adjustUniqueBase(VarnodeTpl* v);
std::string buildTypeXml(std::vector<TypeInfo>& typeInfo, size_t indnt);
std::string writeFuncProto(FuncProtoInfo func, std::string injectstr, bool bUseInternalList, size_t indnt);
std::string writeFunc(SizedAddrInfo addr, std::string funcname, std::string parentname, FuncProtoInfo func);
protected:
void setupTranslator(DecompileCallback* cb, std::string sleighfilename);
XmlPcodeEmit* getPcodeSnippet(std::string parsestring,
const std::vector<std::pair<std::string, int>>& inputs,
const std::vector<std::pair<std::string, int>>& outputs);
public:
enum {
CALLFIXUP_TYPE = 1, ///< Injection that replaces a CALL
CALLOTHERFIXUP_TYPE = 2, ///< Injection that replaces a user-defined p-code op, CALLOTHER
CALLMECHANISM_TYPE = 3, ///< Injection to patch up data-flow around the caller/callee boundary
EXECUTABLEPCODE_TYPE = 4 ///< Injection running as a stand-alone p-code script
};
~DecompInterface();
static int coreTypeLookup(size_t size, std::string metatype);
static void getLangFiles(std::string processorpath, std::string externaltool,
std::map<std::string, std::vector<int>> & toolMap, std::vector<LangInfo>& li);
static void getProtoEvals(std::string cspec, std::vector<std::string>& vec, int* defaultIdx);
static std::string compilePcodeSnippet(std::string sleighfilename, std::string parsestring,
const std::vector<std::pair<std::string, int>>& inputs,
const std::vector<std::pair<std::string, int>>& outputs);
void setup(DecompileCallback* cb, std::string sleighfilename, std::string pspecfilename,
std::string cspecfilename, std::vector<CoreType>& coreTypes, Options opt, int timeout, int maxpload);
//coreTypes IDs will be automatically properly generated upon return
void setMaxResultSize(int maxResultSizeMBytes);
void setShowNamespace(bool showNamespace);
bool setSimplificationStyle(std::string actionstring);
bool toggleSyntaxTree(bool val);
bool toggleCCode(bool val);
bool toggleParamMeasures(bool val);
bool toggleJumpLoads(bool val);
bool setOptions(Options opt);
//only after setup, and if decompilation process running and registered
std::string doDecompile(DecMode dm, AddrInfo addr, std::string& displayXml,
std::string& funcProto, std::string& funcColorProto, FuncProtoInfo& symInf,
std::vector<std::tuple<std::vector<unsigned int>, std::string, unsigned int>>& blockGraph);
void registerProgram();
int deregisterProgram();
std::string regToSpacebase(int regidx);
int spacebaseToReg(std::string name);
int regNameToIndex(std::string regName);
std::string getRegisterFromIndex(unsigned long long offs, int size);
};