Rizin
unix-like reverse engineering framework and cli tools
io_shm.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "rz_io.h"
5 #include "rz_lib.h"
6 #include <sys/types.h>
7 
8 #if HAVE_HEADER_LINUX_ASHMEM_H || HAVE_HEADER_SYS_SHM_H || __WINDOWS__
9 #if HAVE_HEADER_LINUX_ASHMEM_H
10 #include <linux/ashmem.h>
11 #endif
12 #if HAVE_HEADER_SYS_SHM_H
13 #include <sys/shm.h>
14 #endif
15 #if HAVE_HEADER_SYS_IPC_H
16 #include <sys/ipc.h>
17 #endif
18 #if HAVE_HEADER_SYS_MMAN_H
19 #include <sys/mman.h>
20 #endif
21 #if __WINDOWS__
22 #include <windows.h>
23 #endif
24 
25 typedef struct {
26 #if __WINDOWS__
27  HANDLE h;
28 #else
29  int fd;
30  int id;
31 #endif
32  char *name;
33  ut8 *buf;
34  ut32 size;
35 } RzIOShm;
36 
37 #define SHMATSZ 0x9000; // 32*1024*1024; /* 32MB : XXX not used correctly? */
38 
39 static int shm__write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count) {
40  rz_return_val_if_fail(fd && fd->data, -1);
41  RzIOShm *shm = fd->data;
42  if (shm->buf) {
43  (void)memcpy(shm->buf + io->off, buf, count);
44  return count;
45  }
46 #if !defined(__WINDOWS__)
47  return write(shm->fd, buf, count);
48 #else
49  return 0;
50 #endif
51 }
52 
53 static int shm__read(RzIO *io, RzIODesc *fd, ut8 *buf, int count) {
54  rz_return_val_if_fail(fd && fd->data, -1);
55  RzIOShm *shm = fd->data;
56  if (io->off + count >= shm->size) {
57  if (io->off > shm->size) {
58  return -1;
59  }
60  count = shm->size - io->off;
61  }
62  if (shm->buf) {
63  memcpy(buf, shm->buf + io->off, count);
64  return count;
65  }
66 #if !defined(__WINDOWS__)
67  return read(shm->fd, buf, count);
68 #else
69  return 0;
70 #endif
71 }
72 
73 static int shm__close(RzIODesc *fd) {
74  rz_return_val_if_fail(fd && fd->data, -1);
75  int ret;
76  RzIOShm *shm = fd->data;
77 #if __WINDOWS__
78  UnmapViewOfFile(shm->buf);
79  ret = CloseHandle(shm->h);
80 #else
81 #if HAVE_SHM_OPEN || HAVE_HEADER_LINUX_ASHMEM_H
82  ret = close(shm->fd);
83 #else
84  if (shm->buf) {
85  ret = shmdt(((RzIOShm *)(fd->data))->buf);
86  } else {
87  ret = close(shm->fd);
88  }
89 #endif
90 #endif
91  free(shm->name);
92  RZ_FREE(fd->data);
93  return ret;
94 }
95 
96 static ut64 shm__lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {
97  rz_return_val_if_fail(fd && fd->data, -1);
98  RzIOShm *shm = fd->data;
99  switch (whence) {
100  case RZ_IO_SEEK_SET:
101  return io->off = offset;
102  case RZ_IO_SEEK_CUR:
103  if (io->off + offset > shm->size) {
104  return io->off = shm->size;
105  }
106  io->off += offset;
107  return io->off;
108  case RZ_IO_SEEK_END:
109  return io->off = (shm->size ? shm->size : 0xffffffff) + offset;
110  }
111  return io->off;
112 }
113 
114 static bool shm__plugin_open(RzIO *io, const char *pathname, bool many) {
115  return (!strncmp(pathname, "shm://", 6));
116 }
117 
118 #if !HAVE_SHM_OPEN && !HAVE_HEADER_LINUX_ASHMEM_H
119 static inline int getshmfd(RzIOShm *shm) {
120  return (((int)(size_t)shm->buf) >> 4) & 0xfff;
121 }
122 #endif
123 
124 static RzIODesc *shm__open(RzIO *io, const char *uri, int rw, int mode) {
125  if (strncmp(uri, "shm://", 6)) {
126  return NULL;
127  }
128  RzIOShm *shm = RZ_NEW0(RzIOShm);
129  if (!shm) {
130  return NULL;
131  }
132  const char *name = strstr(uri, "://");
133  if (!name) {
134  free(shm);
135  return NULL;
136  }
137  name += 3;
138 
139  // The shared memory size is an optional parameter
140  char *size = strstr(name, "/");
141  if (size) {
142  *size = 0;
143  size += 1;
144  }
145 
146  shm->name = rz_str_newf("/%s", name);
147 #if __WINDOWS__
148  LPWSTR wname = rz_utf8_to_utf16(name);
149  const DWORD desired_access = rw ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ;
150  shm->h = OpenFileMappingW(desired_access, FALSE, wname);
151  free(wname);
152  if (!shm->h) {
153  RZ_LOG_ERROR("Cannot open shared memory \"%s\"\n", shm->name);
154  free(shm->name);
155  free(shm);
156  return NULL;
157  }
158  size_t given_size = 0;
159  if (size && (given_size = rz_num_math(NULL, size))) {
160  shm->size = given_size;
161  }
162  shm->buf = MapViewOfFile(shm->h, desired_access, 0, 0, given_size);
163  if (!shm->buf) {
164  RZ_LOG_ERROR("Cannot map shared memory \"%s\"\n", shm->name);
165  CloseHandle(shm->h);
166  free(shm->name);
167  free(shm);
168  }
169  if (!given_size) {
170  MEMORY_BASIC_INFORMATION mi;
171  if (VirtualQuery(shm->buf, &mi, sizeof(mi)) == sizeof(mi)) {
172  shm->size = mi.RegionSize;
173  }
174  }
175  RZ_LOG_INFO("Connected to shared memory \"%s\" size 0x%x\n",
176  shm->name, shm->size);
177 #else
178 #if HAVE_SHM_OPEN || HAVE_HEADER_LINUX_ASHMEM_H
179  shm->id = rz_str_djb2_hash(name);
180 
181 #if HAVE_SHM_OPEN
182  shm->fd = shm_open(shm->name, O_CREAT | (rw ? O_RDWR : O_RDONLY), 0644);
183 #else // HAVE_HEADER_LINUX_ASHMEM_H
184  shm->fd = open("/dev/ashmem", O_CREAT | (rw ? O_RDWR : O_RDONLY), 0644);
185 #endif
186  if (shm->fd == -1) {
187  RZ_LOG_ERROR("Cannot connect to shared memory \"%s\" (0x%08x)\n", shm->name, shm->id);
188  free(shm->name);
189  free(shm);
190  return NULL;
191  }
192  ut64 given_size = 0;
193  // If the memory size is supplied - we use it,
194  // otherwise try to read it from the file descriptor itself
195  if (size && (given_size = rz_num_math(NULL, size))) {
196  shm->size = given_size;
197  } else {
198  struct stat st;
199  if (fstat(shm->fd, &st)) {
200  RZ_LOG_ERROR("Cannot determine the size of shared memory \"%s\" (0x%08x)\n", shm->name, shm->id);
201  close(shm->fd);
202  free(shm->name);
203  free(shm);
204  return NULL;
205  }
206  shm->size = st.st_size;
207  }
208 
209 #if HAVE_HEADER_LINUX_ASHMEM_H
210  if (ioctl(shm->fd, ASHMEM_SET_NAME, name) == -1 ||
211  ioctl(shm->fd, ASHMEM_SET_SIZE, shm->size) == -1) {
212  RZ_LOG_ERROR("Cannot set shared memory \"%s\"/%lu (0x%08x)\n", shm->name, (unsigned long)shm->size, shm->id);
213  close(shm->fd);
214  free(shm->name);
215  free(shm);
216  return NULL;
217  }
218 #endif
219  shm->buf = mmap(NULL, shm->size, (rw ? (PROT_READ | PROT_WRITE) : PROT_READ), MAP_SHARED, shm->fd, 0);
220  if (shm->buf == MAP_FAILED) {
221  RZ_LOG_ERROR("Cannot mmap shared memory \"%s\"/%lu (0x%08x)", shm->name, (unsigned long)shm->size, shm->id);
222  close(shm->fd);
223  free(shm->name);
224  free(shm);
225  return NULL;
226  }
227 #else
228  shm->id = atoi(ptr);
229  if (!shm->id) {
230  shm->id = rz_str_djb2_hash(ptr);
231  }
232 
233  shm->buf = shmat(shm->id, 0, 0);
234  if (shm->buf == (void *)(size_t)-1) {
235  shm->fd = -1;
236  } else {
237  shm->fd = getshmfd(shm);
238  }
239  shm->size = SHMATSZ;
240  if (shm->fd == -1) {
241  RZ_LOG_ERROR("Cannot connect to shared memory (%d)\n", shm->id);
242  free(shm->name);
243  free(shm);
244  return NULL;
245  }
246 #endif
247  RZ_LOG_INFO("Connected to shared memory \"%s\" (0x%08x) size 0x%x\n",
248  shm->name, shm->id, shm->size);
249 #endif // __WINDOWS__
250  return rz_io_desc_new(io, &rz_io_plugin_shm, uri, rw, mode, shm);
251 }
252 
254  .name = "shm",
255  .desc = "Shared memory resources plugin",
256  .uris = "shm://",
257  .license = "MIT",
258  .open = shm__open,
259  .close = shm__close,
260  .read = shm__read,
261  .check = shm__plugin_open,
262  .lseek = shm__lseek,
263  .write = shm__write,
264 };
265 
266 #else
268  .name = "shm",
269  .desc = "shared memory resources",
270 };
271 #endif
272 
273 #ifndef RZ_PLUGIN_INCORE
275  .type = RZ_LIB_TYPE_IO,
276  .data = &rz_io_plugin_shm,
278 };
279 #endif
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg shmat
Definition: sflib.h:122
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset fstat
Definition: sflib.h:107
static static sync static getppid static getegid const char static filename ioctl
Definition: sflib.h:62
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RzIOPlugin rz_io_plugin_shm
Definition: io_shm.c:267
RZ_API RzLibStruct rizin_plugin
Definition: io_shm.c:274
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char pathname
Definition: sflib.h:66
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags mmap
Definition: sflib.h:115
#define FALSE
Definition: mybfd.h:102
const char * name
Definition: op.c:541
int id
Definition: op.c:540
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_IO_SEEK_CUR
Definition: rz_io.h:16
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
Definition: io_desc.c:11
#define RZ_IO_SEEK_SET
Definition: rz_io.h:15
#define RZ_IO_SEEK_END
Definition: rz_io.h:17
@ RZ_LIB_TYPE_IO
Definition: rz_lib.h:69
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API ut64 rz_str_djb2_hash(const char *str)
Definition: str.c:383
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_VERSION
Definition: rz_version.h:8
#define PROT_READ
Definition: sftypes.h:95
#define O_CREAT
Definition: sftypes.h:489
#define PROT_WRITE
Definition: sftypes.h:96
#define MAP_SHARED
Definition: sftypes.h:101
#define O_RDONLY
Definition: sftypes.h:486
#define O_RDWR
Definition: sftypes.h:488
#define h(i)
Definition: sha256.c:48
Definition: z80asm.h:102
const char * name
Definition: rz_io.h:115
const char * version
Definition: rz_io.h:117
Definition: rz_io.h:59
ut64 off
Definition: rz_io.h:61
Definition: sftypes.h:80
DWORD LPWSTR
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
DWORD
static const z80_opcode fd[]
Definition: z80_tab.h:997
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115