FEX
FEX copied to clipboard
Implement libc thunk library
Thunking libc itself has the potential to make thunking other libraries significantly more robust by making various workarounds unnecessary (see #1208). Here's an (incomplete) list of nontrivial things that need to be tackled:
- Program startup (
__libc_start_main) printf-like functions (including fprintf, sprintf, snprintf, vprintf, ...)- Functions with function pointer arguments (
qsort) - Data symbol handling:
errno- getopt:
optarg/optind/opterr/optopt
- Struct repacking:
- Repacking of data in parameter structs that have different layouts across architectures (e.g.
stat) - Repacking for arguments passed to callbacks
- Repacking of data in parameter structs that have different layouts across architectures (e.g.
__lxstat/__fxstat/...: Data layout of parameter struct is determined by a version field
errno handling
errno is a data symbol exported by libc.so, written to by many (but not all) libc functions on error (and written to by guest application to "reset" errors). When thunking libc, the problem that arises is that the errno symbol exposed by thunked libc to guest applications is a different symbol than the native errno symbol that host libc functions write to. Unless we find magic to allow for sharing the same data symbol, some mechanism to synchronize the value between the two data symbols is needed.
A lot of functions set errno, so a scalable approach is needed for synchronizing the native/thunk errno values. Here are some potential options to handle this:
- Brute-force synchronize errno before/after every libc function
- Add a thunkgen annotation to mark functions that potentially set
errnoand autogenerate synchronization code for annotated functions, only - memprotect the
errnosymbol to catch reads/writes by the guest applications in a SIGSEV handler and synchronize on-demand - Use a custom dynamic loader that relocates matching data symbols where possible given ABI compatibility constraints