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 = &sections,
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