### QEMU Coding Convention Example (C) Source: https://github.com/unicorn-engine/unicorn/wiki/Coding-Convention An example demonstrating the C coding style recommended for code under the 'qemu' directory in the Unicorn Engine. This includes standard formatting for conditional statements. ```c void a_function(void) { if (a == 5) { printf("a was 5.\n"); } else if (a == 6) { printf("a was 6.\n"); } else { printf("a was something else entirely.\n"); } } ``` -------------------------------- ### Compile and Run Unicorn Engine C Example Source: https://github.com/unicorn-engine/unicorn/wiki/Quick-Start This bash script demonstrates the compilation and execution of the Unicorn Engine C example. It first compiles the code using 'make' and then runs the resulting executable. The output shows the initial and final register states after emulation. ```bash $ make cc test1.c -L/usr/local/Cellar/glib/2.44.1/lib -L/usr/local/opt/gettext/lib -lglib-2.0 -lintl -lpthread -lm -lunicorn -o test1 $ ./test1 Emulate i386 code Emulation done. Below is the CPU context >>> ECX = 0x1235 >>> EDX = 0x788f ``` -------------------------------- ### Install Unicorn Engine (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt This snippet handles the installation of the Unicorn engine, including the library files, headers, and pkg-config files. It uses conditional logic based on build options like `BUILD_SHARED_LIBS` and `UNICORN_LEGACY_STATIC_ARCHIVE`. ```cmake if(UNICORN_INSTALL) include("GNUInstallDirs") file(GLOB UNICORN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/unicorn/*.h) if (BUILD_SHARED_LIBS) install(TARGETS unicorn RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() if (UNICORN_LEGACY_STATIC_ARCHIVE) install(FILES $ DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES $/$ DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() install(FILES ${UNICORN_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/unicorn) if (ATOMIC_LINKAGE_FIX) set(ATOMIC_LINK_PKG_CONFIG " -latomic") else() set(ATOMIC_LINK_PKG_CONFIG "") endif() file(WRITE ${CMAKE_BINARY_DIR}/unicorn.pc "Name: unicorn\n\ Description: Unicorn emulator engine\n\ Version: ${UNICORN_VERSION_MAJOR}.${UNICORN_VERSION_MINOR}.${UNICORN_VERSION_PATCH}\n\ libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\ includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\ Libs: -L\$\ alemão{libdir} -lunicorn\n\ Libs.private: -lpthread -lm${ATOMIC_LINK_PKG_CONFIG}\n\ Cflags: -I\$\ alemão{includedir}\n" ) install(FILES ${CMAKE_BINARY_DIR}/unicorn.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) endif() ``` -------------------------------- ### Install Unicorn Python Bindings Source: https://github.com/unicorn-engine/unicorn/blob/master/bindings/python/README.md Installs the Unicorn Python bindings using pip. Supports installing prebuilt wheels or building from source with options for debug builds and multi-threaded compilation. ```bash python3 -m pip install unicorn ``` ```bash DEBUG=1 THREADS=4 python3 -m pip install --user -e . # Workaround for Pylance DEBUG=1 THREADS=4 python3 -m pip install --user -e . --config-settings editable_mode=strict ``` ```bash THREADS=4 python3 -m pip install --user . ``` -------------------------------- ### Start Code Emulation using C Source: https://context7.com/unicorn-engine/unicorn/llms.txt Illustrates how to begin emulating machine code from a specified address using the Unicorn Engine C API. It supports options for timeouts and instruction count limits. Requires the unicorn library. Inputs include machine code, start address, and optional limits; output is the state of registers after emulation. ```c #include int main() { uc_engine *uc; uc_err err; unsigned char code[] = "\x41\x4a"; // INC ecx; DEC edx uint64_t address = 0x1000000; err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err != UC_ERR_OK) { return 1; } err = uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL); err = uc_mem_write(uc, address, code, sizeof(code) - 1); int r_ecx = 0x1234; int r_edx = 0x7890; uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // Emulate all code, no timeout, no instruction limit err = uc_emu_start(uc, address, address + sizeof(code) - 1, 0, 0); if (err != UC_ERR_OK) { printf("Failed on uc_emu_start(): %s\n", uc_strerror(err)); uc_close(uc); return 1; } // Emulate with 2 second timeout err = uc_emu_start(uc, address, address + sizeof(code) - 1, 2 * UC_SECOND_SCALE, 0); // Emulate exactly 5 instructions err = uc_emu_start(uc, address, address + sizeof(code) - 1, 0, 5); // Read results uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); printf("After emulation: ECX = 0x%x, EDX = 0x%x\n", r_ecx, r_edx); uc_close(uc); return 0; } ``` -------------------------------- ### Rust: Unicorn Emulator ARM Emulation Example Source: https://github.com/unicorn-engine/unicorn/blob/master/bindings/rust/sys/README.md Demonstrates basic ARM emulation using unicorn-engine-sys. It covers opening an engine, mapping memory, writing machine code, setting and reading registers, and starting emulation. Requires the unicorn-engine-sys dependency. ```rust use unicorn_engine_sys::{ Arch, Mode, uc_close, uc_emu_start, uc_engine, uc_mem_map, uc_mem_write, uc_open, uc_reg_read, uc_reg_write, }; fn main() { let mut uc_engine: *mut uc_engine = std::ptr::null_mut(); let err = unsafe {{ uc_open(Arch::ARM, Mode::ARM, &raw mut uc_engine) }}; assert_eq!(err, unicorn_error::OK, "Failed to open Unicorn engine"); let code: [u8; 4] = [0x17, 0x00, 0x40, 0xe2]; // sub r0, #23 let err = unsafe {{ uc_mem_map(uc_engine, CODE_START, 0x1000, Prot::ALL.0) }}; assert_eq!(err, unicorn_error::OK, "Failed to map memory"); let err = unsafe {{ uc_mem_write(uc_engine, CODE_START, code.as_ptr().cast(), code.len()) }}; assert_eq!(err, unicorn_error::OK, "Failed to write memory"); let mut r0: u64 = 123; let err = unsafe {{ uc_reg_write(uc_engine, RegisterARM::R0 as i32, (&raw mut r0).cast()) }}; assert_eq!(err, unicorn_error::OK, "Failed to write R0"); let mut r5: u64 = 1337; let err = unsafe {{ uc_reg_write(uc_engine, RegisterARM::R5 as i32, (&raw mut r5).cast()) }}; assert_eq!(err, unicorn_error::OK, "Failed to write R5"); let err = unsafe {{ uc_emu_start(uc_engine, CODE_START, CODE_START + code.len() as u64, 0, 0) }}; assert_eq!(err, unicorn_error::OK, "Failed to start emulation"); r0 = 0; let err = unsafe {{ uc_reg_read(uc_engine, RegisterARM::R0 as i32, (&raw mut r0).cast()) }}; assert_eq!(err, unicorn_error::OK, "Failed to read R0"); r5 = 0; let err = unsafe {{ uc_reg_read(uc_engine, RegisterARM::R5 as i32, (&raw mut r5).cast()) }}; assert_eq!(err, unicorn_error::OK, "Failed to read R5"); assert_eq!(r0, 100); assert_eq!(r5, 1337); // Clean up unsafe {{ uc_close(uc_engine) }}; } ``` -------------------------------- ### Define Sample Library Dependencies Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Defines the libraries required for samples based on platform and build configurations. This ensures that samples are linked correctly. ```cmake if(MSVC) set(SAMPLES_LIB unicorn ) elseif(NOT ANDROID_ABI) set(SAMPLES_LIB unicorn pthread ) else() set(SAMPLES_LIB unicorn ) endif() if(ATOMIC_LINKAGE_FIX) set(SAMPLES_LIB ${SAMPLES_LIB} atomic ) endif() ``` -------------------------------- ### C: Variadic Macro Definition Source: https://github.com/unicorn-engine/unicorn/blob/master/qemu/CODING_STYLE.rst Shows the C99-like syntax for defining variadic macros, which can accept a variable number of arguments. This example defines a DPRINTF macro for debugging output. ```c #define DPRINTF(fmt, ...) \ do { printf("IRQ: " fmt, ## __VA_ARGS__); } while (0) ``` -------------------------------- ### Build and Test Samples (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt This snippet enables testing and builds sample executables. It iterates through sample files, creates executables, links them, and adds them as tests. It also includes logic for Android deployment. ```cmake if(UNICORN_BUILD_TESTS) enable_testing() foreach(SAMPLE_FILE ${UNICORN_SAMPLE_FILE}) add_executable(${SAMPLE_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/samples/${SAMPLE_FILE}.c ) target_link_libraries(${SAMPLE_FILE} PRIVATE ${SAMPLES_LIB} ) endforeach() foreach(TEST_FILE ${UNICORN_TEST_FILE}) add_executable(${TEST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/${TEST_FILE}.c ) target_compile_options(${TEST_FILE} PRIVATE ${UNICORN_COMPILE_OPTIONS} ) target_link_libraries(${TEST_FILE} PRIVATE ${SAMPLES_LIB} ) add_test(${TEST_FILE} ${TEST_FILE}) if(ANDROID_ABI) file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb push ${TEST_FILE} /data/local/tmp/build/\n") file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell \"chmod +x /data/local/tmp/build/${TEST_FILE}\"\n") file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb shell 'LD_LIBRARY_PATH=/data/local/tmp/build:$LD_LIBRARY_PATH /data/local/tmp/build/${TEST_FILE}' || exit -1\n") endif() if (UNICORN_TARGET_ARCH STREQUAL "aarch64" OR UNICORN_TARGET_ARCH STREQUAL "ppc") target_compile_definitions(${TEST_FILE} PRIVATE TARGET_READ_INLINED) endif() endforeach() endif() ``` -------------------------------- ### Start Code Emulation Source: https://context7.com/unicorn-engine/unicorn/llms.txt Begins emulating machine code from a specified address with optional timeout and instruction count limits. ```APIDOC ## Start Code Emulation ### Description Begins emulating machine code from a specified address with optional timeout and instruction count limits. ### Method `uc_emu_start` ### Endpoint N/A (This is a library function) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```c #include int main() { uc_engine *uc; uc_err err; unsigned char code[] = "\x41\x4a"; // INC ecx; DEC edx uint64_t address = 0x1000000; err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err != UC_ERR_OK) { return 1; } err = uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL); err = uc_mem_write(uc, address, code, sizeof(code) - 1); int r_ecx = 0x1234; int r_edx = 0x7890; uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // Emulate all code, no timeout, no instruction limit err = uc_emu_start(uc, address, address + sizeof(code) - 1, 0, 0); if (err != UC_ERR_OK) { printf("Failed on uc_emu_start(): %s\n", uc_strerror(err)); uc_close(uc); return 1; } // Emulate with 2 second timeout err = uc_emu_start(uc, address, address + sizeof(code) - 1, 2 * UC_SECOND_SCALE, 0); // Emulate exactly 5 instructions err = uc_emu_start(uc, address, address + sizeof(code) - 1, 0, 5); // Read results uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); printf("After emulation: ECX = 0x%x, EDX = 0x%x\n", r_ecx, r_edx); uc_close(uc); return 0; } ``` ### Response #### Success Response N/A (This function returns `uc_err` indicating success or failure) #### Response Example N/A ``` -------------------------------- ### C: Multiline Indentation Examples Source: https://github.com/unicorn-engine/unicorn/blob/master/qemu/CODING_STYLE.rst Demonstrates proper indentation for multiline statements in C, including if/else, while/for loops, and function calls. Secondary lines are aligned either after the opening parenthesis or with a 4-space indent. ```c if (a == 1 && b == 2) { while (a == 1 && b == 2) { do_something(x, y, z); do_something(x, y, z); do_something(x, do_another(y, z)); ``` -------------------------------- ### Setup Fuzzing Targets (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt This section sets up fuzzing targets for the Unicorn engine. It defines a list of suffixes for different architectures and creates corresponding executables, linking them with necessary libraries. ```cmake if(UNICORN_FUZZ) set(UNICORN_FUZZ_SUFFIX "arm_arm;arm_armbe;arm_thumb;arm64_arm;arm64_armbe;m68k_be;mips_32be;mips_32le;sparc_32be;x86_16;x86_32;x86_64;s390x_be") if (NOT APPLE) set(SAMPLES_LIB ${SAMPLES_LIB} rt) endif() foreach(SUFFIX ${UNICORN_FUZZ_SUFFIX}) add_executable(fuzz_emu_${SUFFIX} ${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/fuzz_emu_${SUFFIX}.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/fuzz/onedir.c ) target_link_libraries(fuzz_emu_${SUFFIX} PRIVATE ${SAMPLES_LIB} ) endforeach() endif() ``` -------------------------------- ### Configure SPARC-softmmu Library (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Sets up the sparc-softmmu static library using CMake. It lists the necessary source files from the qemu/target/sparc directory and includes compile options, with conditional logic for MSVC compatibility. ```cmake add_library(sparc-softmmu STATIC ${UNICORN_ARCH_COMMON} qemu/target/sparc/cc_helper.c qemu/target/sparc/cpu.c qemu/target/sparc/fop_helper.c qemu/target/sparc/helper.c qemu/target/sparc/int32_helper.c qemu/target/sparc/ldst_helper.c qemu/target/sparc/mmu_helper.c qemu/target/sparc/translate.c qemu/target/sparc/win_helper.c qemu/target/sparc/unicorn.c ) if(MSVC) target_compile_options(sparc-softmmu PRIVATE -DNEED_CPU_H ``` -------------------------------- ### Configure m68k-softmmu Library (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Defines the m68k-softmmu static library using CMake. It includes source files from the qemu/target/m68k directory and sets compile options, including conditional flags for MSVC and the UNICORN_TRACER. ```cmake if(MSVC) target_compile_options(m68k-softmmu PRIVATE -DNEED_CPU_H /FIm68k.h /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/m68k-softmmu /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/m68k ) else() target_compile_options(m68k-softmmu PRIVATE -DNEED_CPU_H -include m68k.h -I${CMAKE_BINARY_DIR}/m68k-softmmu -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/m68k ) endif() if(UNICORN_TRACER) target_compile_options(m68k-softmmu PRIVATE -DUNICORN_TRACER) endif() ``` -------------------------------- ### Configure Unicorn Engine Build Options Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Sets up test and sample files, and conditionally adds compiler definitions based on build configurations. This is crucial for enabling specific features like tracing or shared library builds. ```cmake set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_mem) set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_ctl) set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_ctl) if(UNICORN_TRACER) target_compile_options(unicorn-common PRIVATE -DUNICORN_TRACER) target_compile_options(unicorn PRIVATE -DUNICORN_TRACER) endif() ``` -------------------------------- ### Bash: Execute Python Unicorn Emulation Script Source: https://github.com/unicorn-engine/unicorn/wiki/Quick-Start Command to execute a Python script that utilizes the Unicorn Engine for code emulation. This requires Python and the Unicorn library to be installed. The output will show the emulation process and register states. ```bash $ python test1.py Emulate i386 code Emulation done. Below is the CPU context >>> ECX = 0x1235 >>> EDX = 0x788f ``` -------------------------------- ### Build Fuzzing Targets with CMake Source: https://github.com/unicorn-engine/unicorn/wiki/Developers This command configures the build system to include fuzzing capabilities. It utilizes CMake and requires the `UNICORN_FUZZ` flag to be set. No specific input or output is detailed, but it prepares the project for fuzz testing. ```bash cmake .. -DUNICORN_FUZZ=1 ``` -------------------------------- ### C: Traditional Multiline Comment Style Source: https://github.com/unicorn-engine/unicorn/blob/master/qemu/CODING_STYLE.rst Illustrates the preferred C-style multiline comment format, which includes a row of asterisks on the left and each comment line starting with an asterisk. This style is consistent with the Linux kernel coding style and enhances visual clarity. ```c /* * like * this */ ``` -------------------------------- ### Basic Unicorn Go Usage Example Source: https://github.com/unicorn-engine/unicorn/blob/master/bindings/go/README.md A simple Go program demonstrating the basic functionality of the Unicorn Engine. It initializes an emulator, maps memory, writes machine code, executes it, and reads a register. Error handling is minimal for brevity. ```go package main import ( "fmt" uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" ) func main() { mu, _ := uc.NewUnicorn(uc.ARCH_X86, uc.MODE_32) // mov eax, 1234 code := []byte{184, 210, 4, 0, 0} mu.MemMap(0x1000, 0x1000) mu.MemWrite(0x1000, code) if err := mu.Start(0x1000, 0x1000+uint64(len(code))); err != nil { panic(err) } eax, _ := mu.RegRead(uc.X86_REG_EAX) fmt.Printf("EAX is now: %d\n", eax) } ``` -------------------------------- ### Unicorn Engine Core Source Files (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Lists the primary source files for the Unicorn engine, including its core implementation, soft-MMU virtual machine logic, and CPU core handling. These files are foundational for the overall engine. ```cmake set(UNICORN_SRCS uc.c qemu/softmmu/vl.c qemu/hw/core/cpu.c ) ``` -------------------------------- ### Unicorn Hook Example in Pascal Source: https://github.com/unicorn-engine/unicorn/blob/master/bindings/pascal/README.md Demonstrates how to add a hook for instruction execution in the Unicorn emulator using Pascal. This example utilizes an array of constants to pass arguments, addressing limitations in Pascal's variadic function support. Requires the Unicorn dynamic library. ```pascal uc_hook_add(uc, trace, UC_HOOK_INSN, @HookIn, nil, 1, 0, [UC_X86_INS_IN]); ``` -------------------------------- ### C: Include Directive Ordering Source: https://github.com/unicorn-engine/unicorn/blob/master/qemu/CODING_STYLE.rst Specifies the recommended order for include directives in C files: first "qemu/osdep.h", then system headers within angle brackets <...>, and finally QEMU headers within double quotes "...". This order ensures correct preprocessor macro behavior. ```c #include "qemu/osdep.h" /* Always first... */ #include <...> /* then system headers... */ #include "..." /* and finally QEMU headers. */ ``` -------------------------------- ### Query Unicorn Emulator Status with uc_query Source: https://context7.com/unicorn-engine/unicorn/llms.txt This C code snippet demonstrates how to retrieve information about the Unicorn emulator's current state and configuration. It shows how to get the Unicorn version, check architecture support, query the current mode, page size, and architecture. It also demonstrates how to get the last error and list memory regions. Error handling is included for most operations. ```c #include #include #include int main() { uc_engine *uc; uc_err err; unsigned int major, minor; // Get Unicorn version unsigned int version = uc_version(&major, &minor); printf("Unicorn version: %u.%u (0x%x)\n", major, minor, version); // Check architecture support if (uc_arch_supported(UC_ARCH_X86)) { printf("X86 architecture is supported\n"); } if (uc_arch_supported(UC_ARCH_ARM64)) { printf("ARM64 architecture is supported\n"); } err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err != UC_ERR_OK) { return 1; } // Query current mode size_t mode_query; err = uc_query(uc, UC_QUERY_MODE, &mode_query); if (err == UC_ERR_OK) { printf("Current mode: %zu\n", mode_query); } // Query page size size_t page_size; err = uc_query(uc, UC_QUERY_PAGE_SIZE, &page_size); printf("Page size: %zu bytes\n", page_size); // Query architecture size_t arch_query; err = uc_query(uc, UC_QUERY_ARCH, &arch_query); printf("Architecture: %zu\n", arch_query); // Get last error uc_err last_error = uc_errno(uc); if (last_error != UC_ERR_OK) { printf("Last error: %s\n", uc_strerror(last_error)); } // Get memory regions uc_mem_region *regions; uint32_t count; err = uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL); err = uc_mem_regions(uc, ®ions, &count); if (err == UC_ERR_OK) { printf("Memory regions: %u\n", count); for (uint32_t i = 0; i < count; i++) { printf(" Region %u: 0x%\" PRIx64 \" - 0x%\" PRIx64 \" (perms: 0x%x)\n", i, regions[i].begin, regions[i].end, regions[i].perms); } uc_free(regions); } uc_close(uc); return 0; } ``` -------------------------------- ### Configure PowerPC soft-MMU library (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Configures the CMake build for PowerPC soft-MMU static libraries (ppc and ppc64). It includes source files from QEMU's hardware, target, and libdecnumber components. Compile options are adjusted for MSVC and other compilers, with an option for the UNICORN_TRACER. ```cmake add_library(ppc-softmmu STATIC ${UNICORN_ARCH_COMMON} qemu/hw/ppc/ppc.c qemu/hw/ppc/ppc_booke.c qemu/libdecnumber/decContext.c qemu/libdecnumber/decNumber.c qemu/libdecnumber/dpd/decimal128.c qemu/libdecnumber/dpd/decimal32.c qemu/libdecnumber/dpd/decimal64.c qemu/target/ppc/cpu.c qemu/target/ppc/cpu-models.c qemu/target/ppc/dfp_helper.c qemu/target/ppc/excp_helper.c qemu/target/ppc/fpu_helper.c qemu/target/ppc/int_helper.c qemu/target/ppc/machine.c qemu/target/ppc/mem_helper.c qemu/target/ppc/misc_helper.c qemu/target/ppc/mmu-hash32.c qemu/target/ppc/mmu_helper.c qemu/target/ppc/timebase_helper.c qemu/target/ppc/translate.c qemu/target/ppc/unicorn.c ) if(MSVC) target_compile_options(ppc-softmmu PRIVATE -DNEED_CPU_H /FIppc.h /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/ppc-softmmu /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/ppc ) else() target_compile_options(ppc-softmmu PRIVATE -DNEED_CPU_H -include ppc.h -I${CMAKE_BINARY_DIR}/ppc-softmmu -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/ppc ) endif() if(UNICORN_TRACER) target_compile_options(ppc-softmmu PRIVATE -DUNICORN_TRACER) endif() add_library(ppc64-softmmu STATIC ${UNICORN_ARCH_COMMON} qemu/hw/ppc/ppc.c qemu/hw/ppc/ppc_booke.c qemu/libdecnumber/decContext.c qemu/libdecnumber/decNumber.c qemu/libdecnumber/dpd/decimal128.c qemu/libdecnumber/dpd/decimal32.c qemu/libdecnumber/dpd/decimal64.c qemu/target/ppc/compat.c qemu/target/ppc/cpu.c qemu/target/ppc/cpu-models.c qemu/target/ppc/dfp_helper.c qemu/target/ppc/excp_helper.c qemu/target/ppc/fpu_helper.c qemu/target/ppc/int_helper.c qemu/target/ppc/machine.c qemu/target/ppc/mem_helper.c qemu/target/ppc/misc_helper.c qemu/target/ppc/mmu-book3s-v3.c qemu/target/ppc/mmu-hash32.c qemu/target/ppc/mmu-hash64.c qemu/target/ppc/mmu_helper.c qemu/target/ppc/mmu-radix64.c qemu/target/ppc/timebase_helper.c qemu/target/ppc/translate.c qemu/target/ppc/unicorn.c ) if(MSVC) target_compile_options(ppc64-softmmu PRIVATE -DNEED_CPU_H /FIppc64.h /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/ppc64-softmmu /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/ppc ) else() target_compile_options(ppc64-softmmu PRIVATE -DNEED_CPU_H -include ppc64.h -I${CMAKE_BINARY_DIR}/ppc64-softmmu -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/ppc ) endif() if(UNICORN_TRACER) target_compile_options(ppc64-softmmu PRIVATE -DUNICORN_TRACER) endif() ``` -------------------------------- ### Configure Public Include Directories Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Sets the public include directories for the unicorn and unicorn_static targets. This allows external projects to include Unicorn Engine headers. ```cmake target_include_directories(unicorn PUBLIC include ) if (BUILD_SHARED_LIBS) target_include_directories(unicorn_static PUBLIC include ) endif() ``` -------------------------------- ### CMake: Include Directories and Compile Options Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Configures include paths for the build, including platform-specific directories for MSVC and common directories like 'glib_compat', 'qemu', 'include', and 'qemu/tcg'. It conditionally adds the UNICORN_LOGGING compile option if the UNICORN_LOGGING feature is enabled. ```cmake if(MSVC) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/msvc ) else() include_directories( ${CMAKE_BINARY_DIR} ) endif() include_directories( glib_compat qemu qemu/include include qemu/tcg ) if (UNICORN_LOGGING) add_compile_options(-DUNICORN_LOGGING) endif() ``` -------------------------------- ### Apply Common Compile Options Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Applies common compile options to the unicorn-common and unicorn targets. This ensures consistent build settings across different configurations. ```cmake target_compile_options(unicorn-common PRIVATE ${UNICORN_COMPILE_OPTIONS} ) target_compile_options(unicorn PRIVATE ${UNICORN_COMPILE_OPTIONS} ) ``` -------------------------------- ### String Duplication with GLib Source: https://github.com/unicorn-engine/unicorn/blob/master/qemu/CODING_STYLE.rst Use GLib's g_strdup and g_strndup for duplicating strings instead of the standard strdup and strndup to comply with memory management rules. ```c char *duplicated_string = g_strdup(original_string); char *limited_duplicated_string = g_strndup(original_string, max_len); ``` -------------------------------- ### s390x Soft-MMU Library Configuration (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Defines the static library for the s390x soft-MMU architecture. This includes common and s390x-specific QEMU source files. Compile options are adapted for MSVC and non-MSVC build environments, ensuring necessary headers and include paths are correctly set. ```cmake if (UNICORN_HAS_S390X) add_library(s390x-softmmu STATIC ${UNICORN_ARCH_COMMON} qemu/hw/s390x/s390-skeys.c qemu/target/s390x/cc_helper.c qemu/target/s390x/cpu.c qemu/target/s390x/cpu_features.c qemu/target/s390x/cpu_models.c qemu/target/s390x/crypto_helper.c qemu/target/s390x/excp_helper.c qemu/target/s390x/fpu_helper.c qemu/target/s390x/helper.c qemu/target/s390x/interrupt.c qemu/target/s390x/int_helper.c qemu/target/s390x/ioinst.c qemu/target/s390x/mem_helper.c qemu/target/s390x/misc_helper.c qemu/target/s390x/mmu_helper.c qemu/target/s390x/sigp.c qemu/target/s390x/tcg-stub.c qemu/target/s390x/translate.c qemu/target/s390x/vec_fpu_helper.c qemu/target/s390x/vec_helper.c qemu/target/s390x/vec_int_helper.c qemu/target/s390x/vec_string_helper.c qemu/target/s390x/unicorn.c ) if(MSVC) target_compile_options(s390x-softmmu PRIVATE -DNEED_CPU_H /FIs390x.h /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/s390x-softmmu /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/s390x ) else() target_compile_options(s390x-softmmu PRIVATE -DNEED_CPU_H -include s390x.h -I${CMAKE_BINARY_DIR}/s390x-softmmu -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/s390x ) endif() endif() ``` -------------------------------- ### Emulate X86 32-bit Code in C using Unicorn Engine Source: https://github.com/unicorn-engine/unicorn/wiki/Quick-Start This C code snippet demonstrates how to initialize the Unicorn Engine for X86 32-bit emulation, map memory, write machine code, set register values, execute the code, and read the modified register values. It requires the Unicorn Engine library. ```C #include #include // code to be emulated #define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx // memory address where emulation starts #define ADDRESS 0x1000000 int main(int argc, char **argv, char **envp) { uc_engine *uc; uc_err err; int r_ecx = 0x1234; // ECX register int r_edx = 0x7890; // EDX register printf("Emulate i386 code\n"); // Initialize emulator in X86-32bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err != UC_ERR_OK) { printf("Failed on uc_open() with error returned: %u\n", err); return -1; } // map 2MB memory for this emulation uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return -1; } // initialize machine registers uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // emulate code in infinite time & unlimited instructions err=uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); } // now print out some registers printf("Emulation done. Below is the CPU context\n"); uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); printf(">>> ECX = 0x%x\n", r_ecx); printf(">>> EDX = 0x%x\n", r_edx); uc_close(uc); return 0; } ``` -------------------------------- ### Configure Static Archive Build Options Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Applies compile options specifically for the static archive build. This ensures that the static version of the library is built with the correct settings. ```cmake if (BUILD_SHARED_LIBS) target_compile_options(unicorn_static PRIVATE ${UNICORN_COMPILE_OPTIONS} ) endif() ``` -------------------------------- ### Initialize Unicorn Engine Instance Source: https://context7.com/unicorn-engine/unicorn/llms.txt Opens a new instance of the Unicorn engine for a specified CPU architecture and mode (e.g., 32-bit or 64-bit). Handles potential initialization errors and ensures resources are cleaned up using uc_close(). ```c #include int main() { uc_engine *uc; uc_err err; // Initialize emulator in X86 32-bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); if (err != UC_ERR_OK) { printf("Failed on uc_open() with error: %s\n", uc_strerror(err)); return 1; } // Initialize ARM64 emulator uc_engine *uc_arm; err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc_arm); // Initialize X86-64 emulator uc_engine *uc_x64; err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc_x64); // Clean up uc_close(uc); uc_close(uc_arm); uc_close(uc_x64); return 0; } ``` -------------------------------- ### Main Unicorn Library Definition (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Defines the main 'unicorn' library using the UNICORN_SRCS list, which may include object files compiled from assembly or other sources. ```cmake add_library(unicorn ${UNICORN_SRCS}) ``` -------------------------------- ### MSVC Specific Linker and Target Properties Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Configures linker libraries and target properties specifically for MSVC builds, including handling shared libraries and setting version information. ```cmake if(MSVC) if(BUILD_SHARED_LIBS) target_compile_options(unicorn PRIVATE -DUNICORN_SHARED ) target_link_libraries(unicorn_static PRIVATE ${UNICORN_LINK_LIBRARIES} ) endif() target_link_libraries(unicorn PRIVATE ${UNICORN_LINK_LIBRARIES} ) set_target_properties(unicorn PROPERTIES VERSION "${UNICORN_VERSION_MAJOR}.${UNICORN_VERSION_MINOR}" ) else() target_link_libraries(unicorn PRIVATE ${UNICORN_LINK_LIBRARIES} m ) target_link_libraries(unicorn PUBLIC m ) if (BUILD_SHARED_LIBS) target_link_libraries(unicorn_static PUBLIC m ) target_link_libraries(unicorn_static PRIVATE ${UNICORN_LINK_LIBRARIES} m ) endif() set_target_properties(unicorn PROPERTIES VERSION ${UNICORN_VERSION_MAJOR} SOVERSION ${UNICORN_VERSION_MAJOR} ) endif() ``` -------------------------------- ### TriCore Soft-MMU Library Configuration (CMake) Source: https://github.com/unicorn-engine/unicorn/blob/master/CMakeLists.txt Sets up the static library for the TriCore soft-MMU target, incorporating common architecture sources and TriCore-specific QEMU files. It adjusts compile options for MSVC compatibility, specifying header inclusion and include paths. ```cmake if (UNICORN_HAS_TRICORE) add_library(tricore-softmmu STATIC ${UNICORN_ARCH_COMMON} qemu/target/tricore/cpu.c qemu/target/tricore/fpu_helper.c qemu/target/tricore/helper.c qemu/target/tricore/op_helper.c qemu/target/tricore/translate.c qemu/target/tricore/unicorn.c ) if(MSVC) target_compile_options(tricore-softmmu PRIVATE -DNEED_CPU_H /FItricore.h /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/tricore-softmmu /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/tricore ) else() target_compile_options(tricore-softmmu PRIVATE -DNEED_CPU_H -include tricore.h -I${CMAKE_BINARY_DIR}/tricore-softmmu -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/tricore ) endif() endif() ```