Fixes#2136
This is a fairly tricky edge case to support with FEX.
If execveat is used with AT_EMPTY_PATH then the application can pass an
FD to execve instead of a filename. This includes FDs that have been
deleted from the disk so the child process can't open it by filename
anymore.
To work around this limitation, we need to pass the FD to the new FEX
process and open it directly, similar to how binfmt_misc works with FDs.
The FD will get passed through environment variables, which the new
process will check for and then remove the variable from the
environment.
Lots of prickly edge cases to support here.
Without binfmt_misc:
- Passes the FD to FEXLoader directly.
- Requires duplicating the FD if it has O_CLOEXEC on the FD.
With binfmt_misc:
- Shebang file, pass directly to FEXLoader, just like without binfmt.
- x86 ELF Files, rely on the kernel's binfmt_misc support here.
- Unsupported ELF files, let kernel handle it through binfmt_misc
Argument handling:
- The application can pass in no arguments.
- Means our application configurations were failing to find a config
- Also various checks in the frontend were failing.
- If opened through an FD, find the symlink for that FD for the
application configuration instead.
Side note:
Fixed a performance issue in execve where when we were checking for file
format support. Either ELF or Shebang files, we were reading the /whole/
file upfront. We only need to read a header worth of ELF files, and only
257 bytes if it is potentially a shebang file. Should dramatically
reduce some application's execve times.
The current separated adr and adrp handlers are difficult to use if you
don't know if the resulting address is going to be within 1MB or 4GB.
Adds a `LongAddressGen` helper that will generate the various pieces of
code that will need to be emitted.
Backward labels:
- Can generate three different code segments depending on distance to
label
- adr if label is within 1MB
- adrp if label is 4K page aligned and within 4GB
- adrp+add if label is within 4GB
Forward labels:
- Can generate three different code segments depending on distance to
label
- nop+adr if label is within 1MB
- nop+adrp if label is 4K page aligned and within 4GB
- adrp+add if label is within 4GB
There is still the limitation that this can't generate addresses to
labels that are >4GB away. Which is fine.
We can do a single LDP upfront when loading from the code cache, which
saves an instruction and one LDP costs the same as a single LDR.
Itty bitty optimization in the hot dispatcher.
Pulled from #2176.
On x86-64 the SA_SIGINFO sa_flag is actually a no-op. It is always used
even if not set.
Ensure that we setup siginfo_t regardless of flag being set.
On 32-bit x86 this still needs to be adhered to.
Little side bits that don't change anything
- EFLAGS is passed in signfo correctly.
- User provided restorer usage locations is documented but not
implemented.
We shouldn't use O_EXCL, since we need to overwrite previous entry PIDs
if they happen to exist. The kernel ensures that PIDs don't overlap, but
in some kernel configurations PIDs are aggressively reused, resulting
in O_EXCL quickly hitting an issue when writing stale files.
Additionally O_DIRECT, this doesn't allow us to write to files, so all
write functions were failing.
Additionally use O_APPEND, we are only ever appending, so let the kernel
know.
Additionally use O_TRUNC, in the case that a stale perf file exists,
this will immediately truncate the file to zero.
Optimize `FileLoad` by not using fstream.
For some reason fstream is just really bad.
Switching over to raw pread cuts the amount of time it takes to read
files by a quarter of CPU time.
This is causing some heartburn with the hardlink.
- Removes some termux cmake list hacking.
- Removes the need to do post-install packaging fixups when hardlinks get dropped.
- Removes a custom uninstall target that was necessary before.
Map lookup was quite expensive, switched over to three small vectors
that are constexpr instead.
Some file querying and parsing was fairly slow as well. Optimized to
make that CPU time to go away.
This improves initialization time of CPUIDEmu by 33%
If we have a fixed file to read, we can read it in three syscalls.
fstream is...weirdly slow in the other implementation.
Theoretically in the future this can be improved to a single syscall if
the `readfile` syscall ends up in upstream Linux.
Fixes#2095
std::random_device can fail to find a random source and throw an assert
during initialization.
The constructor allows you to provide a token string to select an
explicit random source, but this is c++ library specific and will still
assert if the source isn't found. Also specific tokens are very much
target and library specific, so it is unsafe to use.
In the libstdc++ case, the default implementation will try to open
`/dev/urandom` which might not be available on all targets.
Instead of relying on this C++ object, use the `getrandom` syscall
directly to generate our RNG used in the ELFCodeLoader.
Resolves any sort of asserting case, blocks on RNG generation, and is
guaranteed to be available since this syscall has been available since a
very old kernel version.
Pulled from #2176.
Ensures that when we are handling signals we are actually restoring a
stack state that is what we expect..
While this could randomly intersect with other stack data, it is highly
unlikely and will still capture incorrect stack frames otherwise.
Keeps it out of release build to ensure we aren't sticking random data
in the stack when it wouldn't have even been checked.
When a process is in the process of forking and getting ready for
execve, it is common practice to do a `close_range` or close loop to
close all file descriptors before the execve.
This is a security/sanitization feature to ensure that FDs aren't leaked
to the child process. While it is more reliable to have these FDs opened
with O_CLOEXEC, people get it wrong all the time so this feature has
been put in place. Both python and glibc wrappers for launching
applications do this.
The problem with this for FEX is that we were using a FILE handle for
emitting JIT symbols to the perf file. When the underlying FD is ripped
out from under the FILE handle, it throws an assert that we can't
recover from.
Switching to a raw FD and checking to ensure the FD is still open on
writes means that we can safely stop JIT symbol logging when a process
is closing FDs under us.
Fixes a crash in Steam early startup where a python script is run for
checking if packages are installed.
Adds three classes:
- Advanced SIMD three same (FP16)
- Advanced SIMD two-register miscellaneous (FP16)
- Advanced SIMD three-register extension
A handful of the three-register extension unit tests are disabled
because the vixl disassembler doesn't support them.
Only six more classes of ASIMD operations remaining once this is merged.
CIVAU does Clean+Invalidate to `Point Of Unification`
CIVAC does Clean+Invalidate to `Point of Coherency`
`Point of Unification` means to L2/L3, so unification of core
visibility.
`Point of Coherency` means SLC/RAM, All cores, DNA engines, etc must be
coherent.