File: utils.h

package info (click to toggle)
dynamips 0.2.14-1
  • links: PTS, VCS
  • area: non-free
  • in suites: bookworm, bullseye, buster, forky, jessie, jessie-kfreebsd, sid, stretch, trixie
  • size: 5,448 kB
  • ctags: 14,852
  • sloc: ansic: 104,416; perl: 20; sh: 4; makefile: 3
file content (429 lines) | stat: -rw-r--r-- 10,929 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
/*
 * Cisco router simulation platform.
 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
 */

#ifndef __UTILS_H__
#define __UTILS_H__

#include "dynamips_common.h"

#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>

/* Host CPU Types */
#define CPU_x86    0
#define CPU_amd64  1
#define CPU_nojit  2

/* Number of host registers available for JIT */
#if JIT_CPU == CPU_x86
#define JIT_HOST_NREG  8
#elif JIT_CPU == CPU_amd64
#define JIT_HOST_NREG  16
#else
#define JIT_HOST_NREG  0
#endif

/* Host to VM (big-endian) conversion functions */
#if ARCH_BYTE_ORDER == ARCH_BIG_ENDIAN
#define htovm16(x) (x)
#define htovm32(x) (x)
#define htovm64(x) (x)

#define vmtoh16(x) (x)
#define vmtoh32(x) (x)
#define vmtoh64(x) (x)
#else
#define htovm16(x) (htons(x))
#define htovm32(x) (htonl(x))
#define htovm64(x) (swap64(x))

#define vmtoh16(x) (ntohs(x))
#define vmtoh32(x) (ntohl(x))
#define vmtoh64(x) (swap64(x))
#endif

/* FD pool */
#define FD_POOL_MAX  16

typedef struct fd_pool fd_pool_t;
struct fd_pool {
   int fd[FD_POOL_MAX];
   struct fd_pool *next;
};

/* Forward declarations */
typedef struct cpu_gen cpu_gen_t;
typedef struct vm_instance vm_instance_t;
typedef struct vm_platform vm_platform_t;
typedef struct mips64_jit_tcb mips64_jit_tcb_t;
typedef struct ppc32_jit_tcb ppc32_jit_tcb_t;
typedef struct jit_op jit_op_t;
typedef struct cpu_tb cpu_tb_t;
typedef struct cpu_tc cpu_tc_t;

/* Translated block function pointer */
typedef void (*insn_tblock_fptr)(void);

/* Host executable page */
typedef struct insn_exec_page insn_exec_page_t;
struct insn_exec_page {
   u_char *ptr;
   insn_exec_page_t *next;
   int flags;
};

/* MIPS instruction */
typedef m_uint32_t mips_insn_t;

/* PowerPC instruction */
typedef m_uint32_t ppc_insn_t;

/* MMAP */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif

/* Macros for double linked list */
#define M_LIST_ADD(item,head,prefix) \
   do { \
      (item)->prefix##_next  = (head); \
      (item)->prefix##_pprev = &(head); \
      \
      if ((head) != NULL) \
         (head)->prefix##_pprev = &(item)->prefix##_next; \
      \
      (head) = (item); \
   }while(0)

