1 /* radare - LGPL3 - Copyright 2016-2020 - c0riolis, x0urc3 */
2
3 #include <r_bin.h>
4 #include "../format/pyc/pyc.h"
5
6 // XXX: to not use globals
7
8 static ut64 code_start_offset = 0;
9 static struct pyc_version version;
10 /* used from marshall.c */
11 RList *interned_table = NULL;
12 static RList *sections_cache = NULL;
13
check_buffer(RBuffer * b)14 static bool check_buffer(RBuffer *b) {
15 if (r_buf_size (b) > 4) {
16 ut32 buf;
17 r_buf_read_at (b, 0, (ut8 *)&buf, sizeof (buf));
18 version = get_pyc_version (buf);
19 return version.magic != -1;
20 }
21 return false;
22 }
23
load_buffer(RBinFile * bf,void ** bin_obj,RBuffer * buf,ut64 loadaddr,Sdb * sdb)24 static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
25 return check_buffer (buf);
26 }
27
get_entrypoint(RBuffer * buf)28 static ut64 get_entrypoint(RBuffer *buf) {
29 ut8 b;
30 ut64 result;
31 int addr;
32 for (addr = 0x8; addr <= 0x10; addr += 0x4) {
33 r_buf_read_at (buf, addr, &b, sizeof (b));
34 if (pyc_is_code (b, version.magic)) {
35 code_start_offset = addr;
36 r_buf_seek (buf, addr + 1, R_BUF_SET);
37 if ((result = get_code_object_addr (buf, version.magic)) == 0) {
38 return addr;
39 }
40 return result;
41 }
42 }
43 return 0;
44 }
45
info(RBinFile * arch)46 static RBinInfo *info(RBinFile *arch) {
47 RBinInfo *ret = R_NEW0 (RBinInfo);
48 if (!ret) {
49 return NULL;
50 }
51 ret->file = strdup (arch->file);
52 ret->type = r_str_newf ("Python %s byte-compiled file", version.version);
53 ret->bclass = strdup ("Python byte-compiled file");
54 ret->rclass = strdup ("pyc");
55 ret->arch = strdup ("pyc");
56 ret->machine = r_str_newf ("Python %s VM (rev %s)", version.version,
57 version.revision);
58 ret->os = strdup ("any");
59 ret->bits = version2double (version.version) < 3.6? 16: 8;
60 ret->cpu = strdup (version.version); // pass version info in cpu, Asm plugin will get it
61 return ret;
62 }
63
sections(RBinFile * arch)64 static RList *sections(RBinFile *arch) {
65 return sections_cache;
66 }
67
entries(RBinFile * arch)68 static RList *entries(RBinFile *arch) {
69 RList *entries = r_list_newf ((RListFree)free);
70 if (!entries) {
71 return NULL;
72 }
73 RBinAddr *addr = R_NEW0 (RBinAddr);
74 if (!addr) {
75 r_list_free (entries);
76 return NULL;
77 }
78 ut64 entrypoint = get_entrypoint (arch->buf);
79 addr->paddr = entrypoint;
80 addr->vaddr = entrypoint;
81 r_buf_seek (arch->buf, entrypoint, R_IO_SEEK_SET);
82 r_list_append (entries, addr);
83 return entries;
84 }
85
baddr(RBinFile * bf)86 static ut64 baddr(RBinFile *bf) {
87 return 0;
88 }
89
symbols(RBinFile * arch)90 static RList *symbols(RBinFile *arch) {
91 RList *shared = r_list_newf ((RListFree)r_list_free);
92 if (!shared) {
93 return NULL;
94 }
95 RList *cobjs = r_list_newf ((RListFree)free);
96 if (!cobjs) {
97 r_list_free (shared);
98 return NULL;
99 }
100 interned_table = r_list_newf ((RListFree)free);
101 if (!interned_table) {
102 r_list_free (shared);
103 r_list_free (cobjs);
104 return NULL;
105 }
106 r_list_append (shared, cobjs);
107 r_list_append (shared, interned_table);
108 arch->o->bin_obj = shared;
109 RList *sections = r_list_newf ((RListFree)free);
110 if (!sections) {
111 r_list_free (shared);
112 arch->o->bin_obj = NULL;
113 return NULL;
114 }
115 RList *symbols = r_list_newf ((RListFree)free);
116 if (!symbols) {
117 r_list_free (shared);
118 arch->o->bin_obj = NULL;
119 r_list_free (sections);
120 return NULL;
121 }
122 RBuffer *buffer = arch->buf;
123 r_buf_seek (buffer, code_start_offset, R_BUF_SET);
124 pyc_get_sections_symbols (sections, symbols, cobjs, buffer, version.magic);
125 sections_cache = sections;
126 return symbols;
127 }
128
129 RBinPlugin r_bin_plugin_pyc = {
130 .name = "pyc",
131 .desc = "Python byte-compiled file plugin",
132 .license = "LGPL3",
133 .info = &info,
134 .load_buffer = &load_buffer,
135 .check_buffer = &check_buffer,
136 .entries = &entries,
137 .sections = §ions,
138 .baddr = &baddr,
139 .symbols = &symbols,
140 };
141
142 #ifndef R2_PLUGIN_INCORE
143 R_API RLibStruct radare_plugin = {
144 .type = R_LIB_TYPE_BIN,
145 .data = &r_bin_plugin_pyc,
146 .version = R2_VERSION,
147 };
148 #endif
149