8250750: JDK-8247515 fix for OSX pc_to_symbol() lookup fails with some symbols

Reviewed-by: sspitsyn, kevinw
This commit is contained in:
Chris Plummer 2020-08-03 16:11:41 -07:00
parent 1e535dfa53
commit d12fdfa3b7
5 changed files with 25 additions and 14 deletions

View File

@ -208,12 +208,12 @@ void Prelease(struct ps_prochandle* ph) {
free(ph);
}
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base, size_t memsz) {
return add_lib_info_fd(ph, libname, -1, base, memsz);
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
return add_lib_info_fd(ph, libname, -1, base);
}
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base, size_t memsz) {
lib_info* newlib;
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
lib_info* newlib;
print_debug("add_lib_info_fd %s\n", libname);
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
@ -229,7 +229,6 @@ lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
strcpy(newlib->name, libname);
newlib->base = base;
newlib->memsz = memsz;
if (fd == -1) {
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
@ -259,11 +258,11 @@ lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
}
#endif // __APPLE__
newlib->symtab = build_symtab(newlib->fd);
newlib->symtab = build_symtab(newlib->fd, &newlib->memsz);
if (newlib->symtab == NULL) {
print_debug("symbol table build failed for %s\n", newlib->name);
} else {
print_debug("built symbol table for 0x%lx %s\n", newlib, newlib->name);
print_debug("built symbol table for 0x%lx memsz=0x%lx %s\n", newlib, newlib->memsz, newlib->name);
}
// even if symbol table building fails, we add the lib_info.

View File

@ -36,6 +36,7 @@
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <mach-o/fat.h>
#include <mach-o/stab.h>
#ifndef register_t
#define register_t uint64_t
@ -171,11 +172,10 @@ typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lw
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
// adds a new shared object to lib list, returns NULL on failure
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base, size_t memsz);
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base);
// adds a new shared object to lib list, supply open lib file descriptor as well
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd,
uintptr_t base, size_t memsz);
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base);
sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id);
// a test for ELF signature without using libelf

View File

@ -507,7 +507,7 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
} else {
break; // Ignore non-relative paths, which are system libs. See JDK-8249779.
}
add_lib_info(ph, name, iter->vaddr, iter->memsz);
add_lib_info(ph, name, iter->vaddr);
break;
}
}

View File

@ -93,11 +93,12 @@ void build_search_table(symtab_t *symtab) {
}
// read symbol table from given fd.
struct symtab* build_symtab(int fd) {
struct symtab* build_symtab(int fd, size_t *p_max_offset) {
symtab_t* symtab = NULL;
int i, j;
mach_header_64 header;
off_t image_start;
size_t max_offset = 0;
print_debug("build_symtab\n");
if (!get_arch_off(fd, CPU_TYPE_X86_64, &image_start)) {
@ -187,6 +188,11 @@ struct symtab* build_symtab(int fd) {
if (stridx == 0 || offset == 0) {
continue; // Skip this entry. It's not a reference to code or data
}
if (lentry.n_type == N_OSO) {
// This is an object file name/path. These entries have something other than
// an offset in lentry.n_value, so we need to ignore them.
continue;
}
symtab->symbols[i].offset = offset;
symtab->symbols[i].name = symtab->strs + stridx;
symtab->symbols[i].size = strlen(symtab->symbols[i].name);
@ -195,6 +201,11 @@ struct symtab* build_symtab(int fd) {
continue; // Skip this entry. It points to an empty string.
}
// Track the maximum offset we've seen. This is used to determine the address range
// that the library covers.
if (offset > max_offset) {
max_offset = (offset + 4096) & ~0xfff; // Round up to next page boundary
}
print_debug("symbol read: %d %d n_type=0x%x n_sect=0x%x n_desc=0x%x n_strx=0x%lx offset=0x%lx %s\n",
j, i, lentry.n_type, lentry.n_sect, lentry.n_desc, stridx, offset, symtab->symbols[i].name);
i++;
@ -212,6 +223,7 @@ struct symtab* build_symtab(int fd) {
// build a hashtable for fast query
build_search_table(symtab);
*p_max_offset = max_offset;
return symtab;
quit:
if (symtab) destroy_symtab(symtab);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@
struct symtab;
// build symbol table for a given ELF or MachO file escriptor
struct symtab* build_symtab(int fd);
struct symtab* build_symtab(int fd, size_t *p_max_offset);
// destroy the symbol table
void destroy_symtab(struct symtab* symtab);