Linux executable lazy loading

I implemented the custom linker script but unfortunately the executable still gets undefined symbol errors on running. Is it possible that the linker arguments aren't enough to override the rust -Zrelro-level? Is there any way I can check in the ELF header part of the file?

cc -m64 /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.13p9e1ntyogo9xsq.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.1iij31zcahtqtiv5.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.1l6169r8k8eut7l2.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.2gjar0q85zo53a76.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.2k238mae54tufgj9.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.2khfd30djo2j9kj2.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.30j9pt2j18mofsvb.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.3aliuipsukidwcp1.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.3hccpq6246r15ccj.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.3mblox8452khn7gt.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.3t4cjyhj779kk0qr.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.3zuhas95lhzq610q.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.45wlivfnv8f4n4m0.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.4d3znlnisojq460.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.4kfpl27e23y5yblb.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.4tsmg47mo9ot09rg.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.56udpy3ecn6gwk3v.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.5a3amov6yy7wfscc.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.5cf61klwqdixyzvj.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.5orcigdhwyefptr.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.9x7slzthbld3jn.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.cde9lw0m0vpja0a.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.gzsb73e5bh99x9g.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.lphb1hwcx9397qd.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.q46zvmgwxroxyjw.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.uov2smtu6r3uncy.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.y30a08oijsqtlo9.rcgu.o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91.1lyc4h18v76f6y14.rcgu.o -Wl,--as-needed -L /USERHOME/CODEDIR/target/debug/deps -L /LIBDIR -L /usr/lib/x86_64-linux-gnu -L /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib -lae -lbom -lepm -lfclasses -lform -ltcinit -ltc -ltccore -lbase_utils -lps -lpublication -lqry -lres -lsa -ltcsoaprojectmanagement -lcfilter -lstdc++ -Wl,--start-group -Wl,-Bstatic /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-008055cc7d873802.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-06f01ac2578bda94.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-f9a3c3274a1835e0.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-d4cbb754ee9f4daa.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-95c14e1c1e3ebcc4.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-d489f0ca872880cc.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-75f07df0b18fea39.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-0c35b278736219a2.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-e530649c9a06e3c6.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-6b148909d375a785.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-cd15fa647f4775d1.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-74be3a703f788ba2.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-8f2c5b445c28b2e3.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-8480e85e0be96197.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-ac23a75f6f42004e.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-557ba8776e04d182.rlib /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-4beb03d03503c439.rlib -Wl,--end-group /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-dd7db1bec6909f24.rlib -Wl,-Bdynamic -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc -Wl,--eh-frame-hdr -Wl,-znoexecstack -L /USERHOME/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib -o /USERHOME/CODEDIR/target/debug/deps/tclogin-3aa5bdb40b601d91 -Wl,--gc-sections -nodefaultlibs -Wl,--unresolved-symbols=ignore-all -Wl,-znorelro -Wl,-zlazy

Script:

#!/bin/bash

declare -a FILTERARGS
for ITEM in "$@"
do
    # if [[ "$ITEM" != "-Wl,-znow" && "$ITEM" != "-Wl,-zrelro" ]]; then
    #    FILTERARGS+=("$ITEM")
    # fi
    case "$ITEM" in
    -Wl,-znow|-Wl,-zrelro)
        # do nothing
        ;;
    *)
       FILTERARGS+=("$ITEM")
        ;;
    esac
done

echo "invoking: cc ${FILTERARGS[@]}"
cc ${FILTERARGS[@]}

You can use readelf -l and then check if there is a GNU_RELRO program header. Also check if readelf -d shows BIND_NOW or Flags: NOW.

I downloaded Rust nightly and attempted a build but got an error:

-bash-4.2$ cargo --version
cargo 1.57.0-nightly (d56b42c54 2021-09-27)
-bash-4.2$ RUSTC_LOG=info cargo build -Zrelro-level=off
error: unknown `-Z` flag specified: relro-level

