Add new function to handle vDSO

This commit is contained in:
Yasumasa Suenaga 2026-01-29 10:21:47 +09:00
parent b45ba166e8
commit 38daaa32f8

View File

@ -602,6 +602,38 @@ static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_f
return load_addr;
}
// Override vDSO path to kernel directory (/lib/modules/<version>/vdso) if possible.
// Then lib_name would be overwritten that path.
// Otherwise copy vDSO memory in coredump to temporal memory generated by memfd_create().
// Returns FD for vDSO (should be closed by caller).
static int handle_vdso(struct ps_prochandle* ph, char* lib_name, size_t lib_name_len) {
int lib_fd;
struct utsname uts;
uname(&uts);
// Check vDSO binary first (for referring debuginfo if possible).
char *vdso_path = (char*)malloc(lib_name_len);
snprintf(vdso_path, lib_name_len, "/lib/modules/%s/vdso/vdso64.so", uts.release);
if (access(vdso_path, F_OK) == 0) {
print_debug("replace vDSO: %s -> %s\n", lib_name, vdso_path);
strncpy(lib_name, vdso_path, lib_name_len);
lib_fd = pathmap_open(lib_name);
} else {
// Copy vDSO memory segment from core to temporal memory
// if vDSO binary is not available.
lib_fd = memfd_create("[vdso] in core", 0);
off64_t ofs = ph->core->vdso_offset;
if (sendfile64(lib_fd, ph->core->core_fd, &ofs, ph->core->vdso_size) == -1) {
print_debug("can't copy vDSO (%d)\n", errno);
close(lib_fd);
lib_fd = -1;
}
}
free(vdso_path);
return lib_fd;
}
// read shared library info from runtime linker's data structures.
// This work is done by librtlb_db in Solaris
static bool read_shared_lib_info(struct ps_prochandle* ph) {
@ -699,27 +731,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
if (lib_name[0] != '\0') { // ignore empty lib names
if (strcmp("linux-vdso.so.1", lib_name) == 0 ||
strcmp("linux-vdso64.so.1", lib_name) == 0) {
struct utsname uts;
uname(&uts);
// Check vDSO binary first (for referring debuginfo if possible).
char vdso_path[PATH_MAX];
snprintf(vdso_path, sizeof(vdso_path), "/lib/modules/%s/vdso/vdso64.so", uts.release);
if (access(vdso_path, F_OK) == 0) {
print_debug("replace vDSO: %s -> %s\n", lib_name, vdso_path);
strcpy(lib_name, vdso_path);
lib_fd = pathmap_open(lib_name);
} else {
// Copy vDSO memory segment from core to temporal memory
// if vDSO binary is not available.
lib_fd = memfd_create("[vdso] in core", 0);
off64_t ofs = ph->core->vdso_offset;
if (sendfile64(lib_fd, ph->core->core_fd, &ofs, ph->core->vdso_size) == -1) {
print_debug("can't copy vDSO (%d)\n", errno);
close(lib_fd);
lib_fd = -1;
}
}
lib_fd = handle_vdso(ph, lib_name, sizeof(lib_name));
} else {
lib_fd = pathmap_open(lib_name);
}