#define M_LIST_REMOVE(item,prefix) \
   do { \
      if ((item)->prefix##_pprev != NULL) { \
         if ((item)->prefix##_next != NULL) \
            (item)->prefix##_next->prefix##_pprev = (item)->prefix##_pprev; \
         \
         *((item)->prefix##_pprev) = (item)->prefix##_next; \
         \
         (item)->prefix##_pprev = NULL; \
         (item)->prefix##_next  = NULL; \
      } \
   }while(0)


/* List item */
typedef struct m_list m_list_t;
struct m_list {
   void *data;
   m_list_t *next;
};

/* MTS mapping info */
typedef struct {
   m_uint64_t vaddr;
   m_uint64_t paddr;
   m_uint64_t len;
   m_uint32_t cached;
   m_uint32_t offset;
   m_uint32_t flags;
}mts_map_t;

/* Invalid VTLB entry */
#define MTS_INV_ENTRY_MASK  0x00000001

/* MTS entry flags */
#define MTS_FLAG_DEV   0x000000001   /* Virtual device used */
#define MTS_FLAG_COW   0x000000002   /* Copy-On-Write */
#define MTS_FLAG_EXEC  0x000000004   /* Exec page */
#define MTS_FLAG_RO    0x000000008   /* Read-only page */

#define MTS_FLAG_WRCATCH (MTS_FLAG_RO|MTS_FLAG_COW)  /* Catch writes */

/* Virtual TLB entry (32-bit MMU) */
typedef struct mts32_entry mts32_entry_t;
struct mts32_entry {
   m_uint32_t gvpa;   /* Guest Virtual Page Address */
   m_uint32_t gppa;   /* Guest Physical Page Address */
   m_iptr_t   hpa;    /* Host Page Address */
   m_uint32_t flags;  /* Flags */
}__attribute__ ((aligned(16)));

/* Virtual TLB entry (64-bit MMU) */
typedef struct mts64_entry mts64_entry_t;
struct mts64_entry {
   m_uint64_t gvpa;   /* Guest Virtual Page Address */
   m_uint64_t gppa;   /* Guest Physical Page Address */
   m_iptr_t   hpa;    /* Host Page Address */
   m_uint32_t flags;  /* Flags */
}__attribute__ ((aligned(16)));

/* Host register allocation */
#define HREG_FLAG_ALLOC_LOCKED  1
#define HREG_FLAG_ALLOC_FORCED  2

struct hreg_map {
   int hreg,vreg;
   int flags;
   struct hreg_map *prev,*next;
};

/* Global logfile */
extern FILE *log_file;

/* Check status of a bit */
static inline int check_bit(u_int old,u_int new,u_int bit)
{
   int mask = 1 << bit;

   if ((old & mask) && !(new & mask))
      return(1);   /* bit unset */
   
   if (!(old & mask) && (new & mask))
      return(2);   /* bit set */

   /* no change */
   return(0);
}

/* Sign-extension */
static forced_inline m_int64_t sign_extend(m_int64_t x,int len)
{
   len = 64 - len;
   return (x << len) >> len;
}

/* Sign-extension (32-bit) */
static forced_inline m_int32_t sign_extend_32(m_int32_t x,int len)
{
   len = 32 - len;
   return (x << len) >> len;
}

/* Extract bits from a 32-bit values */
static inline int bits(m_uint32_t val,int start,int end)
{
   return((val >> start) & ((1 << (end-start+1)) - 1));
}

/* Normalize a size */
static inline u_int normalize_size(u_int val,u_int nb,int shift) 
{
   return(((val+nb-1) & ~(nb-1)) >> shift);
}

/* Convert a 16-bit number between little and big endian */
static forced_inline m_uint16_t swap16(m_uint16_t value)
{
   return((value >> 8) | ((value & 0xFF) << 8));
}

/* Convert a 32-bit number between little and big endian */
static forced_inline m_uint32_t swap32(m_uint32_t value)
{
   m_uint32_t result;

   result = value >> 24;
   result |= ((value >> 16) & 0xff) << 8;
   result |= ((value >> 8)  & 0xff) << 16;
   result |= (value & 0xff) << 24;
   return(result);
}

/* Convert a 64-bit number between little and big endian */
static forced_inline m_uint64_t swap64(m_uint64_t value)
{
   m_uint64_t result;

   result = (m_uint64_t)swap32(value & 0xffffffff) << 32;
   result |= swap32(value >> 32);
   return(result);
}

/* Get current time in number of msec since epoch */
static inline m_tmcnt_t m_gettime(void)
{
   struct timeval tvp;

   gettimeofday(&tvp,NULL);
   return(((m_tmcnt_t)tvp.tv_sec * 1000) + ((m_tmcnt_t)tvp.tv_usec / 1000));
}

/* Get current time in number of usec since epoch */
static inline m_tmcnt_t m_gettime_usec(void)
{
   struct timeval tvp;

   gettimeofday(&tvp,NULL);
   return(((m_tmcnt_t)tvp.tv_sec * 1000000) + (m_tmcnt_t)tvp.tv_usec);
}

#ifdef __CYGWIN__
#define GET_TIMEZONE _timezone
#else
#define GET_TIMEZONE timezone
#endif

/* Get current time in number of ms (localtime) */
static inline m_tmcnt_t m_gettime_adj(void)
{
   struct timeval tvp;
   struct tm tmx;
   time_t gmt_adjust;
   time_t ct;

   gettimeofday(&tvp,NULL);
   ct = tvp.tv_sec;
   localtime_r(&ct,&tmx);

#if defined(__CYGWIN__) || defined(SUNOS)
   gmt_adjust = -(tmx.tm_isdst ? GET_TIMEZONE - 3600 : GET_TIMEZONE);
#else
   gmt_adjust = tmx.tm_gmtoff;
#endif

   tvp.tv_sec += gmt_adjust;
   return(((m_tmcnt_t)tvp.tv_sec * 1000) + ((m_tmcnt_t)tvp.tv_usec / 1000));
}

/* Get a byte-swapped 16-bit value on a non-aligned area */
static inline m_uint16_t m_ntoh16(m_uint8_t *ptr)
{
   m_uint16_t val = (ptr[0] << 8) | ptr[1];
   return(val);
}

/* Get a byte-swapped 32-bit value on a non-aligned area */
static inline m_uint32_t m_ntoh32(m_uint8_t *ptr)
{
   m_uint32_t val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
   return(val);
}

/* Set a byte-swapped 16-bit value on a non-aligned area */
static inline void m_hton16(m_uint8_t *ptr,m_uint16_t val)
{
   ptr[0] = val >> 8;
   ptr[1] = val;
}

/* Set a byte-swapped 32-bit value on a non-aligned area */
static inline void m_hton32(m_uint8_t *ptr,m_uint32_t val)
{
   ptr[0] = val >> 24;
   ptr[1] = val >> 16;
   ptr[2] = val >> 8;
   ptr[3] = val;
}

/* Add an element to a list */
m_list_t *m_list_add(m_list_t **head,void *data);

/* Dynamic sprintf */
char *dyn_sprintf(const char *fmt,...);

/* Split a string */
int m_strsplit(char *str,char delim,char **array,int max_count);

/* Tokenize a string */
int m_strtok(char *str,char delim,char **array,int max_count);

/* Quote a string */
char *m_strquote(char *buffer,size_t buf_len,char *str);

/* Decode from hex. */
int hex_decode(unsigned char *out,const unsigned char *in,int maxlen);

/* Ugly function that dumps a structure in hexa and ascii. */
void mem_dump(FILE *f_output,u_char *pkt,u_int len);

/* Logging function */
void m_flog(FILE *fd,char *module,char *fmt,va_list ap);

/* Logging function */
void m_log(char *module,char *fmt,...);

/* Write an array of string to a logfile */
void m_flog_str_array(FILE *fd,int count,char *str[]);

/* Returns a line from specified file (remove trailing '\n') */
char *m_fgets(char *buffer,int size,FILE *fd);

/* Read a file and returns it in a buffer */
int m_read_file(const char *filename,u_char **buffer,size_t *length);

/* Allocate aligned memory */
void *m_memalign(size_t boundary,size_t size);

/* Block specified signal for calling thread */
int m_signal_block(int sig);

/* Unblock specified signal for calling thread */
int m_signal_unblock(int sig);

/* Set non-blocking mode on a file descriptor */
int m_fd_set_non_block(int fd);

/* Sync a memory zone */
int memzone_sync(void *addr, size_t len);

/* Sync all mappings of a memory zone */
int memzone_sync_all(void *addr, size_t len);

/* Unmap a memory zone */
int memzone_unmap(void *addr, size_t len);

/* Map a memory zone as an executable area */
u_char *memzone_map_exec_area(size_t len);

/* Map a memory zone from a file */
u_char *memzone_map_file(int fd,size_t len);

/* Map a memory zone from a file, with copy-on-write (COW) */
u_char *memzone_map_cow_file(int fd,size_t len);

/* Create a file to serve as a memory zone */
int memzone_create_file(char *filename,size_t len,u_char **ptr);

/* Open a file to serve as a COW memory zone */
int memzone_open_cow_file(char *filename,size_t len,u_char **ptr);

/* Open a file and map it in memory */
int memzone_open_file(char *filename,u_char **ptr,off_t *fsize);
int memzone_open_file_ro(char *filename,u_char **ptr,off_t *fsize);

/* Compute NVRAM checksum */
m_uint16_t nvram_cksum(m_uint16_t *ptr,size_t count);

/* Byte-swap a memory block */
void mem_bswap32(void *ptr,size_t len);

/* Reverse a byte */
m_uint8_t m_reverse_u8(m_uint8_t val);

/* Generate a pseudo random block of data */
void m_randomize_block(m_uint8_t *buf,size_t len);

/* Free an FD pool */
void fd_pool_free(fd_pool_t *pool);

/* Initialize an empty pool */
void fd_pool_init(fd_pool_t *pool);

/* Get a free slot for a FD in a pool */
int fd_pool_get_free_slot(fd_pool_t *pool,int **slot);

/* Fill a FD set and get the maximum FD in order to use with select */
int fd_pool_set_fds(fd_pool_t *pool,fd_set *fds);

/* Send a buffer to all FDs of a pool */
int fd_pool_send(fd_pool_t *pool,void *buffer,size_t len,int flags);

/* Call a function for each FD having incoming data */
int fd_pool_check_input(fd_pool_t *pool,fd_set *fds,
                        void (*cbk)(int *fd_slot,void *opt),void *opt);

/* Equivalent to fprintf, but for a posix fd */
ssize_t fd_printf(int fd,int flags,char *fmt,...);

#endif