---
# System prepended metadata

title: Deciding “Wrapped” vs. “Emulated”

---

# Deciding “Wrapped” vs. “Emulated”

> [library.c](https://github.com/ptitSeb/box64/blob/198eea49a83909209d203eea2e718112cca5dc48/src/librarian/library.c)

Box64 uses three flags—`notwrapped`, `essential`, and `precise`—to decide whether a library should be loaded via the host’s native loader (“wrapped”) or via its ELF loader (“emulated”).

In short, when `precise == 1`, Box64 will go straight to `initEmulatedLib()`. If `initEmulatedLib()` fails, Box64 will attempt `initWrappedLib()` before returning an error.

Similarly, when `precise == 0`, `notwrapped == 0`, and `essential == 1`, Box64 will first try `initWrappedLib()`, and will fall back to `initEmulatedLib()` if the wrapped loading fails.

```c
if(!notwrapped && !precise)
    initWrappedLib(lib, context);
if(lib->type==LIB_UNNKNOW)// faills
    initEmulatedLib(path, lib, context, verneeded);
    // still not loaded but notwrapped indicated: use wrapped...
if(lib->type==LIB_UNNKNOW && notwrapped && !precise)
        initWrappedLib(lib, context);
```

for example `libz.so.1` is not in notwrapped list and not precise
```shell
Error initializing native libz.so.1 (last dlerror is libz.so.1: cannot open shared object file: No such file or directory)
Using emulated /usr/lib/libz.so.1
```


### `notwrapped`: Skip native loading
It is determined by checking if the library name appears in `box64_emulated_libs`, which is a collection of libraries that should be emulated:
```c
path_collection_t   box64_emulated_libs;    // Collection of libs that should not be wrapped
```
By default, `box64_emulated_libs` includes only tree libraries:
```c
"BOX64_EMULATED_LIBS=libSDL2-2.0.so.0\n"
"BOX64_EMULATED_LIBS=libSDL2-2.0.so.0:libSDL2_ttf-2.0.so.0\n"
```
Libraries can be added to `box64_emulated_libs` using the environment variable `BOX64_EMULATED_LIBS`, which forces specific libraries to be loaded in emulated mode:

- `BOX64_EMULATED_LIBS`=XXXX: Emulate library XXXX.

- `BOX64_EMULATED_LIBS`=XXXX:YYYY:ZZZZ: Emulate libraries XXXX, YYYY, and ZZZZ.

(special exceptions): `notwrapped` is set to 1 in the following two cases:

1. If the library is not found in `box64_emulated_libs` and is not an essential library, but the environment variable `BOX64_PREFER_EMULATED` is set:
```c
if(!notwrapped && BOX64ENV(prefer_emulated) && !essential)
    notwrapped = 1;
```
2. If the library name is `libSDL_sound-1.0.so.1` and SDL2 is already loaded:
```c
if(!notwrapped && !strcmp(lib->name, "libSDL_sound-1.0.so.1") && my_context->sdl2lib)
    notwrapped = 1;
```

### `essential`: Always wrapped
The `essential` flag is set if the library appears in the `essential_libs` list — a hardcoded list of core system libraries that must always be loaded in wrapped mode:
```c
static const char* essential_libs[] = {
    "libc.so.6", "libpthread.so.0", "librt.so.1", "libGL.so.1", "libGL.so", "libX11.so.6", 
    "libasound.so.2", "libdl.so.2", "libm.so.6", "libbsd.so.0", "libutil.so.1", "libresolv.so.2", "libresolv.so", 
    "libXxf86vm.so.1", "libXinerama.so.1", "libXrandr.so.2", "libXext.so.6", "libXfixes.so.3", "libXcursor.so.1",
    "libXrender.so.1", "libXft.so.2", "libXi.so.6", "libXss.so.1", "libXpm.so.4", "libXau.so.6", "libXdmcp.so.6",
    "libX11-xcb.so.1", "libxcb.so.1", "libxcb-xfixes.so.0", "libxcb-shape.so.0", "libxcb-shm.so.0", "libxcb-randr.so.0",
    "libxcb-image.so.0", "libxcb-keysyms.so.1", "libxcb-xtest.so.0", "libxcb-glx.so.0", "libxcb-dri2.so.0", "libxcb-dri3.so.0",
    "libXtst.so.6", "libXt.so.6", "libXcomposite.so.1", "libXdamage.so.1", "libXmu.so.6", "libxkbcommon.so.0", 
    "libxkbcommon-x11.so.0", "libpulse-simple.so.0", "libpulse.so.0", "libvulkan.so.1", "libvulkan.so",
    "ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4", "libanl.so.1",
    "ld-linux.so.2", "ld-linux.so.3"
};
```
There’s also a separate list for EGL/GLES libraries:
```c
static const char* essential_libs_egl[] = {
    "libEGL.so", "libGLESv2.so"
};
```
Their wrap behavior controlled via the environment variable `BOX64_WRAP_EGL`:

- `BOX64_WRAP_EGL`=0: Prefer emulated libraries for EGL and GLESv2 (default).

- `BOX64_WRAP_EGL`=1: Prefer wrapped/native libraries for EGL and GLESv2.


### `precise`: libraries loaded from a specific path 

The `precise` flag controls whether the loader should prefer the native host library, based on the path format and certain conditions.
```c
int precise = (!BOX64ENV(prefer_wrapped) && !essential && path && strchr(path, '/'))?1:0;
if(!notwrapped && precise && strstr(path, "libtcmalloc_minimal.so"))
    precise = 0;    // allow native version for tcmalloc_minimum
```

>[[BOX64] Error loading needed lib stdc++.so.6](https://github.com/ptitSeb/box64/issues/2114)


# Wrapper function

How does it all work? Well, each wrapper function is a function that takes in a pointer to the current emu structure and the native (wrapped) function pointer. Then, given that all registers and the stack is stored in the emu structure, the wrapper unpacks the arguments and give them all to the native function. Then, the native function executes (quickly, since it’s native) and returns, giving the hand back to box86. Finally, a ret (or retn, depending on the function) instruction is executed, and the program continues execution as normal.


redirects the call to a wrapper function instead of executing the x86 code directly. This redirection is facilitated by inserting a special opcode sequence (0xCC 0x53 0x43)

---
# Dynamic Linking with Shared Libraries

 

----
##  dynamic recompiler

The main tasks a dynamic recompiler has to perform are:

- Reading in machine code from the source platform (x86-64 system runing linux and using the standard ELF-64)
- Emitting machine code for the target platform(amd64 and RV64)

A dynamic recompiler may also perform some auxiliary tasks:

- Managing a cache of recompiled code (dynablock)
- Updating of elapsed cycle counts on platforms with cycle count registers
- Management of interrupt checking
- Providing an interface to virtualized support hardware, for example a GPU
- Optimizing higher-level code structures to run efficiently on the target hardware 


liking issues that can affect the performance and correctness



Linux ld program take as input a collection of relocatable
object files and command-line arguments and generate as output a fully linked
executable object file that can be loaded and run

---
How does Box64 deal with **Symbol resolution** and **Relocation**


Object file are merely collection of blocks of bytes

---

As one can guess, the emulated libraries are those that need to be, well, emulated. In other words, no distinction is made between the main program and those libraries: all the code is executed either by the dynarec or the x86 emulator. As such, they are also loaded the same as the main executable.

On the other hand, native libraries are the strength of box86. How they work is that execution will exit from the emulated world and go to the native, ARM world. As such, they are loaded differently: some memory is allocated for the bridges and the native library is loaded in memory.

---

When relocating to a native address however, box86 will make the address point to some pseudo-valid x86 code. This pseudo-valid code is actually an opcode that interrupts the program (by design) 0xCC (INT3), some special signature (the characters ‘S’ and ‘C’, hex 53 43), followed by two pointers used later.

```c
typedef union onebridge_s {
    struct {
    uint8_t CC;     // CC int 0x3
    uint8_t S, C;   // 'S' 'C', just a signature
    wrapper_t w;    // wrapper
    uintptr_t f;    // the function for the wrapper
    uint8_t C3;     // C2 or C3 ret
    uint16_t N;     // N in case of C2 ret
    const char* name;   // name of the function bridged
    };
    struct {
    uint8_t B8;     // B8 00 11 22 33 mov eax, num
    uint32_t num;
    uint8_t _0F; uint8_t _05;   // 0F 05 syscall
    uint8_t _C3;    // C3 ret
    const char* syscall_name;   //not used for now
    };
    uint64_t dummy[4];
} onebridge_t;
```