@@ -480,6 +480,7 @@ static long _syscall6(long n, long a1, long a2, long a3, long a4, long a5, long
480480#define SYS_WRITE 1
481481#define SYS_OPEN 2
482482#define SYS_CLOSE 3
483+ #define SYS_LSEEK 8
483484#define SYS_MMAP 9
484485#define SYS_MPROTECT 10
485486#define SYS_MUNMAP 11
@@ -536,6 +537,7 @@ static long _syscall6(long n, long a1, long a2, long a3, long a4, long a5, long
536537#define SYS_READ 63
537538#define SYS_OPENAT 56
538539#define SYS_CLOSE 57
540+ #define SYS_LSEEK 62
539541#define SYS_WRITE 64
540542#define SYS_SENDFILE 71
541543#define SYS_READLINKAT 78
@@ -842,12 +844,20 @@ static int create_patched_memfd(void) {
842844 if (src < 0 ) return -1 ;
843845
844846 int mfd = sys_memfd_create ("ddtrace_patched" , 0 );
845- if (mfd < 0 ) { sys_close (src ); return -1 ; }
847+ if (mfd < 0 ) {
848+ bs_fatal ("Failed to create memfd" , 123 );
849+ __builtin_unreachable ();
850+ }
846851
847852 // Copy entire file into the memfd via sendfile (in-kernel, no userspace buf)
848853 for (;;) {
849854 long n = sys_sendfile (mfd , src , 0x10000000 /*256 MB chunk*/ );
850- if (n <= 0 ) break ;
855+ if (n == 0 ) break ; /* EOF – copy complete */
856+ if (n == -4 ) continue ; /* EINTR – retry the interrupted syscall */
857+ if (n < 0 ) {
858+ bs_fatal ("Failed to copy ddtrace.so to memfd" , 122 );
859+ __builtin_unreachable ();
860+ }
851861 }
852862 sys_close (src );
853863
@@ -873,8 +883,14 @@ static int create_patched_memfd(void) {
873883 const Elf64_Dyn * dyn = (const Elf64_Dyn * )(base + dyn_vaddr );
874884
875885 uintptr_t dynsym_vaddr = 0 ;
886+ uintptr_t strtab_vaddr = 0 ;
876887 const uint32_t * hash = NULL , * gnu_hash = NULL ;
877888
889+ // Pre-pass: find DT_STRTAB (needed to look up DT_NEEDED library names)
890+ for (long i = 0 ; dyn [i ].d_tag != DT_NULL ; i ++ ) {
891+ if (dyn [i ].d_tag == DT_STRTAB ) { strtab_vaddr = dyn [i ].d_un .d_ptr ; break ; }
892+ }
893+
878894 // Pass 1: patch dynamic section tags; collect symtab/hash pointers
879895 for (long i = 0 ; dyn [i ].d_tag != DT_NULL ; i ++ ) {
880896 Elf64_Xword new_tag = 0 ;
@@ -887,10 +903,22 @@ static int create_patched_memfd(void) {
887903 // pointer, corrupting dso->ghashtab and crashing in gnu_lookup_filtered.
888904#define DT_TOMBSTONE 0x6ffffef4
889905 switch (dyn [i ].d_tag ) {
890- // Neutralize: deps, init/fini, version info, and binding flags
891- // To do so, we're gonna replace it with DT_TOMBSTONE (a value that
892- // shouldn't be recognized by the dynamic linker)
906+ // Neutralize: deps (with exceptions), init/fini, version info, binding flags.
893907 case DT_NEEDED :
908+ // Keep libgcc_s and libunwind: they provide _Unwind_RaiseException,
909+ // which Rust needs for panic handling. Without these, any Rust panic
910+ // (common in debug builds) causes SIGSEGV. All other DT_NEEDED
911+ // entries are tombstoned to prevent ld.so from loading PHP-specific
912+ // or problematic deps (e.g. ld-linux-x86-64.so.2, libcurl).
913+ if (strtab_vaddr ) {
914+ const char * libname = (const char * )(base + strtab_vaddr ) + dyn [i ].d_un .d_val ;
915+ if (bs_strncmp (libname , "libgcc_s" , 8 ) == 0 ||
916+ bs_strncmp (libname , "libunwind" , 9 ) == 0 ) {
917+ break ; /* keep this DT_NEEDED */
918+ }
919+ }
920+ new_tag = DT_TOMBSTONE ;
921+ break ;
894922 case DT_BIND_NOW :
895923 case DT_INIT :
896924 case DT_INIT_ARRAY : case DT_INIT_ARRAYSZ :
@@ -912,8 +940,9 @@ static int create_patched_memfd(void) {
912940 new_val = dyn [i ].d_un .d_val & ~1ULL ;
913941 patch_val = 1 ;
914942 break ;
915- // Track symtab and hash tables for dynsym patching
943+ // Track symtab, strtab, and hash tables for dynsym patching
916944 case DT_SYMTAB : dynsym_vaddr = dyn [i ].d_un .d_ptr ; break ;
945+ case DT_STRTAB : strtab_vaddr = dyn [i ].d_un .d_ptr ; break ;
917946 case DT_HASH : hash = (const uint32_t * )(base + dyn [i ].d_un .d_ptr ); break ;
918947 case DT_GNU_HASH : gnu_hash = (const uint32_t * )(base + dyn [i ].d_un .d_ptr ); break ;
919948 default : break ;
0 commit comments