1 /* radare - LGPL - Copyright 2010-2016 pancake */
2 
3 #include <r_io.h>
4 #include <r_lib.h>
5 #include <r_socket.h>
6 #include <r_util.h>
7 #define IRAPI static inline
8 #include <libqnxr.h>
9 
10 typedef struct {
11 	libqnxr_t desc;
12 } RIOQnx;
13 
14 static libqnxr_t *desc = NULL;
15 static RIODesc *rioqnx = NULL;
16 
__plugin_open(RIO * io,const char * file,bool many)17 static bool __plugin_open (RIO *io, const char *file, bool many) {
18 	return (!strncmp (file, "qnx://", 6));
19 }
20 
21 /* hacky cache to speedup io a bit */
22 /* reading in a different place clears the previous cache */
23 static ut64 c_addr = UT64_MAX;
24 static ut32 c_size = UT32_MAX;
25 static ut8 *c_buff = NULL;
26 #define SILLY_CACHE 0
27 
debug_qnx_read_at(ut8 * buf,int sz,ut64 addr)28 static int debug_qnx_read_at (ut8 *buf, int sz, ut64 addr) {
29 	ut32 size_max = 500;
30 	ut32 packets = sz / size_max;
31 	ut32 last = sz % size_max;
32 	ut32 x;
33 	if (c_buff && addr != UT64_MAX && addr == c_addr) {
34 		memcpy (buf, c_buff, sz);
35 		return sz;
36 	}
37 	if (sz < 1 || addr >= UT64_MAX) {
38 		return -1;
39 	}
40 	for (x = 0; x < packets; x++) {
41 		qnxr_read_memory (desc, addr + x * size_max, (buf + x * size_max), size_max);
42 	}
43 	if (last) {
44 		qnxr_read_memory (desc, addr + x * size_max, (buf + x * size_max), last);
45 	}
46 	c_addr = addr;
47 	c_size = sz;
48 #if SILLY_CACHE
49 	free (c_buff);
50 	c_buff = r_mem_dup (buf, sz);
51 #endif
52 	return sz;
53 }
54 
debug_qnx_write_at(const ut8 * buf,int sz,ut64 addr)55 static int debug_qnx_write_at (const ut8 *buf, int sz, ut64 addr) {
56 	ut32 x, size_max = 500;
57 	ut32 packets = sz / size_max;
58 	ut32 last = sz % size_max;
59 
60 	if (sz < 1 || addr >= UT64_MAX) {
61 		return -1;
62 	}
63 	if (c_addr != UT64_MAX && addr >= c_addr && c_addr + sz < (c_addr + c_size)) {
64 		R_FREE (c_buff);
65 		c_addr = UT64_MAX;
66 	}
67 	for (x = 0; x < packets; x++) {
68 		qnxr_write_memory (desc, addr + x * size_max,
69 				   (const uint8_t *)(buf + x * size_max), size_max);
70 	}
71 	if (last) {
72 		qnxr_write_memory (desc, addr + x * size_max,
73 				   (buf + x * size_max), last);
74 	}
75 
76 	return sz;
77 }
78 
__open(RIO * io,const char * file,int rw,int mode)79 static RIODesc *__open (RIO *io, const char *file, int rw, int mode) {
80 	RIOQnx *rioq;
81 	char host[128], *port, *p;
82 
83 	if (!__plugin_open (io, file, 0)) {
84 		return NULL;
85 	}
86 	if (rioqnx) {
87 		// FIX: Don't allocate more than one RIODesc
88 		return rioqnx;
89 	}
90 	strncpy (host, file + 6, sizeof(host) - 1);
91 	host[sizeof(host) - 1] = '\0';
92 	port = strchr (host, ':');
93 	if (!port) {
94 		eprintf ("Port not specified. Please use qnx://[host]:[port]\n");
95 		return NULL;
96 	}
97 	*port = '\0';
98 	port++;
99 	p = strchr (port, '/');
100 	if (p) {
101 		*p = 0;
102 	}
103 
104 	if (r_sandbox_enable (0)) {
105 		eprintf ("sandbox: Cannot use network\n");
106 		return NULL;
107 	}
108 	rioq = R_NEW0 (RIOQnx);
109 	qnxr_init (&rioq->desc);
110 	int i_port = atoi (port);
111 	if (qnxr_connect (&rioq->desc, host, i_port) == 0) {
112 		desc = &rioq->desc;
113 		rioqnx = r_io_desc_new (io, &r_io_plugin_qnx, file, rw, mode, rioq);
114 		return rioqnx;
115 	}
116 	eprintf ("qnx.io.open: Cannot connect to host.\n");
117 	free (rioq);
118 	return NULL;
119 }
120 
__write(RIO * io,RIODesc * fd,const ut8 * buf,int count)121 static int __write (RIO *io, RIODesc *fd, const ut8 *buf, int count) {
122 	ut64 addr = io->off;
123 	if (!desc) {
124 		return -1;
125 	}
126 	return debug_qnx_write_at (buf, count, addr);
127 }
128 
__lseek(RIO * io,RIODesc * fd,ut64 offset,int whence)129 static ut64 __lseek (RIO *io, RIODesc *fd, ut64 offset, int whence) {
130 	return offset;
131 }
132 
__read(RIO * io,RIODesc * fd,ut8 * buf,int count)133 static int __read (RIO *io, RIODesc *fd, ut8 *buf, int count) {
134 	memset (buf, 0xff, count);
135 	ut64 addr = io->off;
136 	if (!desc) {
137 		return -1;
138 	}
139 	return debug_qnx_read_at (buf, count, addr);
140 }
141 
__close(RIODesc * fd)142 static int __close (RIODesc *fd) {
143 	// TODO
144 	return -1;
145 }
146 
__system(RIO * io,RIODesc * fd,const char * cmd)147 static char *__system (RIO *io, RIODesc *fd, const char *cmd) {
148 	return NULL;
149 }
150 
151 RIOPlugin r_io_plugin_qnx = {
152 	.name = "qnx",
153 	.license = "LGPL3",
154 	.desc = "Attach to QNX pdebug instance",
155 	.uris = "qnx://",
156 	.open = __open,
157 	.close = __close,
158 	.read = __read,
159 	.write = __write,
160 	.check = __plugin_open,
161 	.lseek = __lseek,
162 	.system = __system,
163 	.isdbg = true
164 };
165 
166 #ifndef R2_PLUGIN_INCORE
167 R_API RLibStruct radare_plugin = {
168 	.type = R_LIB_TYPE_IO,
169 	.data = &r_io_plugin_qnx,
170 	.version = R2_VERSION
171 };
172 #endif
173