Skip to content

Commit 9293858

Browse files
committed
wip
1 parent b6a70af commit 9293858

3 files changed

Lines changed: 37 additions & 8 deletions

File tree

ext/solib_bootstrap.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

libdatadog

loader/tests/functional/test_configuration_telemetry.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
assertMatchesFormat($output, '%A"loaded_by_ssi":true%s%A');
1717

1818
// Let time to write the telemetry log
19-
usleep(10000);
19+
usleep(100000);
2020

2121
$content = file_get_contents($telemetryLogPath);
2222
assertContains($content, '{"name":"instrumentation_source","value":"ssi","origin":"default","config_id":null,"seq_id":null}');

0 commit comments

Comments
 (0)