forked from radareorg/radare2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathr_anal.h
1620 lines (1392 loc) · 63 KB
/
r_anal.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
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* radare2 - LGPL - Copyright 2009-2024 - nibble, pancake, xvilka */
#ifndef R2_ANAL_H
#define R2_ANAL_H
/* use old refs and function storage */
// still required by core in lot of places
#define USE_VARSUBS 0
#include <r_cons.h>
#include <r_io.h>
#include <r_esil.h>
#include <r_arch.h>
#include <r_list.h>
#include <r_util/r_print.h>
#include <r_search.h>
#include <r_bind.h>
#include <r_syscall.h>
#include <r_flag.h>
#include <r_bin.h>
#include <r_codemeta.h>
#include <sdb/set.h>
#ifdef __cplusplus
extern "C" {
#endif
R_LIB_VERSION_HEADER(r_anal);
/* dwarf processing context */
typedef struct r_anal_dwarf_context {
const RBinDwarfDebugInfo *info;
HtUP/*<offset, RBinDwarfLocList*>*/ *loc;
// const RBinDwarfCfa *cfa; TODO
} RAnalDwarfContext;
// TODO: save memory2 : fingerprints must be pointers to a buffer
// containing a dupped file in memory
/* save memory:
bb_has_ops=1 -> 600M
bb_has_ops=0 -> 350MB
*/
typedef struct {
struct r_anal_t *anal;
int type;
int rad;
SdbForeachCallback cb;
void *user;
int count;
struct r_anal_function_t *fcn;
PJ *pj;
} RAnalMetaUserItem;
typedef struct r_anal_range_t {
ut64 from;
ut64 to;
int bits;
ut64 rb_max_addr;
RBNode rb;
} RAnalRange;
enum {
R_ANAL_DATA_TYPE_NULL = 0,
R_ANAL_DATA_TYPE_UNKNOWN = 1,
R_ANAL_DATA_TYPE_STRING = 2,
R_ANAL_DATA_TYPE_WIDE_STRING = 3,
R_ANAL_DATA_TYPE_POINTER = 4,
R_ANAL_DATA_TYPE_NUMBER = 5,
R_ANAL_DATA_TYPE_INVALID = 6,
R_ANAL_DATA_TYPE_HEADER = 7,
R_ANAL_DATA_TYPE_SEQUENCE = 8,
R_ANAL_DATA_TYPE_PATTERN = 9,
R_ANAL_DATA_TYPE_ZERO = 10,
};
// used from core/anal.c
#define R_ANAL_ADDR_TYPE_EXEC 1
#define R_ANAL_ADDR_TYPE_READ 1 << 1
#define R_ANAL_ADDR_TYPE_WRITE 1 << 2
#define R_ANAL_ADDR_TYPE_FLAG 1 << 3
#define R_ANAL_ADDR_TYPE_FUNC 1 << 4
#define R_ANAL_ADDR_TYPE_HEAP 1 << 5
#define R_ANAL_ADDR_TYPE_STACK 1 << 6
#define R_ANAL_ADDR_TYPE_REG 1 << 7
#define R_ANAL_ADDR_TYPE_PROGRAM 1 << 8
#define R_ANAL_ADDR_TYPE_LIBRARY 1 << 9
#define R_ANAL_ADDR_TYPE_ASCII 1 << 10
#define R_ANAL_ADDR_TYPE_SEQUENCE 1 << 11
/* type = (R_ANAL_VAR_TYPE_BYTE & R_ANAL_VAR_TYPE_SIZE_MASK) |
* ( RANAL_VAR_TYPE_SIGNED & RANAL_VAR_TYPE_SIGN_MASK) |
* ( RANAL_VAR_TYPE_CONST & RANAL_VAR_TYPE_MODIFIER_MASK)
*/
typedef struct r_anal_type_var_t {
char *name;
int index;
int scope;
ut16 type; // contain (type || signedness || modifier)
ut8 size;
union {
ut8 v8;
ut16 v16;
ut32 v32;
ut64 v64;
} value;
} RAnalTypeVar;
typedef struct r_anal_type_ptr_t {
char *name;
ut16 type; // contain (type || signedness || modifier)
ut8 size;
union {
ut8 v8;
ut16 v16;
ut32 v32;
ut64 v64;
} value;
} RAnalTypePtr;
typedef struct r_anal_type_array_t {
char *name;
ut16 type; // contain (type || signedness || modifier)
ut8 size;
ut64 count;
union {
ut8 *v8;
ut16 *v16;
ut32 *v32;
ut64 *v64;
} value;
} RAnalTypeArray;
typedef struct r_anal_type_struct_t RAnalTypeStruct;
typedef struct r_anal_type_t RAnalType;
struct r_anal_type_struct_t {
char *name;
ut8 type;
ut32 size;
void *parent;
RAnalType *items;
};
typedef struct r_anal_type_union_t {
char *name;
ut8 type;
ut32 size;
void *parent;
RAnalType *items;
} RAnalTypeUnion;
typedef struct r_anal_type_alloca_t {
long address;
long size;
void *parent;
RAnalType *items;
} RAnalTypeAlloca;
enum {
R_ANAL_FQUALIFIER_NONE = 0,
R_ANAL_FQUALIFIER_STATIC = 1,
R_ANAL_FQUALIFIER_VOLATILE = 2,
R_ANAL_FQUALIFIER_INLINE = 3,
R_ANAL_FQUALIFIER_NAKED = 4,
R_ANAL_FQUALIFIER_VIRTUAL = 5,
};
#define R_ANAL_CC_MAXARG 16
enum {
R_ANAL_FCN_TYPE_NULL = 0,
R_ANAL_FCN_TYPE_FCN = 1 << 0,
R_ANAL_FCN_TYPE_LOC = 1 << 1,
R_ANAL_FCN_TYPE_SYM = 1 << 2,
R_ANAL_FCN_TYPE_IMP = 1 << 3,
R_ANAL_FCN_TYPE_INT = 1 << 4, /* privileged function - ends with iret/reti/.. */
R_ANAL_FCN_TYPE_ROOT = 1 << 5, /* matching flag */
R_ANAL_FCN_TYPE_ANY = -1 /* all the bits set */
};
#define RAnalBlock struct r_anal_bb_t
enum {
R_ANAL_DIFF_TYPE_NULL = 0,
R_ANAL_DIFF_TYPE_MATCH = 'm',
R_ANAL_DIFF_TYPE_UNMATCH = 'u'
};
typedef struct r_anal_enum_case_t {
char *name;
int val;
} RAnalEnumCase;
typedef struct r_anal_struct_member_t {
char *name;
char *type;
size_t offset; // in bytes
size_t size; // in bits? rename to 'bitsize'
} RAnalStructMember;
typedef struct r_anal_union_member_t {
char *name;
char *type;
size_t offset; // in bytes
size_t size; // in bits? TODO rename to 'bitsize'
} RAnalUnionMember;
typedef enum {
R_ANAL_BASE_TYPE_KIND_STRUCT,
R_ANAL_BASE_TYPE_KIND_UNION,
R_ANAL_BASE_TYPE_KIND_ENUM,
R_ANAL_BASE_TYPE_KIND_TYPEDEF, // probably temporary addition, dev purposes
R_ANAL_BASE_TYPE_KIND_ATOMIC, // For real atomic base types
} RAnalBaseTypeKind;
typedef struct r_anal_base_type_struct_t {
RVector/*<RAnalStructMember>*/ members;
} RAnalBaseTypeStruct;
typedef struct r_anal_base_type_union_t {
RVector/*<RAnalUnionMember>*/ members;
} RAnalBaseTypeUnion;
typedef struct r_anal_base_type_enum_t {
RVector/*<RAnalEnumCase*/ cases; // list of all the enum casessssss
} RAnalBaseTypeEnum;
typedef struct r_anal_base_type_t {
char *name;
char *type; // Used by typedef, atomic type, enum
ut64 size; // size of the whole type in bits
RAnalBaseTypeKind kind;
union {
RAnalBaseTypeStruct struct_data;
RAnalBaseTypeEnum enum_data;
RAnalBaseTypeUnion union_data;
};
} RAnalBaseType;
typedef struct r_anal_diff_t {
int type;
ut64 addr;
double dist;
char *name;
ut32 size;
} RAnalDiff;
typedef struct r_anal_attr_t RAnalAttr;
struct r_anal_attr_t {
char *key;
long value;
RAnalAttr *next;
};
/* Stores useful function metadata */
typedef struct r_anal_function_meta_t {
// _min and _max are calculated lazily when queried.
// On changes, they will either be updated (if this can be done trivially) or invalidated.
// They are invalid iff _min == UT64_MAX.
ut64 _min; // PRIVATE, min address, use r_anal_function_min_addr() to access
ut64 _max; // PRIVATE, max address, use r_anal_function_max_addr() to access
int numrefs; // number of cross references
int numcallrefs; // number of calls
} RAnalFcnMeta;
typedef struct r_anal_function_t {
// TODO R2_600 Use RBinName here
char *name;
char *realname; // R2_590: add realname for the mangled one
int bits; // ((> bits 0) (set-bits bits))
int type;
const char *cc; // calling convention, should come from RAnal.constpool
ut64 addr;
HtUP/*<ut64, char *>*/ *labels;
HtPP/*<char *, ut64 *>*/ *label_addrs;
RPVector vars;
HtUP/*<st64, RPVector<RAnalVar *>>*/ *inst_vars; // offset of instructions => the variables they access
ut64 reg_save_area; // size of stack area pre-reserved for saving registers
st64 bp_off; // offset of bp inside owned stack frame
st64 stack; // stack frame size
int maxstack;
int ninstr;
bool folded;
bool is_pure;
bool is_variadic;
bool has_changed; // true if function may have changed since last anaysis TODO: set this attribute where necessary
bool bp_frame;
bool is_noreturn; // true if function does not return
ut8 *fingerprint; // TODO: make is fuzzy and smarter
size_t fingerprint_size;
RAnalDiff *diff;
RList *bbs; // TODO: should be RPVector
RAnalFcnMeta meta;
RList *imports; // maybe bound to class?
struct r_anal_t *anal; // this function is associated with this instance
#if R2_600
ut64 ts; // timestamp when the function was registered. useful to sort them by order or "incremental projects"). afla
#endif
} RAnalFunction;
typedef struct r_anal_func_arg_t {
const char *name;
const char *fmt;
const char *cc_source;
char *orig_c_type;
char *c_type;
ut64 size;
ut64 src; //Function-call argument value or pointer to it
} RAnalFuncArg;
struct r_anal_type_t {
char *name;
ut32 type;
ut32 size;
RList *content;
};
typedef enum {
R_META_TYPE_ANY = -1,
R_META_TYPE_BIND = 'b',
R_META_TYPE_CODE = 'c',
R_META_TYPE_DATA = 'd',
R_META_TYPE_STRING = 's',
R_META_TYPE_FORMAT = 'f',
R_META_TYPE_MAGIC = 'm',
R_META_TYPE_HIDE = 'h',
R_META_TYPE_COMMENT = 'C',
R_META_TYPE_RUN = 'r',
R_META_TYPE_HIGHLIGHT = 'H',
R_META_TYPE_VARTYPE = 't',
} RAnalMetaType;
/* meta */
typedef struct r_anal_meta_item_t {
// XXX missing size
RAnalMetaType type;
int subtype;
char *str;
const RSpace *space;
} RAnalMetaItem;
struct r_anal_t;
struct r_anal_bb_t;
typedef struct r_anal_callbacks_t {
int (*on_fcn_new) (struct r_anal_t *, void *user, RAnalFunction *fcn);
int (*on_fcn_delete) (struct r_anal_t *, void *user, RAnalFunction *fcn);
int (*on_fcn_rename) (struct r_anal_t *, void *user, RAnalFunction *fcn, const char *oldname);
int (*on_fcn_bb_new) (struct r_anal_t *, void *user, RAnalFunction *fcn, struct r_anal_bb_t *bb);
} RAnalCallbacks;
#define R_ESIL_GOTO_LIMIT 4096
typedef struct r_anal_options_t {
int depth;
int graph_depth;
bool vars; //analyze local var and arguments
bool varname_stack; // name vars based on their offset in the stack
bool var_newstack; // new sp-relative variable analysis
int cjmpref;
int jmpref;
int jmpabove;
bool ijmp;
bool jmpmid; // continue analysis after jmp into middle of insn
bool loads;
bool ignbithints;
int followdatarefs;
int searchstringrefs;
int followbrokenfcnsrefs;
int bb_max_size;
bool trycatch;
bool norevisit;
int recont; // continue on recurse analysis mode
int noncode;
bool nopskip; // skip nops at the beginning of functions
int hpskip; // skip `mov reg,reg` and `lea reg,[reg]`
int jmptbl; // analyze jump tables
int nonull;
bool pushret; // analyze push+ret as jmp
bool armthumb; //
bool delay;
bool tailcall;
int tailcall_delta;
bool retpoline;
bool propagate_noreturn;
bool recursive_noreturn; // anal.rnr
bool slow;
bool flagends;
bool zigndups;
bool icods; // R2_600 -- add anal.icods or anal.xrefs.indirect references. needed for stm8 at least
bool newcparser;
// R2_600 - add zign_dups field for "zign.dups" config
} RAnalOptions;
// XXX we have cc / calling conventions / abi settings already no need for a custom enum here
typedef enum {
R_ANAL_CPP_ABI_ITANIUM = 0, // default for GCC
R_ANAL_CPP_ABI_MSVC
} RAnalCPPABI;
typedef struct r_anal_hint_cb_t {
//add more cbs as needed
void (*on_bits) (struct r_anal_t *a, ut64 addr, int bits, bool set);
} RHintCb;
typedef struct r_anal_thread_t {
int id;
int map; // tls map id
ut64 birth;
RReg *reg;
} RAnalThread;
typedef struct {
void *priv;
} RAnalBacktraces;
typedef struct r_ref_manager_t RefManager;
typedef struct r_anal_t {
RArchConfig *config;
int lineswidth; // asm.lines.width
int sleep; // anal.sleep, sleep some usecs before analyzing more (avoid 100% cpu usages)
RAnalCPPABI cxxabi; // anal.cpp.abi
void *user;
ut64 gp; // anal.gp, global pointer. used for mips. but can be used by other arches too in the future
RBTree bb_tree; // all basic blocks by address. They can overlap each other, but must never start at the same address.
RList *fcns;
HtUP *ht_addr_fun; // address => function
HtPP *ht_name_fun; // name => function
RReg *reg;
ut8 *last_disasm_reg;
int last_disasm_reg_size;
RSyscall *syscall;
int diff_ops;
double diff_thbb;
double diff_thfcn;
RIOBind iob;
RFlagBind flb;
RFlagSet flg_class_set;
RFlagGet flg_class_get;
RFlagSet flg_fcn_set;
RBinBind binb; // Set only from core when an analysis plugin is called.
RCoreBind coreb;
int maxreflines; // asm.lines.maxref
int esil_goto_limit; // esil.gotolimit
REsil *esil;
struct r_anal_plugin_t *cur;
RArch *arch;
RAnalRange *limit; // anal.from, anal.to
RList *plugins; // anal plugins
Sdb *sdb_types;
Sdb *sdb_fmts;
Sdb *sdb_zigns;
RefManager *rm;
RSpaces zign_spaces;
char *zign_path; // dir.zigns
PrintfCallback cb_printf;
RPrint *print;
//moved from RAnalFcn
Sdb *sdb; // root
Sdb *sdb_pins;
HtUP/*<RVector<RAnalAddrHintRecord>>*/ *addr_hints; // all hints that correspond to a single address
RBTree/*<RAnalArchHintRecord>*/ arch_hints;
RBTree/*<RAnalArchBitsRecord>*/ bits_hints;
RHintCb hint_cbs;
RIntervalTree meta;
RSpaces meta_spaces;
Sdb *sdb_cc; // calling conventions
Sdb *sdb_classes;
Sdb *sdb_classes_attrs;
RAnalCallbacks cb;
RAnalOptions opt;
RList *reflines;
RListComparator columnSort;
int stackptr;
bool (*log)(struct r_anal_t *anal, const char *msg);
bool (*read_at)(struct r_anal_t *anal, ut64 addr, ut8 *buf, int len);
bool verbose;
RFlagGetAtAddr flag_get;
REvent *ev;
RList/*<char *>*/ *imports; // global imports
SetU *visited;
RStrConstPool constpool;
RList *leaddrs;
char *pincmd;
RAnalBacktraces btstore;
/* private */
RThreadLock *lock;
ut64 cmpval;
ut64 lea_jmptbl_ip;
int cs_obits;
int cs_omode;
size_t cs_handle;
int thread; // see apt command
RList *threads;
RColor tracetagcolors[64]; // each trace color for each bit
/* end private */
R_DIRTY_VAR;
} RAnal;
typedef const char *(*RAnalLabelAt) (RAnalFunction *fcn, ut64);
typedef enum {
R_ANAL_VAR_KIND_REG = 'r',
R_ANAL_VAR_KIND_BPV = 'b',
R_ANAL_VAR_KIND_SPV = 's'
} RAnalVarKind;
#define VARPREFIX "var"
#define ARGPREFIX "arg"
#if 0
typedef enum {
R_ANAL_VAR_ACCESS_TYPE_PTR = 0,
R_ANAL_VAR_ACCESS_TYPE_READ = (1 << 0),
R_ANAL_VAR_ACCESS_TYPE_WRITE = (1 << 1)
} RAnalVarAccessType;
#endif
typedef struct r_anal_var_access_t {
const char *reg; // register used for access
st64 offset; // relative to the function's entrypoint
st64 stackptr; // delta added to register to get the var, e.g. [rbp - 0x10]
ut8 type; // R_PERM_{R/W/NONE} // TODO: R2_600 what about using rwx instead of custom enum?
} RAnalVarAccess;
typedef struct r_anal_var_constraint_t {
RAnalCondType cond;
ut64 val;
} RAnalVarConstraint;
// generic for args and locals
typedef struct r_anal_var_t {
RAnalFunction *fcn;
char *name; // name of the variable
char *type; // cparse type of the variable
RAnalVarKind kind;
bool isarg;
int delta; /* delta offset inside stack frame */
char *regname; // name of the register
RVector/*<RAnalVarAccess>*/ accesses; // ordered by offset, touch this only through API or expect uaf
char *comment;
RVector/*<RAnalVarConstraint>*/ constraints;
// below members are just for caching, TODO: remove them and do it better
int argnum;
} RAnalVar;
// RAnalVar "prototype", RAnalVar w/o function used for serialization
typedef struct r_anal_var_proto_t {
char *name;
char *type;
RAnalVarKind kind;
bool isarg;
int delta;
} RAnalVarProt;
// Refers to a variable or a struct field inside a variable, only for varsub
R_DEPRECATE typedef struct r_anal_var_field_t {
char *name;
st64 delta;
bool field;
} RAnalVarField;
// TO DEPRECATE R2_590
// Use r_anal_get_functions_in¿() instead
R_DEPRECATE R_API RAnalFunction *r_anal_get_fcn_in(RAnal *anal, ut64 addr, int type);
R_DEPRECATE R_API RAnalFunction *r_anal_get_fcn_in_bounds(RAnal *anal, ut64 addr, int type);
R_API R_DEPRECATE RList/*<RAnalVar *>*/ *r_anal_var_all_list(RAnal *anal, RAnalFunction *fcn);
R_API R_DEPRECATE RList/*<RAnalVarField *>*/ *r_anal_function_get_var_fields(RAnalFunction *fcn, int kind);
// There could be multiple vars used in multiple functions. Use r_anal_get_functions_in()+r_anal_function_get_vars_used_at() instead.
R_API R_DEPRECATE RAnalVar *r_anal_get_used_function_var(RAnal *anal, ut64 addr);
typedef RAnalFunction *(* RAnalGetFcnIn)(RAnal *anal, ut64 addr, int type);
typedef RAnalHint *(* RAnalGetHint)(RAnal *anal, ut64 addr);
typedef char *(* RAnalMnemonics)(RAnal *anal, int id, bool json);
typedef int (* RAnalEncode)(RAnal *anal, ut64 addr, const char *s, ut8 *data, int len);
typedef int (* RAnalDecode)(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
typedef void (* RAnalOpInit)(RAnalOp *op);
typedef void (* RAnalOpFini)(RAnalOp *op);
typedef bool (* RAnalUse)(RAnal *op, const char *name); // TODO: add bits and cpu too imho
typedef struct r_anal_bind_t {
RAnal *anal;
RAnalGetFcnIn get_fcn_in;
RAnalGetHint get_hint;
RAnalMnemonics mnemonics;
RAnalEncode encode;
RAnalDecode decode;
RAnalOpInit opinit;
RAnalOpFini opfini;
RAnalUse use;
} RAnalBind;
#define R_ANAL_CONDTYPE_SINGLE(x) (!x->right || x->left==x->right)
typedef struct r_anal_cond_t {
int type; // filled by CJMP opcode
RArchValue *left; // filled by CMP left opcode
RArchValue *right; // filled by CMP right opcode
} RAnalCond;
typedef struct r_anal_bb_t {
RBNode _rb; // private, node in the RBTree
ut64 _max_end; // private, augmented value for RBTree
ut64 addr;
ut64 size;
ut64 jump;
ut64 fail;
ut64 traced; // bitfield (each bit represents 1 trace)
bool folded;
RColor color;
ut8 *fingerprint;
RAnalDiff *diff;
RAnalCond *cond;
RAnalSwitchOp *switch_op;
ut8 *op_bytes;
ut8 *parent_reg_arena;
int parent_reg_arena_size;
#if R2_600
// for the oppos
USE RVec
#else
ut16 *op_pos; // offsets of instructions in this block, count is ninstr - 1 (first is always 0)
int op_pos_size; // size of the op_pos array
int ninstr;
#endif
int stackptr;
int parent_stackptr;
ut64 cmpval;
const char *cmpreg;
ut32 bbhash; // calculated with xxhash
RList *fcns;
RAnal *anal;
char *esil;
int ref;
int depth;
#undef RAnalBlock
} RAnalBlock;
typedef enum {
R_ANAL_REF_TYPE_NULL = 0, // unknown/undefined
R_ANAL_REF_TYPE_ERROR = 1, // unreadable/invalid
R_ANAL_REF_TYPE_CODE = 'c', // code ref
R_ANAL_REF_TYPE_CALL = 'C', // code ref (call) -- maybe use 'k' for kall?
R_ANAL_REF_TYPE_JUMP = 'j', // code ref (call)
R_ANAL_REF_TYPE_DATA = 'd', // mem ref
R_ANAL_REF_TYPE_ICOD = 'i', // indirect code reference
R_ANAL_REF_TYPE_STRN = 's', // string ref
R_ANAL_REF_TYPE_MASK = 0xff,
// perm / direction
R_ANAL_REF_TYPE_READ = 4 << 8,
R_ANAL_REF_TYPE_WRITE = 2 << 8,
R_ANAL_REF_TYPE_EXEC = 1 << 8,
R_ANAL_REF_PERM_MASK = 0xff00, // direction -> perm
R_ANAL_REF_DIRECTION_MASK = 0xff00, // direction -> perm
// SIZE
R_ANAL_REF_TYPE_SIZE_1 = 1 << 16,
R_ANAL_REF_TYPE_SIZE_2 = 2 << 16,
R_ANAL_REF_TYPE_SIZE_4 = 4 << 16,
R_ANAL_REF_TYPE_SIZE_8 = 8 << 16,
R_ANAL_REF_SIZE_MASK = 0xff0000
} RAnalRefType;
#define R_ANAL_REF_TYPE_PERM(x) (((x)>>8) & 0xff)
#define R_ANAL_REF_TYPE_MASK(x) r_anal_ref_typemask((x))
#define R_ANAL_REF_TYPE_SIZE(x) (((x)>>16) & 0xff)
typedef struct r_anal_ref_t {
ut64 at;
ut64 addr;
RAnalRefType type;
} RAnalRef;
typedef struct r_vec_RVecAnalRef_t RVecAnalRef;
/* represents a reference line from one address (from) to another (to) */
typedef struct r_anal_refline_t {
ut64 from;
ut64 to;
int index;
int level;
int type;
int direction;
} RAnalRefline;
typedef struct r_anal_cycle_frame_t {
ut64 naddr; //next addr
RList *hooks;
struct r_anal_cycle_frame_t *prev;
} RAnalCycleFrame;
typedef struct r_anal_cycle_hook_t { //rename ?
ut64 addr;
int cycles;
} RAnalCycleHook;
typedef struct r_esil_word_t {
int type;
const char *str;
} REsilWord;
enum {
R_ANAL_TRAP_NONE = 0,
R_ANAL_TRAP_UNHANDLED = 1,
R_ANAL_TRAP_BREAKPOINT = 2,
R_ANAL_TRAP_DIVBYZERO = 3,
R_ANAL_TRAP_WRITE_ERR = 4,
R_ANAL_TRAP_READ_ERR = 5,
R_ANAL_TRAP_EXEC_ERR = 6,
R_ANAL_TRAP_INVALID = 7,
R_ANAL_TRAP_UNALIGNED = 8,
R_ANAL_TRAP_TODO = 9,
R_ANAL_TRAP_HALT = 10,
};
typedef struct r_anal_esil_cfg_t {
RGraphNode *start;
RGraphNode *end;
RGraph *g;
} RAnalEsilCFG;
// this is 80-bit offsets so we can address every piece of esil in an instruction
typedef struct r_anal_esil_expr_offset_t {
ut64 off;
ut16 idx;
} RAnalEsilEOffset;
typedef enum {
R_ANAL_ESIL_BLOCK_ENTER_NORMAL = 0,
R_ANAL_ESIL_BLOCK_ENTER_TRUE,
R_ANAL_ESIL_BLOCK_ENTER_FALSE,
R_ANAL_ESIL_BLOCK_ENTER_GLUE,
} RAnalEsilBlockEnterType;
typedef struct r_anal_esil_basic_block_t {
RAnalEsilEOffset first;
RAnalEsilEOffset last;
char *expr; //synthesized esil-expression for this block
RAnalEsilBlockEnterType enter; //maybe more type is needed here
} RAnalEsilBB;
enum {
R_ANAL_ESIL_DFG_TAG_CONST = 1,
R_ANAL_ESIL_DFG_TAG_VAR = 2,
R_ANAL_ESIL_DFG_TAG_PTR = 4,
R_ANAL_ESIL_DFG_TAG_RESULT = 8,
R_ANAL_ESIL_DFG_TAG_GENERATIVE = 16,
R_ANAL_ESIL_DFG_TAG_REG = 32,
R_ANAL_ESIL_DFG_TAG_MEM = 64,
R_ANAL_ESIL_DFG_TAG_MERGE = 128,
R_ANAL_ESIL_DFG_TAG_SIBLING = 256,
}; // RAnalEsilDFGTagType
typedef struct r_anal_esil_dfg_t {
ut32 idx;
int fd;
RIOBind iob;
RReg *reg;
Sdb *regs; // resolves regnames to intervals
RRBTree *vars; // vars represented in regs and mem
RQueue *todo; // todo-queue allocated in this struct for perf
void *insert; // needed for setting regs in dfg
RGraph *flow;
RGraphNode *cur;
RGraphNode *old;
REsil *esil;
bool use_map_info;
bool use_maps;
bool malloc_failed;
} RAnalEsilDFG;
typedef struct r_anal_esil_dfg_node_t {
// add more info here
ut32 idx;
RStrBuf *content;
ut32 /*RAnalEsilDFGTagType*/ type;
} RAnalEsilDFGNode;
typedef bool (*RAnalCmdCallback)(/* Rcore */RAnal *anal, const char* input);
typedef int (*RAnalOpCallback)(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
typedef int (*RAnalOpAsmCallback)(RAnal *a, ut64 addr, const char *str, ut8 *outbuf, int outlen);
typedef bool (*RAnalRegProfCallback)(RAnal *a);
typedef char*(*RAnalRegProfGetCallback)(RAnal *a);
typedef int (*RAnalFPBBCallback)(RAnal *a, RAnalBlock *bb);
typedef int (*RAnalFPFcnCallback)(RAnal *a, RAnalFunction *fcn);
typedef int (*RAnalDiffBBCallback)(RAnal *anal, RAnalFunction *fcn, RAnalFunction *fcn2);
typedef int (*RAnalDiffFcnCallback)(RAnal *anal, RList *fcns, RList *fcns2);
typedef int (*RAnalDiffEvalCallback)(RAnal *anal);
typedef int (*REsilCB)(REsil *esil);
typedef int (*REsilLoopCB)(REsil *esil, RAnalOp *op);
typedef int (*REsilTrapCB)(REsil *esil, int trap_type, int trap_code);
typedef struct r_anal_plugin_t {
RPluginMeta meta;
const char *depends; // comma separated list of dependencies
bool (*init)(RAnal *a);
bool (*fini)(RAnal *a);
// legacy r_anal_functions
RAnalOpCallback op;
RAnalCmdCallback cmd;
#if 1
/// XXX unused but referenced, maybe worth checking in case we want them for anal
RAnalFPBBCallback fingerprint_bb;
RAnalFPFcnCallback fingerprint_fcn;
RAnalDiffBBCallback diff_bb;
RAnalDiffFcnCallback diff_fcn;
RAnalDiffEvalCallback diff_eval;
#endif
} RAnalPlugin;
/*----------------------------------------------------------------------------------------------*/
int * (r_anal_compare) (RAnalFunction , RAnalFunction);
/*----------------------------------------------------------------------------------------------*/
#ifdef R_API
R_API ut64 r_anal_value_to_ut64(RAnal *anal, RArchValue *val);
R_API bool r_anal_value_set_ut64(RAnal *anal, RArchValue *val, ut64 num);
/* --------- */ /* R2_590 REFACTOR */ /* ---------- */
R_API RListRange* r_listrange_new(void);
R_API void r_listrange_free(RListRange *s);
R_API void r_listrange_add(RListRange *s, RAnalFunction *f);
R_API void r_listrange_del(RListRange *s, RAnalFunction *f);
R_API void r_listrange_resize(RListRange *s, RAnalFunction *f, int newsize);
R_API RAnalFunction *r_listrange_find_in_range(RListRange* s, ut64 addr);
R_API RAnalFunction *r_listrange_find_root(RListRange* s, ut64 addr);
/* --------- */ /* REFACTOR */ /* ---------- */
/* type.c */
R_API RAnalType *r_anal_type_new(void);
R_API void r_anal_type_add(RAnal *l, RAnalType *t);
R_API RAnalType *r_anal_type_find(RAnal *a, const char* name);
R_API void r_anal_type_list(RAnal *a, short category, short enabled);
R_API const char *r_anal_datatype_tostring(RAnalDataType t);
R_API RAnalType *r_anal_str_to_type(RAnal *a, const char* s);
R_API RAnalType *r_anal_type_free(RAnalType *t);
R_API RAnalType *r_anal_type_loadfile(RAnal *a, const char *path);
R_API bool r_anal_cmd(RAnal *a, const char *cmd);
/* block.c */
typedef bool (*RAnalBlockCb)(RAnalBlock *block, void *user);
typedef bool (*RAnalAddrCb)(ut64 addr, void *user);
// lifetime
R_API void r_anal_block_ref(RAnalBlock *bb);
R_API void r_anal_block_unref(RAnalBlock *bb);
R_API void r_anal_block_reset(RAnal *a);
// Create one block covering the given range.
// This will fail if the range overlaps any existing blocks.
R_API RAnalBlock *r_anal_create_block(RAnal *anal, ut64 addr, ut64 size);
static inline bool r_anal_block_contains(RAnalBlock *bb, ut64 addr) {
return (addr >= bb->addr) && (addr < bb->addr + bb->size);
}
// Split the block at the given address into two blocks.
// bb will stay the first block, the second block will be returned (or NULL on failure)
// The returned block will always be refd, i.e. it is necessary to always call r_anal_block_unref() on the return value!
R_API RAnalBlock *r_anal_block_split(RAnalBlock *bb, ut64 addr);
static inline bool r_anal_block_is_contiguous(RAnalBlock *a, RAnalBlock *b) {
return (a->addr + a->size) == b->addr;
}
// Merge block b into a.
// b will be FREED (not just unrefd) and is NOT VALID anymore if this function is successful!
// This only works if b follows directly after a and their function lists are identical.
// returns true iff the blocks could be merged
R_API bool r_anal_block_merge(RAnalBlock *a, RAnalBlock *b);
// Manually delete a block and remove it from all its functions
// If there are more references to it than from its functions only, it will not be removed immediately!
R_API void r_anal_delete_block(RAnalBlock *bb);
R_API void r_anal_delete_block_at(RAnal *anal, ut64 addr);
R_API void r_anal_block_set_size(RAnalBlock *block, ut64 size);
// Set the address and size of the block.
// This can fail (and return false) if there is already another block at the new address
R_API bool r_anal_block_relocate(RAnalBlock *block, ut64 addr, ut64 size);
R_API ut64 r_anal_block_ninstr(RAnalBlock *block, int pos);
R_API RAnalBlock *r_anal_get_block_at(RAnal *anal, ut64 addr);
R_API bool r_anal_blocks_foreach_in(RAnal *anal, ut64 addr, RAnalBlockCb cb, void *user);
R_API RList *r_anal_get_blocks_in(RAnal *anal, ut64 addr); // values from r_anal_blocks_foreach_in as a list
R_API void r_anal_blocks_foreach_intersect(RAnal *anal, ut64 addr, ut64 size, RAnalBlockCb cb, void *user);
R_API RList *r_anal_get_blocks_intersect(RAnal *anal, ut64 addr, ut64 size); // values from r_anal_blocks_foreach_intersect as a list
// Call cb on every direct successor address of block
// returns false if the loop was breaked by cb
R_API bool r_anal_block_successor_addrs_foreach(RAnalBlock *block, RAnalAddrCb cb, void *user);
// Call cb on block and every (recursive) successor of it
// returns false if the loop was breaked by cb
R_API bool r_anal_block_recurse(RAnalBlock *block, RAnalBlockCb cb, void *user);
// Call cb on block and every (recursive) successor of it
// If cb returns false, recursion stops only for that block
// returns false if the loop was breaked by cb
R_API bool r_anal_block_recurse_followthrough(RAnalBlock *block, RAnalBlockCb cb, void *user);
// Call cb on block and every (recursive) successor of it
// Call on_exit on block that doesn't have non-visited successors
// returns false if the loop was breaked by cb
R_API bool r_anal_block_recurse_depth_first(RAnalBlock *block, RAnalBlockCb cb, R_NULLABLE RAnalBlockCb on_exit, void *user);
// same as r_anal_block_recurse, but returns the blocks as a list
R_API RList *r_anal_block_recurse_list(RAnalBlock *block);
// return one shortest path from block to dst or NULL if none exists.
R_API R_NULLABLE RList/*<RAnalBlock *>*/ *r_anal_block_shortest_path(RAnalBlock *block, ut64 dst);
// Add a case to the block's switch_op.
// If block->switch_op is NULL, it will be created with the given switch_addr.
R_API void r_anal_block_add_switch_case(RAnalBlock *block, ut64 switch_addr, ut64 case_value, ut64 case_addr);
// Chop off the block at the specified address and remove all destinations.
// Blocks that have become unreachable after this operation will be automatically removed from all functions of block.
// addr must be the address directly AFTER the noreturn call!
// After the chopping, an r_anal_block_automerge() is performed on the touched blocks.
// IMPORTANT: The automerge might also FREE block! This function returns block iff it is still valid afterwards.
// If this function returns NULL, the pointer to block MUST not be touched anymore!
R_API RAnalBlock *r_anal_block_chop_noreturn(RAnalBlock *block, ut64 addr);
// Merge every block in blocks with their contiguous predecessor, if possible.
// IMPORTANT: Merged blocks will be FREED! The blocks list will be updated to contain only the survived blocks.
R_API void r_anal_block_automerge(RList *blocks);
// return true iff an instruction in the given basic block starts at the given address
R_API bool r_anal_block_op_starts_at(RAnalBlock *block, ut64 addr);
// Updates bbhash based on current bytes inside the block
R_API void r_anal_block_update_hash(RAnalBlock *block);
// returns true if a byte in the given basic block was modified
R_API bool r_anal_block_was_modified(RAnalBlock *block);
// ---------------------------------------
/* function.c */
R_API RAnalFunction *r_anal_function_new(RAnal *anal);
R_API void r_anal_function_free(RAnalFunction *fcn);
// Add a function created with r_anal_function_new() to anal
R_API bool r_anal_add_function(RAnal *anal, RAnalFunction *fcn);
// Create a new function and add it to anal (r_anal_function_new() + set members + r_anal_add_function())
R_API RAnalFunction *r_anal_create_function(RAnal *anal, const char *name, ut64 addr, int type, RAnalDiff *diff);
// returns all functions that have a basic block containing the given address
R_API RList *r_anal_get_functions_in(RAnal *anal, ut64 addr);
// returns the function that has its entrypoint at addr or NULL
R_API RAnalFunction *r_anal_get_function_at(RAnal *anal, ut64 addr);
R_API bool r_anal_function_delete(RAnalFunction *fcn);
// rhange the entrypoint of fcn
// This can fail (and return false) if there is already another function at the new address
R_API bool r_anal_function_relocate(RAnalFunction *fcn, ut64 addr);
// rename the given function
// This can fail (and return false) if there is another function with the name given
R_API bool r_anal_function_rename(RAnalFunction *fcn, const char *name);
R_API void r_anal_function_add_block(RAnalFunction *fcn, RAnalBlock *bb);
R_API void r_anal_function_remove_block(RAnalFunction *fcn, RAnalBlock *bb);
// size of the entire range that the function spans, including holes.
// this is exactly r_anal_function_max_addr() - r_anal_function_min_addr()
R_API ut64 r_anal_function_linear_size(RAnalFunction *fcn);
// lowest address covered by the function
R_API ut64 r_anal_function_min_addr(RAnalFunction *fcn);
// first address directly after the function
R_API ut64 r_anal_function_max_addr(RAnalFunction *fcn);
// size from the function entrypoint (fcn->addr) to the end of the function (r_anal_function_max_addr)
R_API ut64 r_anal_function_size_from_entry(RAnalFunction *fcn);
// the "real" size of the function, that is the sum of the size of the
// basicblocks this function is composed of
R_API ut64 r_anal_function_realsize(const RAnalFunction *fcn);
// returns whether the function contains a basic block that contains addr
// This is completely independent of fcn->addr, which is only the entrypoint!
R_API bool r_anal_function_contains(RAnalFunction *fcn, ut64 addr);
// returns true if function bytes were modified