jart / blink

tiniest x86-64-linux emulator
ISC License
7.01k stars 225 forks source link

Dynamic shared object support #7

Closed worthless443 closed 1 year ago

worthless443 commented 2 years ago

as of the commit 7fa43c6d8e90acf2a966a9da480e884536b2b79d, building using the default make target (which I believe is o/blink/blink) and running as

# hope this is the way it should be used
./o/blink/blink  /usr/bin/<program>

raises

I2022-11-26T19:51:13.269347:blink/throw.c:59: 32942: SEGMENTATION FAULT AT ADDRESS 5007
     PC 15 add %al,(%rax)
     AX 0000000000005007  CX 0000000000000000  DX 00007ffffffff8f8  BX 0000000000000000
     SP 00007ffffffff8d8  BP 0000000000000000  SI 0000000000000000  DI 0000000000001120
     R8 000000000000007f  R9 0000000000000000 R10 0000000000000000 R11 0000000000000000
    R12 0000000000000000 R13 0000000000000000 R14 0000000000000000 R15 0000000000000000
     FS 0000000000000000  GS 0000000000000000 OPS 22               JIT 0               
    /usr/bin/python3
    000000000000 000000000015 UNKNOWN

And... I'm not sure if this is how it is intended to run or it is an issue to be looked upon.

jart commented 2 years ago

Blink is still a work in progress. Right now it's only able to run static executables. I think it's a bad look seeing something like this happen. We should at the very least display a friendlier error when an executable has shared object dependencies.

trungnt2910 commented 1 year ago

With file system APIs implemented, what's preventing blink from actually supporting shared object dependencies?

As for what I know, all we need to do is to:

(Or maybe I'm wrong, I've done ELF loading for binaries of other OSes before but not Linux.)

bjorn3 commented 1 year ago

Transfer control to ld-linux-x86-64.so.2 and let it handle the rest.

I believe you need to load both the original ELF binary and the dynamic linker and then set up an auxiliary vector with AT_BASE pointing to the base address of the dynamic linker, AT_PHDR pointing to the original binary's program header (as well as AT_PHENT and AT_PHNUM with the correct values for this program header), AT_ENTRY pointing to the original binary's entrypoint, AT_EXECFD pointing to the fd of the original binary's file and AT_EXECFN pointing to a string containing the path to the original binary's file.

See https://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c#n1828

Implement basic ELF relocation types.

Is that even necessary? I thought the dynamic linker would handle that.

jart commented 1 year ago

Thank you for the help @bjorn3. Dynamic executable support incoming.

bjorn3 commented 1 year ago

Thanks! I tried a couple of non-trivial dynamically linked executables. Rustup and cargo can show their help text. Rustc on the other hand doesn't seem to work. The first issue is that rpath doesn't seem to function correctly. Setting LD_LIBRARY_PATH results in /home/bjorn/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc: error while loading shared libraries: libLLVM-15-rust-1.66.0-stable.so: cannot enable executable stack as shared object requires: Invalid argument. Readelf reveals that PT_GNU_STACK is missing from libLLVM-15-rust-1.66.0-stable.so. Do you want me to open separate issues for these problems?

jart commented 1 year ago

Sure. Run an strace on it. (Or enable LOG_SYS in blink/log.h). Blink doesn't forbid programs from executing the stack. So it's probably upset that some system call return EINVAL or something.

bjorn3 commented 1 year ago

Opened https://github.com/jart/blink/issues/39