Running 32-bit executables on Dreamhost shared hosting

Dreamhost (DH) shared hosting allows running executables, including c programs that are compiled and linked by gcc. Users can compile their programs offline, or use the gcc compiler on the server. DH supports this for 64-bit executables.

However, 32-bit executables compiled with gcc using the standard switches will not run on a DH shared server. That is because 32-bit dynamic (shared) libraries are required, but these aren’t installed for DH shared hosting. For 32-bit compiled “hello.c”, ./hello produces error message: “No such file or directory”

Users can’t add the required libraries. The location of the 32-bit libraries is hard-coded into the executable as, e.g.,
/lib/i386-linux-gnu/libc.so.6
/lib is not writable by users under DH shared hosting.

Here are 3 workarounds I’ve tested. The first two involve recompiling from source code.

Option 1) Re-compile the executable as 64-bit.

This works on DH shared hosting, compiling either gcc offline or online. However, care must be taken to understand how changing the word length from 32 to 64 bits can affect pointers or math functions in the original c program.

Option 2) Re-compile the executable offline as 32-bit with static libraries.

The executable will be larger, which may not be advisable for sites with multiple executables. I have only one executable and don’t plan to add any more, so this works for me.

To compile as 32-bit, I installed the package gcc-multilib on my local 64-bit Ubuntu system. Then ran a makefile that included “-m32 -static” forcing 32-bit and static libraries. “Static” means the required functions from the c libraries are included with the stand-alone executable. No dynamic or shared libraries are required at runtime.

This option does work on the DH server.

Option 3) Don’t have source code? This will allow using a legacy 32-bit executable.

One creative blogger reported hex-editing the 32-bit executable to change the library path name to a new path with exactly the same number of characters. I found it possible to change the path in the 32-bit loader.

Notice that the loader ld-linux.so.2 is a symlink to ld-2.27.so (in Ubuntu 18.04 Bionic).
Hex-edit ld-2.27.so, beginning at offset 0x1BD61
from: /lib/i386-linux-gnu/
to: /home/DH_##abcd/l32/
Save as a different name, e.g., ld-linux.so.2.hex.

The required libraries need to be in folder “/home/DH_##abcd/l32/” on the server. A very simple “Hello World” c program uses only libc.so.6. However, in Ubuntu that file is a symlink to libc-2.27.so. Symlinks aren’t FTPd by Filezilla. Thus, libc-2.27.so needs to be copied to the server l32 folder and renamed libc.so.6. Real-world c programs will require additional libraries. Use the command “ldd” + the name of your compiled executable to see which libraries are required.

To run, SSH into the server folder containing legacy compiled 32-bit executable “hello” and the edited ld-linux.so.2.hex. Then run the loader on the “hello” executable:
./ld-linux.so.2.hex ./hello
This worked on the DH server.

Other possibilities

Run existing executable under a VPS or Dedicated server, so you can add the folder: /lib/i386-linux-gnu to your server

Another possibility that I have not validated is to change the path that’s used by the executable, to point to the required library.
A blogger suggested changing the environment variable, e.g.,
LD_LIBRARY_PATH=/home/DH_##abcd/l32/ export LD_LIBRARY_PATH
echo $LD_LIBRARY_PATH
./ld-linux.so.2 ./hello
http://taopm.sourceforge.net/docs/online_userman/UserManual_13.html
Another thought the --library-path option for the loader would work.
http://man7.org/linux/man-pages/man8/ld.so.8.html

I was not able to make either work. Since my 32-bit executable works with Option 2, I’m not investigating this further.