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);