Below is the information from readelf on the Rust binary which will still not run and the C binary which runs as expected. As you can see, the Rust binary now does not show BIND_NOW but I am still getting undefined symbol errors when launching the Rust binary but not the C binary.

Rust readelf -d:

 0x000000000000000c (INIT)               0x405530
 0x000000000000000d (FINI)               0x435f40
 0x0000000000000019 (INIT_ARRAY)         0x643000
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x643010
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x401a20
 0x0000000000000006 (SYMTAB)             0x4006b8
 0x000000000000000a (STRSZ)              9597 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x645c80
 0x0000000000000002 (PLTRELSZ)           120 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x4054b8
 0x0000000000000007 (RELA)               0x404240
 0x0000000000000008 (RELASZ)             4728 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x404140
 0x000000006fffffff (VERNEEDNUM)         6
 0x000000006ffffff0 (VERSYM)             0x403f9e
 0x0000000000000000 (NULL)               0x0

Rust readelf -l

Elf file type is EXEC (Executable file)
Entry point 0x407c18
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000042200 0x0000000000042200  R E    200000
  LOAD           0x0000000000043000 0x0000000000643000 0x0000000000643000
                 0x0000000000002d08 0x0000000000002ed0  RW     200000
  DYNAMIC        0x0000000000045390 0x0000000000645390 0x0000000000645390
                 0x00000000000002c0 0x00000000000002c0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  TLS            0x0000000000043000 0x0000000000643000 0x0000000000643000
                 0x0000000000000000 0x0000000000000078  R      10
  GNU_EH_FRAME   0x000000000003afa4 0x000000000043afa4 0x000000000043afa4
                 0x0000000000001004 0x0000000000001004  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .debug_gdb_scripts .eh_frame_hdr .eh_frame .gcc_except_table
   03     .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .tbss
   07     .eh_frame_hdr
   08

C readelf -d

 0x000000000000000c (INIT)               0x401220
 0x000000000000000d (FINI)               0x4016e4
 0x0000000000000019 (INIT_ARRAY)         0x602428
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x602430
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x400520
 0x0000000000000006 (SYMTAB)             0x4002e0
 0x000000000000000a (STRSZ)              2777 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x603000
 0x0000000000000002 (PLTRELSZ)           264 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x401118
 0x0000000000000007 (RELA)               0x4010a0
 0x0000000000000008 (RELASZ)             120 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x401030
 0x000000006fffffff (VERNEEDNUM)         3
 0x000000006ffffff0 (VERSYM)             0x400ffa
 0x0000000000000000 (NULL)               0x0

C readelf -l

Elf file type is EXEC (Executable file)
Entry point 0x401300
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000001a78 0x0000000000001a78  R E    200000
  LOAD           0x0000000000002428 0x0000000000602428 0x0000000000602428
                 0x0000000000000c68 0x0000000000000c78  RW     200000
  DYNAMIC        0x0000000000002450 0x0000000000602450 0x0000000000602450
                 0x0000000000000ba0 0x0000000000000ba0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x0000000000001878 0x0000000000401878 0x0000000000401878
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
  GNU_RELRO      0x0000000000002428 0x0000000000602428 0x0000000000602428
                 0x0000000000000bd8 0x0000000000000bd8  R      1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table
   03     .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .init_array .fini_array .jcr .data.rel.ro .dynamic .got

-Zrelro-level=off is a rustc flag so it needs to be in rustflags. Bases on the rest of the post it seems that you have successfully disabled RELRO though.

This is pretty strange. I would have expected it to work without BIND_NOW. I'm afraid I can't help further.

A few days ago I submitted a Rust issue: Rust program using Linux C library links but fails to run · Issue #89751 · rust-lang/rust · GitHub but so far no one has looked at it yet.

Finally found the resolution to the issue. I had to update the linker script to also remove -Wl,--as-needed along with the other options and that allowed it to run.

BTW instead of the linker wrapper hack, can you maybe just use crate-type = ["staticlib"] and then use ld to link the resulting lib$crate.a to an executable with whatever parameters you wish? That's what I did for one project that had special linking requirements.