tonisuter / aws-lambda-swift

A custom AWS Lambda Runtime for Swift
138 stars 13 forks source link

Where does the list of required shared libraries come from? #5

Closed ole closed 5 years ago

ole commented 5 years ago

Hi Toni, great project! I found it through your post on the Swift forums.

I modified your project to write my own little function. Since my function uses Swift 5 features, I switched the Docker image to codevapor/swift:5.0.

Everything seemed to work, but when I tested my function on AWS, it failed with:

error while loading shared libraries: libswiftDispatch.so: cannot open shared object file: No such file or directory
screen shot 2018-12-25 at 21 04 36

It looks like the source of this error is that the names of one or more shared libraries changed in Swift 5, e.g. libdispatch.so is now called libswiftDispatch.so. So I need to update the list of shared libraries in the Makefile. Can I ask how you generated this list?

Running ldd [path_to_my_binary] on Linux seems to be an option to get a list of the shared libraries loaded by an executable, but I wanted to ask if you used a different option.

Thanks and happy holidays!

PS: Don't let me stop you from enjoying your holidays. This isn't urgent.

tonisuter commented 5 years ago

Hi Ole

Thank you :-)! That's a good question.

I tried several things. First, I tried to statically link the standard library using swiftc's -static-stdlib flag. This works fine when the program only uses the standard library. However, it doesn't work on Linux when the program imports Foundation due to a bug (see SR-2205).

So I created a very simple Swift executable in a swift:latest Docker container that just imports Foundation and prints the current date. I used the ldd command to get a list of the shared libraries that the executable uses (see Stackoverflow):

$ docker run --rm -it swift /bin/bash
root@0f4fa22b3c5f:/# mkdir TestPkg
root@0f4fa22b3c5f:/# cd TestPkg
root@0f4fa22b3c5f:/TestPkg# swift package init --type executable
root@0f4fa22b3c5f:/TestPkg# echo "import Foundation" > Sources/TestPkg/main.swift
root@0f4fa22b3c5f:/TestPkg# echo "print(Date())" >> Sources/TestPkg/main.swift
root@0f4fa22b3c5f:/TestPkg# swift build
root@0f4fa22b3c5f:/TestPkg# ldd .build/debug/TestPkg | sed -e 's/\t//' | sed -e 's/.*=..//' | sed -e 's/ (0.*)//' | sort

On AWS, I then tried to execute the lambda while setting the library search path to a directory that contains all of those shared libraries like this:

LD_LIBRARY_PATH=./shared-libs ./lambda

That didn't work due to a relocation error. Thanks to this repository I figured out that I can execute the lambda through the dynamic linker (i.e., the ld-linux-x86-64.so.2 file) which somehow solves the relocation error. This is what I'm now doing in the bootstrap file and it seems to work quite well.

I hope this helps. Happy holidays to you, too!

ole commented 5 years ago

Thanks @tonisuter, that's very helpful. I'll try again and report back.

ole commented 5 years ago

Copying the list produced by ldd into the Makefile worked, so I can confirm (unsurprisingly) the process also works with the current Swift 5 prerelease using the codevapor/swift:5.0 Docker image. Thanks again for the help.