Skip to content

8355047: SA fails to discover JDK libraries for Linux core files #25861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@

#define SA_ALTROOT "SA_ALTROOT"

// variables used for remapping file names
static const char* _remap_from;
static const char* _remap_to;
static int _remap_from_length = -1;

void pathmap_remap(const char* remap_from, const char* remap_to, int remap_from_length) {
_remap_from = remap_from;
_remap_to = remap_to;
_remap_from_length = remap_from_length;
}

int pathmap_open(const char* name) {
static const char *alt_root = NULL;
static int alt_root_initialized = 0;
Expand All @@ -47,6 +58,21 @@ int pathmap_open(const char* name) {
alt_root = getenv(SA_ALTROOT);
}

if (_remap_from_length != -1 &&
memcmp(name, _remap_from, _remap_from_length) == 0) {
// try to remap the path
char remapped_name[PATH_MAX];
int result = snprintf(remapped_name, PATH_MAX, "%s%s",
_remap_to, &name[_remap_from_length]);
if (result < PATH_MAX) {
int lib_fd = open(remapped_name, O_RDONLY);
if (lib_fd >= 0) {
print_debug("remapped %s to %s\n", name, remapped_name);
return lib_fd;
}
}
}

if (alt_root == NULL) {
return open(name, O_RDONLY);
}
Expand Down
2 changes: 2 additions & 0 deletions src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ struct core_data {
// part of the class sharing workaround
map_info* class_share_maps;// class share maps in a linked list
map_info** map_array; // sorted (by vaddr) array of map_info pointers
char exec_path[PATH_MAX]; // file name java
};

struct ps_prochandle {
Expand All @@ -118,6 +119,7 @@ struct ps_prochandle {
extern "C" {
#endif

void pathmap_remap(const char* remap_from, const char* remap_to, int remap_from_length);
int pathmap_open(const char* name);

void print_debug(const char* format,...);
Expand Down
82 changes: 82 additions & 0 deletions src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ static bool core_handle_prstatus(struct ps_prochandle* ph, const char* buf, size

#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))

#ifndef NT_FILE
#define NT_FILE 0x46494c45
#endif

// read NT_PRSTATUS entries from core NOTE segment
static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) {
char* buf = NULL;
Expand Down Expand Up @@ -300,6 +304,81 @@ static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) {
}
auxv++;
}
} else if (notep->n_type == NT_FILE) {
/*
NT_FILE section contains all file locations that were memory-mapped,
including the executable file. If the executable file location
in the NT_FILE note does not match --exe, we will rewrite the locations
of other files we load at a later stage.

For example, if --exe is ~/jdk/bin/java, but NT_FILE is /opt/jdk/bin/java,
we will detect the common suffix (jdk/bin/java), and will later rewrite
the prefix /opt/ to ~/, for example
/opt/jdk/lib/server/libjvm.so will be rewritten to ~/jdk/lib/server/libjvm.so.
*/

// variables used for remapping file names
static char remap_from[PATH_MAX];
static char remap_to[PATH_MAX];
static int remap_from_length;

long file_count = *(long*) descdata;

int filename_offset = (3 * file_count + 2) * sizeof(long);

const char* exename = ph->core->exec_path;
int exelen = strlen(exename);

for (int i = 0; i < file_count; i++) {
// iterate over the mapped files, find file name matching the exename
char* mapped_file_name = &descdata[filename_offset];
int filelen;
if (filename_offset >= notep->n_descsz ||
(filelen = strnlen(mapped_file_name, notep->n_descsz - filename_offset)) >=
MIN(PATH_MAX, notep->n_descsz - filename_offset)) {
print_debug("Malformed NT_FILE section, ignore\n");
break;
} else {
print_debug("Mapped file location: %s\n", mapped_file_name);

// Try to find a common suffix between the original
// and the current file path
int maxchars = MIN(exelen, filelen);
int lastslash = -1;

for (int i = 1; i <= maxchars; i++) {
if (exename[exelen - i] != mapped_file_name[filelen - i]) {
break;
}
if (exename[exelen - i] == '/') {
lastslash = i;
}
}
if (lastslash == exelen && filelen == exelen) {
print_debug("Exe file matches core file, will not remap\n");
break;
} else if (lastslash != -1) {
int fd = pathmap_open(mapped_file_name);
if (fd >= 0) {
print_debug("Mapped file opened successfully, will not remap\n");
close(fd);
break;
}
remap_from_length = filelen - lastslash + 1;
memcpy(remap_from, mapped_file_name, remap_from_length);
remap_from[remap_from_length] = '\0';
int remap_to_length = exelen - lastslash + 1;
memcpy(remap_to, exename, remap_to_length);
remap_to[remap_to_length] = '\0';

print_debug("Found common suffix, will remap %s to %s\n", remap_from, remap_to);
pathmap_remap(remap_from, remap_to, remap_from_length);
break;
}
}
// move to next file path
filename_offset += filelen + 1;
}
}
p = descdata + ROUNDUP(notep->n_descsz, 4);
}
Expand Down Expand Up @@ -770,6 +849,9 @@ Pgrab_core(const char* exec_file, const char* core_file) {
ph->core->exec_fd = -1;
ph->core->interp_fd = -1;

strncpy(ph->core->exec_path, exec_file, sizeof(ph->core->exec_path));
ph->core->exec_path[sizeof(ph->core->exec_path) - 1] = '\0';

// open the core file
if ((ph->core->core_fd = open(core_file, O_RDONLY)) < 0) {
print_error("can't open core file: %s\n", strerror(errno));
Expand Down