1

I am trying to run a simple tcl script with tclsh8.6 that I compiled from source using a musl toolchain on x86_64 Debian.

The script, hello.tcl, looks like this:

puts hello

and when I try to run it I get the following error:

$ /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl
-bash: /usr/local/x86_64-linux-musl/bin/tclsh8.6: No such file or directory

The necessary tcl libraries and include files are all installed to the prefix /usr/local/x86_64-linux-musl. The binary also exists:

$ ls -l /usr/local/x86_64-linux-musl/bin/tclsh8.6
-rwxr-xr-x 1 root root 8328 Nov 15 12:18 /usr/local/x86_64-linux-musl/bin/tclsh8.6

$ ldd /usr/local/x86_64-linux-musl/bin/tclsh8.6 
    linux-vdso.so.1 (0x00007ffd04718000)
    libtcl8.6.so => /usr/local/x86_64-linux-musl/lib/libtcl8.6.so (0x00007f005981e000)
    libc.so => /usr/local/x86_64-linux-musl/lib/libc.so (0x00007f0059587000)

I would like to keep things musl based, so I am trying to avoid a potential solution I found elsewhere, which is to reinstall tcl or tcl-dev with apt-get.

What is causing this error? Any guidance/help is greatly appreciated. Thanks :)

EDIT

As requested by some of the comments here is some additional information.

The output of the file command:

$ file /usr/local/x86_64-linux-musl/bin/tclsh8.6 
/usr/local/x86_64-linux-musl/bin/tclsh8.6: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, not stripped

The output of the strace command:

strace /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl 
execve("/usr/local/x86_64-linux-musl/bin/tclsh8.6", ["/usr/local/x86_64-linux-musl/bin"..., "hello.tcl"], 0x7fffb8c5b278 /* 19 vars */) = -1 ENOENT (No such file or directory)
strace: exec: No such file or directory
+++ exited with 1 +++

After seeing this output, I checked to see if the loader/interpreter existed at /lib and it didn't. To fix this, I ran:

$ sudo ln -s /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1

That gave me a different error when I ran tclsh8.6:

$ /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl 
-bash: /usr/local/x86_64-linux-musl/bin/tclsh8.6: Permission denied

Running it with sudo gives the same thing:

$ sudo /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl 
sudo: unable to execute /usr/local/x86_64-linux-musl/bin/tclsh8.6: Permission denied

The permissions on the interpreter and script are as follows:

$ ls -l /usr/local/x86_64-linux-musl/bin/tclsh8.6 
-rwxr-xr-x 1 root root 8328 Nov 15 13:34 /usr/local/x86_64-linux-musl/bin/tclsh8.6
$ ls -l hello.tcl 
-rwxr-xr-x 1 user user 11 Nov 15 12:44 hello.tcl

Hopefully this new information helps a bit more.

EDIT 2

More permission information :)

$ ls -l /lib/ld-musl-x86_64.so.1 
lrwxrwxrwx 1 root root 52 Nov 16 10:04 /lib/ld-musl-x86_64.so.1 -> /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1

$ ls -l /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1 
lrwxrwxrwx 1 root root 12 Nov 15 12:02 /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1 -> /lib/libc.so

$ $ ls -l /lib/libc.so
-rw-r--r-- 1 root root 246 Nov 14 15:15 /lib/libc.so

And here is the contents of /lib/libc.so:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( //lib/libc.so.6 //lib/libc_nonshared.a  AS_NEEDED ( //lib/ld-linux-x86-64.so.2 ) )

It is a linker script, which if you make executable fails and says the library is corrupted.

peachykeen
  • 4,143
  • 4
  • 30
  • 49
  • Can you run it without any arguments to get a tcl repl? – Shawn Nov 15 '20 at 22:34
  • @Shawn I have tried this and it gives the same error. – peachykeen Nov 16 '20 at 04:40
  • 2
    And what does `file /usr/local/x86_64-linux-musl/bin/tclsh8.6` say? – Shawn Nov 16 '20 at 10:08
  • This is very strange. `strace /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl` might report something about what's going wrong. (It'll produce a _lot_ of output so you'll need to read carefully…) – Donal Fellows Nov 16 '20 at 10:23
  • (Since on my system, /usr/bin/tclsh8.6 is a shared object that uses /lib64/ld-linux-x86-64.so.2 as an interpreter, I'm guessing your musl one is the same way but the linker it's looking for isn't present, hence the error) – Shawn Nov 16 '20 at 11:58
  • @Shawn I updated the original question a lot more information and an updated attempt to solve the problem. Thank you for helping. – peachykeen Nov 16 '20 at 17:25
  • @DonalFellows I included the output of `strace` above. – peachykeen Nov 16 '20 at 17:26
  • Hah, I was right about the missing ld.so! Now what are the permissions on `/usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1`? – Shawn Nov 16 '20 at 17:34
  • Yes! Good call @Shawn! I added the additional permission info above. – peachykeen Nov 16 '20 at 17:37
  • I feel like that last symlink to /lib/libc.so is not correct, but don't have anything with musl to confirm (It's definitely wrong for glibc setups, which end up pointing to wherever ld-VERSION.so lives) – Shawn Nov 16 '20 at 17:58
  • OK! I solved it. Thank you for continued patience and help! You are correct again :) The last symlink should link to the musl `libc.so` at `/usr/local/x86_64-linux-musl/lib/libc.so` which is executable. I guess it turns out that the program interpreter also contains the libc implementation. If you want to type up an answer, I can accept and close this question, or I can type up the answer. – peachykeen Nov 16 '20 at 18:12

1 Answers1

1

With the help of @Shawn I was able to figure out my problem.

tclsh8.6 was looking for the program interpreter at /lib/ld-musl-x86_64.so.1 which didn't exist - I guess when I was installing musl-cross-make it didn't set this up. To fix this problem, I simply symlinked from where ld-musl-x86_64.so.1 was located to lib:

$ sudo ln -s /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1

However, I still was getting an error, but this time it was a permissions error:

$ /usr/local/x86_64-linux-musl/bin/tclsh8.6 hello.tcl 
-bash: /usr/local/x86_64-linux-musl/bin/tclsh8.6: Permission denied

It turns out that ld-musl-x86_64.so.1 ended up being a symlink that resolved to /lib/libc.so which is a linker script and not the executable DSO that we want. I changed this symlink accordingly:

sudo ln -fs /usr/local/x86_64-linux-musl/lib/libc.so /usr/local/x86_64-linux-musl/lib/ld-musl-x86_64.so.1

After that, I could execute my script and everything worked like a charm! :)

peachykeen
  • 4,143
  • 4
  • 30
  • 49