Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dartaotruntime] Support ELF linking or appending snapshot as ELF data section #50926

Open
ntkme opened this issue Jan 6, 2023 · 7 comments
Open
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends.

Comments

@ntkme
Copy link
Contributor

ntkme commented Jan 6, 2023

When executing a self-contained executable (dartaotruntime + aot-snapshot), the way we get snapshot is first File::ReadLinkInto("/proc/self/exe", ...), and then attempt to read snapshot from the file path as following:

sdk/runtime/bin/main.cc

Lines 1190 to 1191 in 8e7b111

if (Platform::ResolveExecutablePathInto(executable_path, kPathBufSize) > 0) {
app_snapshot = Snapshot::TryReadAppendedAppSnapshotElf(executable_path);

const char* Platform::ResolveExecutablePath() {
return File::ReadLink("/proc/self/exe");
}
intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
return File::ReadLinkInto("/proc/self/exe", result, result_size);
}

However, /proc/self/exe is not a reliable way to get the path to current executable. It can be broken in a few ways, but in particular when the executable is explicitly launched via ld-linux. Here is a demonstration:

$ /usr/bin/readlink -f /proc/self/exe
/usr/bin/readlink
$ /lib64/ld-linux-x86-64.so.2 /usr/bin/readlink -f /proc/self/exe
/usr/lib/x86_64-linux-gnu/ld-2.31.so

The behavior of dartaotruntime is affected by this, that when launching via ld-linux, the call to Snapshot::TryReadAppendedAppSnapshotElf(executable_path) will effectively read ld-linux and not be able to correct locate the embedded aot-snapshot inside the elf binary, for which it will simply behave as running a normal dart vm instead of running the aot snapshot.

This is the root cause of: sass/dart-sass-embedded#78, please see discussion on user impact there. Interestingly, it seems on certain linux distribution or with certain config, this issue is present even if the user is directly launching the executable without explicitly invoking ld-linux from command line. In such case, it is a bigger issue as all self-contained executables are broken on such platform.

@ntkme ntkme changed the title Linux /proc/self/exe is not reliable for getting snapshot inside self-contained executable [dartaotruntime] Linux /proc/self/exe is not reliable for getting snapshot inside self-contained executable Jan 9, 2023
@mraleph
Copy link
Member

mraleph commented Jan 9, 2023

@ntkme Do you actually have a reproduction for the issue outside of loading through runtime linker directly? Because if that's the only case when it breaks - I would be tempted to mark this low priority. The real fix here is to start doing real linking and stop doing concatenation of files, which we have been using as a stop gap solution.

@mraleph mraleph added the area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends. label Jan 9, 2023
@ntkme
Copy link
Contributor Author

ntkme commented Jan 9, 2023

Personally I don’t have a way to reproduce it other than invoking through the linker, but it did happen for one user when invoking directly: sass/dart-sass-embedded#78 (comment)

Unfortunately, that user stopped replying the thread so that we don’t know much about the environment and configuration where it happened.

@ntkme
Copy link
Contributor Author

ntkme commented Jan 9, 2023

Another way to break this is use patchelf to modify the interpreter, which is common for NixOS users. Technically it is a different issue but closely related. As patchelf don’t understand the magic offset, once the binary is patch the offset would be wrong: sass-contrib/sass-embedded-host-ruby#91 (comment)

@mraleph
Copy link
Member

mraleph commented Jan 9, 2023

Yeah, the issue with patchelf has the same underlying reason - doing real linking (or at the very least real ELF sections editing) is the answer.

@ntkme ntkme changed the title [dartaotruntime] Linux /proc/self/exe is not reliable for getting snapshot inside self-contained executable [dartaotruntime] Append trailing data directly on ELF is undefined behavior and snapshot can be broken Jan 9, 2023
@ntkme ntkme changed the title [dartaotruntime] Append trailing data directly on ELF is undefined behavior and snapshot can be broken [dartaotruntime] Append trailing data directly on ELF is undefined behavior and snapshot can be broken for self-contained exe Jan 10, 2023
@NANASHI0X74
Copy link

I tried to package a dart executable for nixos and apparently I've run into this exact issue.

@NANASHI0X74
Copy link

@mraleph you said that the concatenating of aot snapshots was a stopgap solution, but are there any plans or ongoing efforts to do the real linking as you suggested? 😄

@mraleph
Copy link
Member

mraleph commented Sep 11, 2023

No ongoing effort at the moment, sorry. If you want to distribute AOT compiled Dart code to the OS where our current approach breaks then your next best option currently is to distribute AOT snapshot and AOT runtime as separate binaries and have a shell script which wraps these two things together.

@ntkme ntkme changed the title [dartaotruntime] Append trailing data directly on ELF is undefined behavior and snapshot can be broken for self-contained exe [dartaotruntime] Support ELF linking or appending snapshot as ELF data section Sep 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, FFI, and the AOT and JIT backends.
Projects
None yet
Development

No branches or pull requests

3 participants