1 /* Unicorn Emulator Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
3 
4 module unicorn.unicorn;
5 extern(C):
6 
7 struct uc_engine;
8 
9 struct uc_hook { private size_t typedef; }
10 
11 enum UC_API_MAJOR = 1;
12 enum UC_API_MINOR = 0;
13 
14 /// Unicorn package version
15 enum UC_VERSION_MAJOR = UC_API_MAJOR;
16 enum UC_VERSION_MINOR = UC_API_MINOR;
17 enum UC_VERSION_EXTRA = 1;
18 
19 
20 /*
21   Macro to create combined version which can be compared to
22   result of uc_version() API.
23 */
24 int UC_MAKE_VERSION(int major, int minor) { return (major << 8) + minor; }
25 
26 /// Scales to calculate timeout on microsecond unit
27 /// 1 second = 1000,000 microseconds
28 enum UC_SECOND_SCALE = 1000000;
29 /// 1 milisecond = 1000 nanoseconds
30 enum UC_MILISECOND_SCALE = 1000;
31 
32 /// Architecture type
33 enum uc_arch {
34     ARM = 1,    /// ARM architecture (including Thumb, Thumb-2)
35     ARM64,      /// ARM-64, also called AArch64
36     MIPS,       /// Mips architecture
37     X86,        /// X86 architecture (including x86 & x86-64)
38     PPC,        /// PowerPC architecture (currently unsupported)
39     SPARC,      /// Sparc architecture
40     M68K,       /// M68K architecture
41     MAX,
42 }
43 
44 /// Mode type
45 enum uc_mode {
46     LITTLE_ENDIAN = 0,    /// little-endian mode (default mode)
47     BIG_ENDIAN = 1 << 30, /// big-endian mode
48     /// arm / arm64
49     ARM = 0,              /// ARM mode
50     THUMB = 1 << 4,       /// THUMB mode (including Thumb-2)
51     MCLASS = 1 << 5,      /// ARM's Cortex-M series (currently unsupported)
52     V8 = 1 << 6,          /// ARMv8 A32 encodings for ARM (currently unsupported)
53     /// mips
54     MICRO = 1 << 4,       /// MicroMips mode (currently unsupported)
55     MIPS3 = 1 << 5,       /// Mips III ISA (currently unsupported)
56     MIPS32R6 = 1 << 6,    /// Mips32r6 ISA (currently unsupported)
57     MIPS32 = 1 << 2,      /// Mips32 ISA
58     MIPS64 = 1 << 3,      /// Mips64 ISA
59     /// x86 / x64
60     X86_16 = 1 << 1,      /// 16-bit mode
61     X86_32 = 1 << 2,      /// 32-bit mode
62     X86_64 = 1 << 3,      /// 64-bit mode
63     /// ppc 
64     PPC32 = 1 << 2,       /// 32-bit mode (currently unsupported)
65     PPC64 = 1 << 3,       /// 64-bit mode (currently unsupported)
66     QPX = 1 << 4,         /// Quad Processing eXtensions mode (currently unsupported)
67     /// sparc
68     SPARC32 = 1 << 2,     /// 32-bit mode
69     SPARC64 = 1 << 3,     /// 64-bit mode
70     V9 = 1 << 4,          /// SparcV9 mode (currently unsupported)
71     /// m68k
72 }
73 
74 /// All type of errors encountered by Unicorn API.
75 /// These are values returned by uc_errno()
76 enum uc_err {
77     OK = 0,   /// No error: everything was fine
78     NOMEM,      /// Out-Of-Memory error: uc_open(), uc_emulate()
79     ARCH,     /// Unsupported architecture: uc_open()
80     HANDLE,   /// Invalid handle
81     MODE,     /// Invalid/unsupported mode: uc_open()
82     VERSION,  /// Unsupported version (bindings)
83     READ_UNMAPPED, /// Quit emulation due to READ on unmapped memory: uc_emu_start()
84     WRITE_UNMAPPED, /// Quit emulation due to WRITE on unmapped memory: uc_emu_start()
85     FETCH_UNMAPPED, /// Quit emulation due to FETCH on unmapped memory: uc_emu_start()
86     HOOK,    /// Invalid hook type: uc_hook_add()
87     INSN_INVALID, /// Quit emulation due to invalid instruction: uc_emu_start()
88     MAP, /// Invalid memory mapping: uc_mem_map()
89     WRITE_PROT, /// Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start()
90     READ_PROT, /// Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start()
91     FETCH_PROT, /// Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start()
92     ARG,     /// Inavalid argument provided to uc_xxx function (See specific function API)
93     READ_UNALIGNED,  /// Unaligned read
94     WRITE_UNALIGNED,  /// Unaligned write
95     FETCH_UNALIGNED,  /// Unaligned fetch
96     HOOK_EXIST,  /// hook for this event already existed
97     RESOURCE,    /// Insufficient resource: uc_emu_start()
98     EXCEPTION /// Unhandled CPU exception
99 }
100 
101 
102 /*
103   Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK)
104 
105   @address: address where the code is being executed
106   @size: size of machine instruction(s) being executed, or 0 when size is unknown
107   @user_data: user data passed to tracing APIs.
108 */
109 alias uc_cb_hookcode_t = void function(uc_engine *uc, ulong address, uint size, void *user_data);
110 
111 /*
112   Callback function for tracing interrupts (for uc_hook_intr())
113 
114   @intno: interrupt number
115   @user_data: user data passed to tracing APIs.
116 */
117 alias uc_cb_hookintr_t = void function(uc_engine *uc, uint intno, void *user_data);
118 
119 /*
120   Callback function for tracing IN instruction of X86
121 
122   @port: port number
123   @size: data size (1/2/4) to be read from this port
124   @user_data: user data passed to tracing APIs.
125 */
126 alias uc_cb_insn_in_t = uint function(uc_engine *uc, uint port, int size, void *user_data);
127 
128 /*
129   Callback function for OUT instruction of X86
130 
131   @port: port number
132   @size: data size (1/2/4) to be written to this port
133   @value: data value to be written to this port
134 */
135 alias uc_cb_insn_out_t = void function(uc_engine *uc, uint port, int size, uint value, void *user_data);
136 
137 /// All type of memory accesses for UC_HOOK_MEM_*
138 enum uc_mem_type {
139     READ = 16,   /// Memory is read from
140     WRITE,       /// Memory is written to
141     FETCH,       /// Memory is fetched
142     READ_UNMAPPED,    /// Unmapped memory is read from
143     WRITE_UNMAPPED,   /// Unmapped memory is written to
144     FETCH_UNMAPPED,   /// Unmapped memory is fetched
145     WRITE_PROT,  /// Write to write protected, but mapped, memory
146     READ_PROT,   /// Read from read protected, but mapped, memory
147     FETCH_PROT,  /// Fetch from non-executable, but mapped, memory
148     READ_AFTER,   /// Memory is read from (successful access)
149 }
150 
151 /// All type of hooks for uc_hook_add() API.
152 enum uc_hook_type {
153     //// Hook all interrupt/syscall events
154     INTR = 1 << 0,
155     //// Hook a particular instruction - only a very small subset of instructions supported here
156     INSN = 1 << 1,
157     //// Hook a range of code
158     CODE = 1 << 2,
159     //// Hook basic blocks
160     BLOCK = 1 << 3,
161     //// Hook for memory read on unmapped memory
162     MEM_READ_UNMAPPED = 1 << 4,
163     //// Hook for invalid memory write events
164     MEM_WRITE_UNMAPPED = 1 << 5,
165     //// Hook for invalid memory fetch for execution events
166     MEM_FETCH_UNMAPPED = 1 << 6,
167     //// Hook for memory read on read-protected memory
168     MEM_READ_PROT = 1 << 7,
169     //// Hook for memory write on write-protected memory
170     MEM_WRITE_PROT = 1 << 8,
171     //// Hook for memory fetch on non-executable memory
172     MEM_FETCH_PROT = 1 << 9,
173     //// Hook memory read events.
174     MEM_READ = 1 << 10,
175     //// Hook memory write events.
176     MEM_WRITE = 1 << 11,
177     //// Hook memory fetch for execution events
178     MEM_FETCH = 1 << 12,
179     //// Hook memory read events, but only successful access.
180     //// The callback will be triggered after successful read.
181     MEM_READ_AFTER = 1 << 13,
182 
183     //// Hook type for all events of unmapped memory access
184     MEM_UNMAPPED = MEM_READ_UNMAPPED + MEM_WRITE_UNMAPPED + MEM_FETCH_UNMAPPED,
185     //// Hook type for all events of illegal protected memory access
186     MEM_PROT = MEM_READ_PROT + MEM_WRITE_PROT + MEM_FETCH_PROT,
187     //// Hook type for all events of illegal read memory access
188     MEM_READ_INVALID = MEM_READ_PROT + MEM_READ_UNMAPPED,
189     //// Hook type for all events of illegal write memory access
190     MEM_WRITE_INVALID = MEM_WRITE_PROT + MEM_WRITE_UNMAPPED,
191     //// Hook type for all events of illegal fetch memory access
192     MEM_FETCH_INVALID = MEM_FETCH_PROT + MEM_FETCH_UNMAPPED,
193     //// Hook type for all events of illegal memory access
194     MEM_INVALID = MEM_UNMAPPED + MEM_PROT,
195     //// Hook type for all events of valid memory access
196     MEM_VALID = MEM_READ + MEM_WRITE + MEM_FETCH,
197 }
198 
199 /*
200   Callback function for hooking memory (UC_MEM_READ, UC_MEM_WRITE & UC_MEM_FETCH)
201 
202   @type: this memory is being READ, or WRITE
203   @address: address where the code is being executed
204   @size: size of data being read or written
205   @value: value of data being written to memory, or irrelevant if type = READ.
206   @user_data: user data passed to tracing APIs
207 */
208 alias uc_cb_hookmem_t = void function(uc_engine *uc, uc_mem_type type,
209         ulong address, int size, long value, void *user_data);
210 
211 /*
212   Callback function for handling invalid memory access events (UC_MEM_*_UNMAPPED and
213     UC_MEM_*PROT events)
214 
215   @type: this memory is being READ, or WRITE
216   @address: address where the code is being executed
217   @size: size of data being read or written
218   @value: value of data being written to memory, or irrelevant if type = READ.
219   @user_data: user data passed to tracing APIs
220 
221   @return: return true to continue, or false to stop program (due to invalid memory).
222 */
223 alias uc_cb_eventmem_t = bool function(uc_engine *uc, uc_mem_type type,
224         ulong address, int size, long value, void *user_data);
225 
226 /*
227   Memory region mapped by uc_mem_map() and uc_mem_map_ptr()
228   Retrieve the list of memory regions with uc_mem_regions()
229 */
230 struct uc_mem_region {
231     ulong begin; /// begin address of the region (inclusive)
232     ulong end;   /// end address of the region (inclusive)
233     uint perms; /// memory permissions of the region
234 }
235 
236 /// All type of queries for uc_query() API.
237 enum uc_query_type {
238     /// Dynamically query current hardware mode.
239     MODE = 1,
240     PAGE_SIZE,
241 }
242 
243 /// Opaque storage for CPU context, used with uc_context_*()
244 struct uc_context;
245 
246 /*
247  Return combined API version & major and minor version numbers.
248 
249  @major: major number of API version
250  @minor: minor number of API version
251 
252  @return hexical number as (major << 8 | minor), which encodes both
253      major & minor versions.
254      NOTE: This returned value can be compared with version number made
255      with macro UC_MAKE_VERSION
256 
257  For example, second API version would return 1 in @major, and 1 in @minor
258  The return value would be 0x0101
259 
260  NOTE: if you only care about returned value, but not major and minor values,
261  set both @major & @minor arguments to NULL.
262 */
263 uint uc_version(uint *major, uint *minor);
264 
265 
266 /*
267  Determine if the given architecture is supported by this library.
268 
269  @arch: architecture type (UC_ARCH_*)
270 
271  @return True if this library supports the given arch.
272 */
273 bool uc_arch_supported(uc_arch arch);
274 
275 
276 /*
277  Create new instance of unicorn engine.
278 
279  @arch: architecture type (UC_ARCH_*)
280  @mode: hardware mode. This is combined of UC_MODE_*
281  @uc: pointer to uc_engine, which will be updated at return time
282 
283  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
284    for detailed error).
285 */
286 uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc);
287 
288 /*
289  Close UC instance: MUST do to release the handle when it is not used anymore.
290  NOTE: this must be called only when there is no longer usage of Unicorn.
291  The reason is the this API releases some cached memory, thus access to any
292  Unicorn API after uc_close() might crash your application.
293  After this, @uc is invalid, and nolonger usable.
294 
295  @uc: pointer to a handle returned by uc_open()
296 
297  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
298    for detailed error).
299 */
300 uc_err uc_close(uc_engine *uc);
301 
302 /*
303  Query internal status of engine.
304 
305  @uc: handle returned by uc_open()
306  @type: query type. See uc_query_type
307 
308  @result: save the internal status queried
309 
310  @return: error code of uc_err enum type (UC_ERR_*, see above)
311 */
312 uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result);
313 
314 /*
315  Report the last error number when some API function fail.
316  Like glibc's errno, uc_errno might not retain its old value once accessed.
317 
318  @uc: handle returned by uc_open()
319 
320  @return: error code of uc_err enum type (UC_ERR_*, see above)
321 */
322 uc_err uc_errno(uc_engine *uc);
323 
324 /*
325  Return a string describing given error code.
326 
327  @code: error code (see UC_ERR_* above)
328 
329  @return: returns a pointer to a string that describes the error code
330    passed in the argument @code
331  */
332 const(char)* uc_strerror(uc_err code);
333 
334 /*
335  Write to register.
336 
337  @uc: handle returned by uc_open()
338  @regid:  register ID that is to be modified.
339  @value:  pointer to the value that will set to register @regid
340 
341  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
342    for detailed error).
343 */
344 uc_err uc_reg_write(uc_engine *uc, int regid, const void *value);
345 
346 /*
347  Read register value.
348 
349  @uc: handle returned by uc_open()
350  @regid:  register ID that is to be retrieved.
351  @value:  pointer to a variable storing the register value.
352 
353  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
354    for detailed error).
355 */
356 uc_err uc_reg_read(uc_engine *uc, int regid, void *value);
357 
358 /*
359  Write multiple register values.
360 
361  @uc: handle returned by uc_open()
362  @rges:  array of register IDs to store
363  @value: pointer to array of register values
364  @count: length of both *regs and *vals
365 
366  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
367    for detailed error).
368 */
369 uc_err uc_reg_write_batch(uc_engine *uc, int *regs, const void **vals, int count);
370 
371 /*
372  Read multiple register values.
373 
374  @uc: handle returned by uc_open()
375  @rges:  array of register IDs to retrieve
376  @value: pointer to array of values to hold registers
377  @count: length of both *regs and *vals
378 
379  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
380    for detailed error).
381 */
382 uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count);
383 
384 /*
385  Write to a range of bytes in memory.
386 
387  @uc: handle returned by uc_open()
388  @address: starting memory address of bytes to set.
389  @bytes:   pointer to a variable containing data to be written to memory.
390  @size:   size of memory to write to.
391 
392  NOTE: @bytes must be big enough to contain @size bytes.
393 
394  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
395    for detailed error).
396 */
397 uc_err uc_mem_write(uc_engine *uc, ulong address, const void *bytes, size_t size);
398 
399 /*
400  Read a range of bytes in memory.
401 
402  @uc: handle returned by uc_open()
403  @address: starting memory address of bytes to get.
404  @bytes:   pointer to a variable containing data copied from memory.
405  @size:   size of memory to read.
406 
407  NOTE: @bytes must be big enough to contain @size bytes.
408 
409  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
410    for detailed error).
411 */
412 uc_err uc_mem_read(uc_engine *uc, ulong address, void *bytes, size_t size);
413 
414 /*
415  Emulate machine code in a specific duration of time.
416 
417  @uc: handle returned by uc_open()
418  @begin: address where emulation starts
419  @until: address where emulation stops (i.e when this address is hit)
420  @timeout: duration to emulate the code (in microseconds). When this value is 0,
421         we will emulate the code in infinite time, until the code is finished.
422  @count: the number of instructions to be emulated. When this value is 0,
423         we will emulate all the code available, until the code is finished.
424 
425  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
426    for detailed error).
427 */
428 uc_err uc_emu_start(uc_engine *uc, ulong begin, ulong until, ulong timeout, size_t count);
429 
430 /*
431  Stop emulation (which was started by uc_emu_start() API.
432  This is typically called from callback functions registered via tracing APIs.
433 
434  @uc: handle returned by uc_open()
435 
436  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
437    for detailed error).
438 */
439 uc_err uc_emu_stop(uc_engine *uc);
440 
441 /*
442  Register callback for a hook event.
443  The callback will be run when the hook event is hit.
444 
445  @uc: handle returned by uc_open()
446  @hh: hook handle returned from this registration. To be used in uc_hook_del() API
447  @type: hook type
448  @callback: callback to be run when instruction is hit
449  @user_data: user-defined data. This will be passed to callback function in its
450       last argument @user_data
451  @begin: start address of the area where the callback is effect (inclusive)
452  @end: end address of the area where the callback is effect (inclusive)
453    NOTE 1: the callback is called only if related address is in range [@begin, @end]
454    NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered
455  @...: variable arguments (depending on @type)
456    NOTE: if @type = UC_HOOK_INSN, this is the instruction ID (ex: UC_X86_INS_OUT)
457 
458  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
459    for detailed error).
460 */
461 uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
462         void *user_data, ulong begin, ulong end, ...);
463 
464 /*
465  Unregister (remove) a hook callback.
466  This API removes the hook callback registered by uc_hook_add().
467  NOTE: this should be called only when you no longer want to trace.
468  After this, @hh is invalid, and nolonger usable.
469 
470  @uc: handle returned by uc_open()
471  @hh: handle returned by uc_hook_add()
472 
473  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
474    for detailed error).
475 */
476 uc_err uc_hook_del(uc_engine *uc, uc_hook hh);
477 
478 enum uc_prot {
479    NONE = 0,
480    READ = 1,
481    WRITE = 2,
482    EXEC = 4,
483    ALL = 7,
484 }
485 
486 /*
487  Map memory in for emulation.
488  This API adds a memory region that can be used by emulation.
489 
490  @uc: handle returned by uc_open()
491  @address: starting address of the new memory region to be mapped in.
492     This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
493  @size: size of the new memory region to be mapped in.
494     This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
495  @perms: Permissions for the newly mapped region.
496     This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
497     or this will return with UC_ERR_ARG error.
498 
499  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
500    for detailed error).
501 */
502 uc_err uc_mem_map(uc_engine *uc, ulong address, size_t size, uint perms);
503 
504 /*
505  Map existing host memory in for emulation.
506  This API adds a memory region that can be used by emulation.
507 
508  @uc: handle returned by uc_open()
509  @address: starting address of the new memory region to be mapped in.
510     This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
511  @size: size of the new memory region to be mapped in.
512     This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
513  @perms: Permissions for the newly mapped region.
514     This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
515     or this will return with UC_ERR_ARG error.
516  @ptr: pointer to host memory backing the newly mapped memory. This host memory is
517     expected to be an equal or larger size than provided, and be mapped with at
518     least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined.
519 
520  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
521    for detailed error).
522 */
523 uc_err uc_mem_map_ptr(uc_engine *uc, ulong address, size_t size, uint perms, void *ptr);
524 
525 /*
526  Unmap a region of emulation memory.
527  This API deletes a memory mapping from the emulation memory space.
528 
529  @uc: handle returned by uc_open()
530  @address: starting address of the memory region to be unmapped.
531     This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
532  @size: size of the memory region to be modified.
533     This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
534 
535  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
536    for detailed error).
537 */
538 uc_err uc_mem_unmap(uc_engine *uc, ulong address, size_t size);
539 
540 /*
541  Set memory permissions for emulation memory.
542  This API changes permissions on an existing memory region.
543 
544  @uc: handle returned by uc_open()
545  @address: starting address of the memory region to be modified.
546     This address must be aligned to 4KB, or this will return with UC_ERR_ARG error.
547  @size: size of the memory region to be modified.
548     This size must be multiple of 4KB, or this will return with UC_ERR_ARG error.
549  @perms: New permissions for the mapped region.
550     This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
551     or this will return with UC_ERR_ARG error.
552 
553  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
554    for detailed error).
555 */
556 uc_err uc_mem_protect(uc_engine *uc, ulong address, size_t size, uint perms);
557 
558 /*
559  Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr()
560  This API allocates memory for @regions, and user must free this memory later
561  by free() to avoid leaking memory.
562  NOTE: memory regions may be splitted by uc_mem_unmap()
563 
564  @uc: handle returned by uc_open()
565  @regions: pointer to an array of uc_mem_region struct. This is allocated by
566    Unicorn, and must be freed by user later with uc_free()
567  @count: pointer to number of struct uc_mem_region contained in @regions
568 
569  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
570    for detailed error).
571 */
572 uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint *count);
573 
574 /*
575  Allocate a region that can be used with uc_context_{save,restore} to perform
576  quick save/rollback of the CPU context, which includes registers and some
577  internal metadata. Contexts may not be shared across engine instances with
578  differing arches or modes.
579 
580  @uc: handle returned by uc_open()
581  @context: pointer to a uc_engine*. This will be updated with the pointer to
582    the new context on successful return of this function.
583    Later, this allocated memory must be freed with uc_free().
584 
585  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
586    for detailed error).
587 */
588 uc_err uc_context_alloc(uc_engine *uc, uc_context **context);
589 
590 /*
591  Free the memory allocated by uc_context_alloc & uc_mem_regions.
592 
593  @mem: memory allocated by uc_context_alloc (returned in *context), or
594        by uc_mem_regions (returned in *regions)
595 
596  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
597    for detailed error).
598 */
599 uc_err uc_free(void *mem);
600 
601 /*
602  Save a copy of the internal CPU context.
603  This API should be used to efficiently make or update a saved copy of the
604  internal CPU state.
605 
606  @uc: handle returned by uc_open()
607  @context: handle returned by uc_context_alloc()
608 
609  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
610    for detailed error).
611 */
612 uc_err uc_context_save(uc_engine *uc, uc_context *context);
613 
614 /*
615  Restore the current CPU context from a saved copy.
616  This API should be used to roll the CPU context back to a previous
617  state saved by uc_context_save().
618 
619  @uc: handle returned by uc_open()
620  @buffer: handle returned by uc_context_alloc that has been used with uc_context_save
621 
622  @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
623    for detailed error).
624 */
625 uc_err uc_context_restore(uc_engine *uc, uc_context *context);