Rizin
unix-like reverse engineering framework and cli tools
utils.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016 madprogrammer
2 // SPDX-FileCopyrightText: 2016 FSF Inc
3 // SPDX-License-Identifier: GPL-2.0-only
4 
5 #include <errno.h>
6 #include <rz_types.h>
7 #include "utils.h"
8 
9 #define I386_NUM_GREGS 16
10 #define I386_NUM_FREGS 16
11 #define I386_NUM_XREGS 9
12 
13 #define NUM_GPREGS 13
14 
15 #define I386_SSE_NUM_REGS (I386_NUM_GREGS + I386_NUM_FREGS + I386_NUM_XREGS)
16 
17 #define I387_NUM_XMM_REGS 8
18 #define I387_ST0_REGNUM I386_ST0_REGNUM
19 #define I387_FCTRL_REGNUM (I387_ST0_REGNUM + 8)
20 #define I387_FSTAT_REGNUM (I387_FCTRL_REGNUM + 1)
21 #define I387_FTAG_REGNUM (I387_FCTRL_REGNUM + 2)
22 #define I387_FISEG_REGNUM (I387_FCTRL_REGNUM + 3)
23 #define I387_FIOFF_REGNUM (I387_FCTRL_REGNUM + 4)
24 #define I387_FOSEG_REGNUM (I387_FCTRL_REGNUM + 5)
25 #define I387_FOOFF_REGNUM (I387_FCTRL_REGNUM + 6)
26 #define I387_FOP_REGNUM (I387_FCTRL_REGNUM + 7)
27 #define I387_XMM0_REGNUM (I387_ST0_REGNUM + 16)
28 #define I387_MXCSR_REGNUM (I387_XMM0_REGNUM + I387_NUM_XMM_REGS)
29 
30 /* These correspond to the DSMSG_* versions in dsmsgs.h. */
31 enum {
37 };
38 
40  I386_EAX_REGNUM, /* %eax */
41  I386_ECX_REGNUM, /* %ecx */
42  I386_EDX_REGNUM, /* %edx */
43  I386_EBX_REGNUM, /* %ebx */
44  I386_ESP_REGNUM, /* %esp */
45  I386_EBP_REGNUM, /* %ebp */
46  I386_ESI_REGNUM, /* %esi */
47  I386_EDI_REGNUM, /* %edi */
48  I386_EIP_REGNUM, /* %eip */
49  I386_EFLAGS_REGNUM, /* %eflags */
50  I386_CS_REGNUM, /* %cs */
51  I386_SS_REGNUM, /* %ss */
52  I386_DS_REGNUM, /* %ds */
53  I386_ES_REGNUM, /* %es */
54  I386_FS_REGNUM, /* %fs */
55  I386_GS_REGNUM, /* %gs */
56  I386_ST0_REGNUM /* %st(0) */
57 };
58 
60  7 * 4, /* %eax */
61  6 * 4, /* %ecx */
62  5 * 4, /* %edx */
63  4 * 4, /* %ebx */
64  11 * 4, /* %esp */
65  2 * 4, /* %epb */
66  1 * 4, /* %esi */
67  0 * 4, /* %edi */
68  8 * 4, /* %eip */
69  10 * 4, /* %eflags */
70  9 * 4, /* %cs */
71  12 * 4, /* %ss */
72  -1 /* filler */
73 };
74 
75 /* Pdebug returns errno values on Neutrino that do not correspond to right
76  errno values on host side. */
77 
78 #define NTO_ENAMETOOLONG 78
79 #define NTO_ELIBACC 83
80 #define NTO_ELIBBAD 84
81 #define NTO_ELIBSCN 85
82 #define NTO_ELIBMAX 86
83 #define NTO_ELIBEXEC 87
84 #define NTO_EILSEQ 88
85 #define NTO_ENOSYS 89
86 
87 #if defined(__linux__) || defined(__WINDOWS__) || defined(__APPLE__) || defined(__CYGWIN__) || defined(MINGW32) || defined(__NetBSD__)
88 
89 struct errnomap_t {
90  int nto;
91  int other;
92 };
93 
94 int errnoconvert(int x) {
95  struct errnomap_t errnomap[] = {
96 #if defined(__linux__)
97  { NTO_ENAMETOOLONG, ENAMETOOLONG },
98  { NTO_ELIBACC, ELIBACC },
99  { NTO_ELIBBAD, ELIBBAD },
100  { NTO_ELIBSCN, ELIBSCN },
101  { NTO_ELIBMAX, ELIBMAX },
102  { NTO_ELIBEXEC, ELIBEXEC },
103  { NTO_EILSEQ, EILSEQ },
104  { NTO_ENOSYS, ENOSYS }
105 #elif defined(__CYGWIN__)
106  { NTO_ENAMETOOLONG, ENAMETOOLONG },
107  { NTO_ENOSYS, ENOSYS }
108 #elif defined(__MINGW32__) || defined(MINGW32) || defined(__NetBSD__)
109  /* The closest mappings from mingw's errno.h. */
110  { NTO_ENAMETOOLONG, ENAMETOOLONG },
111  { NTO_ELIBACC, ESRCH },
112  { NTO_ELIBBAD, ESRCH },
113  { NTO_ELIBSCN, ENOEXEC },
114  { NTO_ELIBMAX, EPERM },
115  { NTO_ELIBEXEC, ENOEXEC },
116  { NTO_EILSEQ, EILSEQ },
117  { NTO_ENOSYS, ENOSYS }
118 #else
119  { 0 }
120 #endif
121  };
122  int i;
123 
124  for (i = 0; i < sizeof(errnomap) / sizeof(errnomap[0]); i++)
125  if (errnomap[i].nto == x)
126  return errnomap[i].other;
127  return x;
128 }
129 
130 #else
131 int errnoconvert(int x) {
132  return x;
133 }
134 #endif /* __QNXNTO__ */
135 
136 LONGEST
137 extract_signed_integer(const ut8 *addr, int len, int be) {
138  LONGEST retval;
139  const ut8 *p;
140  const ut8 *startaddr = addr;
141  const ut8 *endaddr = startaddr + len;
142 
143  if (len > (int)sizeof(LONGEST))
144  eprintf(
145  "This operation is not available on integers of more than %d byte(s)\n",
146  (int)sizeof(LONGEST));
147 
148  /* Start at the most significant end of the integer, and work towards
149  the least significant. */
150  if (be) {
151  p = startaddr;
152  /* Do the sign extension once at the start. */
153  retval = ((LONGEST)*p ^ 0x80) - 0x80;
154  for (++p; p < endaddr; p++)
155  retval = (retval << 8) | *p;
156  } else {
157  p = endaddr - 1;
158  /* Do the sign extension once at the start. */
159  retval = ((LONGEST)*p ^ 0x80) - 0x80;
160  for (--p; p >= startaddr; --p)
161  retval = (retval << 8) | *p;
162  }
163  return retval;
164 }
165 
166 ULONGEST
167 extract_unsigned_integer(const ut8 *addr, int len, int be) {
168  ULONGEST retval;
169  const ut8 *p;
170  const ut8 *startaddr = addr;
171  const ut8 *endaddr = startaddr + len;
172 
173  if (len > (int)sizeof(LONGEST))
174  eprintf(
175  "This operation is not available on integers of more than %d byte(s)\n",
176  (int)sizeof(LONGEST));
177 
178  /* Start at the most significant end of the integer, and work towards
179  the least significant. */
180  retval = 0;
181  if (be) {
182  for (p = startaddr; p < endaddr; ++p)
183  retval = (retval << 8) | *p;
184  } else {
185  for (p = endaddr - 1; p >= startaddr; --p)
186  retval = (retval << 8) | *p;
187  }
188  return retval;
189 }
190 
191 int i386nto_regset_id(int regno) {
192  if (regno == -1)
193  return NTO_REG_END;
194  if (regno < I386_NUM_GREGS)
195  return NTO_REG_GENERAL;
196  if (regno < I386_NUM_GREGS + I386_NUM_FREGS)
197  return NTO_REG_FLOAT;
198  if (regno < I386_SSE_NUM_REGS)
199  return NTO_REG_FLOAT; /* We store xmm registers in fxsave_area. */
200 
201  return -1;
202 }
203 
204 int i386nto_reg_offset(int regnum) {
205  if (regnum >= 0 && regnum < ARRAY_SIZE(i386nto_gregset_reg_offset))
206  return i386nto_gregset_reg_offset[regnum];
207 
208  return -1;
209 }
210 
211 int i386nto_register_area(int regno, int regset, ut32 *off) {
212  *off = 0;
213  if (regset == NTO_REG_GENERAL) {
214  if (regno == -1)
215  return NUM_GPREGS * 4;
216 
217  *off = i386nto_reg_offset(regno);
218  if (*off == -1)
219  return 0;
220  return 4;
221  } else if (regset == NTO_REG_FLOAT) {
222  ut32 off_adjust, regsize, regset_size, regno_base;
223  /* The following are flags indicating number in our fxsave_area. */
224  int first_four = (regno >= I387_FCTRL_REGNUM && regno <= I387_FISEG_REGNUM);
225  int second_four = (regno > I387_FISEG_REGNUM && regno <= I387_FOP_REGNUM);
226  int st_reg = (regno >= I387_ST0_REGNUM && regno < I387_ST0_REGNUM + 8);
227  int xmm_reg = (regno >= I387_XMM0_REGNUM && regno < I387_MXCSR_REGNUM);
228 #if 0
229  if (nto_cpuinfo_valid && nto_cpuinfo_flags | X86_CPU_FXSR)
230  {
231 #endif
232  regset_size = 512;
233  /* fxsave_area structure. */
234  if (first_four) {
235  /* fpu_control_word, fpu_status_word, fpu_tag_word, fpu_operand
236 registers. */
237  regsize = 2; /* Two bytes each. */
238  off_adjust = 0;
239  regno_base = I387_FCTRL_REGNUM;
240  } else if (second_four) {
241  /* fpu_ip, fpu_cs, fpu_op, fpu_ds registers. */
242  regsize = 4;
243  off_adjust = 8;
244  regno_base = I387_FISEG_REGNUM + 1;
245  } else if (st_reg) {
246  /* ST registers. */
247  regsize = 16;
248  off_adjust = 32;
249  regno_base = I387_ST0_REGNUM;
250  } else if (xmm_reg) {
251  /* XMM registers. */
252  regsize = 16;
253  off_adjust = 160;
254  regno_base = I387_XMM0_REGNUM;
255  } else if (regno == I387_MXCSR_REGNUM) {
256  regsize = 4;
257  off_adjust = 24;
258  regno_base = I387_MXCSR_REGNUM;
259  } else {
260  /* Whole regset. */
261  off_adjust = 0;
262  regno_base = 0;
263  regsize = regset_size;
264  }
265 #if 0
266  }
267  else
268  {
269  regset_size = 108;
270  /* fsave_area structure. */
271  if (first_four || second_four)
272  {
273  /* fpu_control_word, ... , fpu_ds registers. */
274  regsize = 4;
275  off_adjust = 0;
276  regno_base = I387_FCTRL_REGNUM;
277  }
278  else if (st_reg)
279  {
280  /* One of ST registers. */
281  regsize = 10;
282  off_adjust = 7 * 4;
283  regno_base = I387_ST0_REGNUM;
284  }
285  else
286  {
287  /* Whole regset. */
288  off_adjust = 0;
289  regno_base = 0;
290  regsize = regset_size;
291  }
292  }
293 #endif
294 
295  *off = (regno != -1) ? off_adjust + (regno - regno_base) * regsize : 0;
296  return regsize;
297  }
298  return -1;
299 }
300 
302  ptid_t ptid;
303  ptid.pid = pid;
304  ptid.tid = tid;
305 
306  return ptid;
307 }
308 
309 int ptid_equal(ptid_t ptid1, ptid_t ptid2) {
310  return ptid1.pid == ptid2.pid && ptid1.tid == ptid2.tid;
311 }
size_t len
Definition: 6502dis.c:15
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
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 pid
Definition: sflib.h:64
int x
Definition: mipsasm.c:20
int off
Definition: pal.c:13
#define eprintf(x, y...)
Definition: rlcc.c:7
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
#define ESRCH
Definition: sftypes.h:113
#define ENOEXEC
Definition: sftypes.h:118
#define EPERM
Definition: sftypes.h:111
Definition: libqnxr.h:30
st32 pid
Definition: libqnxr.h:31
st64 tid
Definition: libqnxr.h:32
#define ULONGEST
Definition: utils.h:14
#define LONGEST
Definition: utils.h:13
#define I387_FISEG_REGNUM
Definition: utils.c:22
int ptid_equal(ptid_t ptid1, ptid_t ptid2)
Definition: utils.c:309
int i386nto_register_area(int regno, int regset, ut32 *off)
Definition: utils.c:211
#define NTO_ENOSYS
Definition: utils.c:85
#define I386_NUM_FREGS
Definition: utils.c:10
#define I387_XMM0_REGNUM
Definition: utils.c:27
int i386nto_reg_offset(int regnum)
Definition: utils.c:204
int i386nto_regset_id(int regno)
Definition: utils.c:191
#define NUM_GPREGS
Definition: utils.c:13
i386_regnum
Definition: utils.c:39
@ I386_EFLAGS_REGNUM
Definition: utils.c:49
@ I386_ESI_REGNUM
Definition: utils.c:46
@ I386_ST0_REGNUM
Definition: utils.c:56
@ I386_FS_REGNUM
Definition: utils.c:54
@ I386_ECX_REGNUM
Definition: utils.c:41
@ I386_GS_REGNUM
Definition: utils.c:55
@ I386_EIP_REGNUM
Definition: utils.c:48
@ I386_EBP_REGNUM
Definition: utils.c:45
@ I386_ES_REGNUM
Definition: utils.c:53
@ I386_CS_REGNUM
Definition: utils.c:50
@ I386_EAX_REGNUM
Definition: utils.c:40
@ I386_SS_REGNUM
Definition: utils.c:51
@ I386_EDX_REGNUM
Definition: utils.c:42
@ I386_ESP_REGNUM
Definition: utils.c:44
@ I386_EBX_REGNUM
Definition: utils.c:43
@ I386_DS_REGNUM
Definition: utils.c:52
@ I386_EDI_REGNUM
Definition: utils.c:47
#define NTO_ELIBEXEC
Definition: utils.c:83
int errnoconvert(int x)
Definition: utils.c:131
#define I387_FCTRL_REGNUM
Definition: utils.c:19
#define I387_MXCSR_REGNUM
Definition: utils.c:28
ptid_t ptid_build(st32 pid, st64 tid)
Definition: utils.c:301
#define NTO_ELIBACC
Definition: utils.c:79
#define I386_SSE_NUM_REGS
Definition: utils.c:15
#define I387_ST0_REGNUM
Definition: utils.c:18
#define NTO_EILSEQ
Definition: utils.c:84
LONGEST extract_signed_integer(const ut8 *addr, int len, int be)
Definition: utils.c:137
#define NTO_ELIBSCN
Definition: utils.c:81
#define NTO_ELIBBAD
Definition: utils.c:80
static int i386nto_gregset_reg_offset[]
Definition: utils.c:59
#define NTO_ENAMETOOLONG
Definition: utils.c:78
#define I387_FOP_REGNUM
Definition: utils.c:26
ULONGEST extract_unsigned_integer(const ut8 *addr, int len, int be)
Definition: utils.c:167
#define NTO_ELIBMAX
Definition: utils.c:82
#define I386_NUM_GREGS
Definition: utils.c:9
@ NTO_REG_FLOAT
Definition: utils.c:33
@ NTO_REG_SYSTEM
Definition: utils.c:34
@ NTO_REG_ALT
Definition: utils.c:35
@ NTO_REG_GENERAL
Definition: utils.c:32
@ NTO_REG_END
Definition: utils.c:36
static int addr
Definition: z80asm.c:58