Skip to content

Protect patching with an open handle #1264

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

Merged
Merged
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
a210c87
#1250 validate that the obtained dlopen handle is same as the origina…
Baraa-Hasheesh Apr 24, 2025
295b14e
rename varaiable
Baraa-Hasheesh Apr 24, 2025
165cd18
Merge branch 'master' into protect-symbol-parsing
Baraa-Hasheesh Apr 25, 2025
4fc704a
Add useful doc comment
Baraa-Hasheesh Apr 25, 2025
547a727
functions for main exec, ld check, original handle
fandreuz Apr 25, 2025
4bda095
protect patches
fandreuz Apr 25, 2025
46d7a25
nn
fandreuz Apr 25, 2025
5fb3a15
nn
fandreuz Apr 25, 2025
9897f7e
remove comment
fandreuz Apr 25, 2025
08e8e05
nn
fandreuz Apr 25, 2025
1c5c9ae
fix compilation on macos
fandreuz Apr 25, 2025
0c74ccf
move include
fandreuz Apr 25, 2025
003224b
fix macos
fandreuz Apr 25, 2025
4a10fe5
nn
fandreuz Apr 25, 2025
5abfd2f
include syms
fandreuz Apr 25, 2025
5c6a2c9
stuff
fandreuz Apr 25, 2025
e6ce338
change variable under check
fandreuz Apr 25, 2025
5653968
move to cpp
fandreuz Apr 25, 2025
03d8f79
move stuff away from h
fandreuz Apr 25, 2025
ef47cb2
op
fandreuz Apr 25, 2025
b2b8b68
known lib crash nativemem
fandreuz Apr 25, 2025
cc0b9d9
spurious bracket
fandreuz Apr 25, 2025
efae089
nn
fandreuz Apr 25, 2025
1feaf12
nn
fandreuz Apr 25, 2025
19a552c
Update test/test/nativemem/nativemem_known_lib_crash.c
fandreuz Apr 25, 2025
dbb4d67
nn
fandreuz Apr 28, 2025
79d93a0
raii
fandreuz Apr 28, 2025
108598c
Merge remote-tracking branch 'fandreuz/sim-294-keep-handle-while-patc…
fandreuz Apr 28, 2025
85d2ebb
isvalid
fandreuz Apr 28, 2025
964d025
const. import
fandreuz Apr 28, 2025
aa02f9e
move dtor away
fandreuz Apr 28, 2025
842e2da
move ctor
fandreuz Apr 28, 2025
92944da
move ass. delete cp
fandreuz Apr 28, 2025
a38d144
nn
fandreuz Apr 28, 2025
683825d
Merge branch 'master' into sim-294-keep-handle-while-patching
fandreuz Apr 28, 2025
c2e56c8
needed import
fandreuz Apr 28, 2025
3dd17e6
rename
fandreuz Apr 29, 2025
646cbf7
Merge branch 'master' into sim-294-keep-handle-while-patching
fandreuz Apr 29, 2025
5378fcf
move 'makeUnloadProtection' into UP ctor
fandreuz Apr 29, 2025
b479c11
fix test for alpine
fandreuz Apr 29, 2025
2c69485
move make imports patchable
fandreuz Apr 29, 2025
d837bc9
set flag
fandreuz Apr 29, 2025
20f5f81
cc
fandreuz Apr 29, 2025
79da179
nn
fandreuz Apr 29, 2025
457d59a
Merge branch 'master' into sim-294-keep-handle-while-patching
fandreuz Apr 30, 2025
fa529c8
Merge branch 'master' into sim-294-keep-handle-while-patching
fandreuz May 1, 2025
15eeade
use image_base
fandreuz May 1, 2025
d58c662
Update test/test/nativemem/nativemem_known_lib_crash.c
fandreuz May 1, 2025
cda6051
stop ap
fandreuz May 1, 2025
a6b3804
log
fandreuz May 1, 2025
bc30666
Revert "use image_base"
fandreuz May 1, 2025
bc19fc3
remove tood
fandreuz May 1, 2025
15da753
trigger
fandreuz May 1, 2025
14a8a55
trigger
fandreuz May 1, 2025
8de5e01
debug
fandreuz May 2, 2025
8f57df7
unloadprotection to symbols
fandreuz May 2, 2025
1edc7f6
missing image base
fandreuz May 2, 2025
4e5fb57
nn
fandreuz May 2, 2025
5cff23d
clean lib name
fandreuz May 2, 2025
50ead5b
Merge branch 'master' into sim-294-keep-handle-while-patching
fandreuz May 2, 2025
0eacfab
cc
fandreuz May 2, 2025
7cdfa80
nn
fandreuz May 2, 2025
b310dba
move patchimprot
fandreuz May 2, 2025
fa729eb
nn
fandreuz May 2, 2025
c17d592
cc
fandreuz May 2, 2025
94dd779
quote
fandreuz May 2, 2025
7d4cb93
trigger
fandreuz May 2, 2025
45e9622
check musl
fandreuz May 2, 2025
b5d4e19
inline
fandreuz May 7, 2025
5e10cdd
use the stuff on macos
fandreuz May 7, 2025
70c3800
patch from cc
fandreuz May 7, 2025
4542d1d
trigger
fandreuz May 7, 2025
2abe2aa
nn
fandreuz May 7, 2025
8974647
no cleanname
fandreuz May 7, 2025
dcd97c7
missing const
fandreuz May 7, 2025
1d049c5
nn
fandreuz May 10, 2025
7a1895a
stack-allocated
fandreuz May 10, 2025
7e575b4
stuff
fandreuz May 14, 2025
6f3e498
fix
fandreuz May 14, 2025
42879e3
bara's fix
fandreuz May 14, 2025
2e1c15b
cc
fandreuz May 14, 2025
a5c24b0
ops
fandreuz May 14, 2025
7e0a452
new stuff
fandreuz May 14, 2025
703950b
trigger
fandreuz May 14, 2025
1e83770
Merge branch 'coredump-gha' into sim-294-keep-handle-while-patching
fandreuz May 14, 2025
ff43185
test fix
fandreuz May 15, 2025
b220a20
comment
fandreuz May 15, 2025
a7103d0
op
fandreuz May 15, 2025
4d5645f
not here
fandreuz May 16, 2025
873ce86
dlinfo+dladdr
fandreuz May 16, 2025
ffdeb52
revert
fandreuz May 16, 2025
01fc8eb
review comments
fandreuz May 16, 2025
017ff0d
nn
fandreuz May 16, 2025
30364f0
initialize when needed
fandreuz May 16, 2025
9ae2c0f
cc
fandreuz May 19, 2025
7acb726
no dwarf
fandreuz May 19, 2025
d93698b
nn
fandreuz May 19, 2025
00ac27e
amend comment
fandreuz May 19, 2025
41d89d1
rename isValidHandle
fandreuz May 19, 2025
9191dc2
Cleanup
apangin May 20, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/test-and-publish-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ jobs:
name: ubuntu-latest
java-version: [11, 17, 21, 24]
java-distribution: [corretto]
image: [public.ecr.aws/async-profiler/asprof-builder-x86:latest]
image: ["public.ecr.aws/async-profiler/asprof-builder-x86:latest"]
include:
- runson:
display: macos-arm64
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ build-test-bins:
$(CC) -o $(TEST_BIN_DIR)/native_api -Isrc test/test/c/native_api.c -ldl
$(CC) -o $(TEST_BIN_DIR)/profile_with_dlopen -Isrc test/test/nativemem/profile_with_dlopen.c -ldl
$(CC) -o $(TEST_BIN_DIR)/preload_malloc -Isrc test/test/nativemem/preload_malloc.c -ldl
$(CC) -o $(TEST_BIN_DIR)/nativemem_known_lib_crash -Isrc test/test/nativemem/nativemem_known_lib_crash.c -ldl
$(CXX) -o $(TEST_BIN_DIR)/non_java_app $(INCLUDES) $(CPP_TEST_INCLUDES) test/test/nonjava/non_java_app.cpp $(LIBS)

test-cpp: build-test-cpp
Expand Down
11 changes: 9 additions & 2 deletions src/codeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,18 @@ size_t NativeFunc::usedMemory(const char* name) {


CodeCache::CodeCache(const char* name, short lib_index, bool imports_patchable,
const void* min_address, const void* max_address) {
const void* min_address, const void* max_address,
const char* image_base) {
_name = NativeFunc::create(name, -1);

// Strip " (deleted)" suffix so that removed library can be reopened
size_t len = strlen(name);

_lib_index = lib_index;
_min_address = min_address;
_max_address = max_address;
_text_base = NULL;
_image_base = image_base;

_plt_offset = 0;
_plt_size = 0;
Expand Down Expand Up @@ -234,7 +240,6 @@ void CodeCache::addImport(void** entry, const char* name) {
void** CodeCache::findImport(ImportId id) {
if (!_imports_patchable) {
makeImportsPatchable();
_imports_patchable = true;
}
return _imports[id][PRIMARY];
}
Expand Down Expand Up @@ -270,6 +275,8 @@ void CodeCache::makeImportsPatchable() {
uintptr_t patch_end = (uintptr_t)max_import & ~OS::page_mask;
mprotect((void*)patch_start, patch_end - patch_start + OS::page_size, PROT_READ | PROT_WRITE);
}

_imports_patchable = true;
}

void CodeCache::setDwarfTable(FrameDesc* table, int length) {
Expand Down
12 changes: 11 additions & 1 deletion src/codeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,18 @@ class CodeBlob {

class FrameDesc;

class UnloadProtection;

class CodeCache {
friend UnloadProtection;

private:
char* _name;
short _lib_index;
const void* _min_address;
const void* _max_address;
const char* _text_base;
const char* _image_base;

unsigned int _plt_offset;
unsigned int _plt_size;
Expand All @@ -131,7 +136,8 @@ class CodeCache {
short lib_index = -1,
bool imports_patchable = false,
const void* min_address = NO_MIN_ADDRESS,
const void* max_address = NO_MAX_ADDRESS);
const void* max_address = NO_MAX_ADDRESS,
const char* image_base = NULL);

~CodeCache();

Expand All @@ -147,6 +153,10 @@ class CodeCache {
return _max_address;
}

const char* imageBase() const {
return _image_base;
}

bool contains(const void* address) const {
return address >= _min_address && address < _max_address;
}
Expand Down
6 changes: 6 additions & 0 deletions src/hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "cpuEngine.h"
#include "mallocTracer.h"
#include "profiler.h"
#include "symbols.h"


#define ADDRESS_OF(sym) ({ \
Expand Down Expand Up @@ -182,6 +183,11 @@ void Hooks::patchLibraries() {

while (_patched_libs < native_lib_count) {
CodeCache* cc = (*native_libs)[_patched_libs++];
UnloadProtection handle(cc);
if (!handle.isValid()) {
continue;
}

if (!cc->contains((const void*)Hooks::init)) {
// Let libasyncProfiler always use original dlopen
cc->patchImport(im_dlopen, (void*)dlopen_hook);
Expand Down
7 changes: 6 additions & 1 deletion src/mallocTracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "os.h"
#include "profiler.h"
#include "tsc.h"
#include "symbols.h"
#include <dlfcn.h>
#include <string.h>

Expand Down Expand Up @@ -120,12 +121,16 @@ void MallocTracer::patchLibraries() {

while (_patched_libs < native_lib_count) {
CodeCache* cc = (*native_libs)[_patched_libs++];

if (cc->contains((const void*)MallocTracer::initialize)) {
// Let libasyncProfiler always use original allocation methods
continue;
}

UnloadProtection handle(cc);
if (!handle.isValid()) {
continue;
}

cc->patchImport(im_malloc, (void*)malloc_hook);
cc->patchImport(im_realloc, (void*)realloc_hook);
cc->patchImport(im_free, (void*)free_hook);
Expand Down
14 changes: 14 additions & 0 deletions src/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ class Symbols {
}
};

class UnloadProtection {
private:
void* _lib_handle;
bool _valid;

public:
UnloadProtection(const CodeCache *cc);
~UnloadProtection();

UnloadProtection& operator=(const UnloadProtection& other) = delete;

bool isValid() const { return _valid; }
};

#endif // _SYMBOLS_H
109 changes: 72 additions & 37 deletions src/symbols_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <elf.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <link.h>
#include <linux/limits.h>
#include <sys/auxv.h>
#include <link.h>
#include "symbols.h"
#include "dwarf.h"
#include "fdtransferClient.h"
Expand Down Expand Up @@ -52,8 +52,11 @@ static void applyPatch(CodeCache* cc) {
if (patch_libnet) {
size_t len = strlen(cc->name());
if (len >= 10 && strcmp(cc->name() + len - 10, "/libnet.so") == 0) {
cc->patchImport(im_poll, (void*)poll_hook);
patch_libnet = false;
UnloadProtection handle(cc);
if (handle.isValid()) {
cc->patchImport(im_poll, (void*)poll_hook);
patch_libnet = false;
}
}
}
}
Expand All @@ -64,6 +67,25 @@ static void applyPatch(CodeCache* cc) {}

#endif

static const void* getMainPhdr() {
void* main_phdr = NULL;
dl_iterate_phdr([](struct dl_phdr_info* info, size_t size, void* data) {
*(const void**)data = info->dlpi_phdr;
return 1;
}, &main_phdr);
return main_phdr;
}

static const void* _main_phdr = getMainPhdr();
static const char* _ld_base = (const char*)getauxval(AT_BASE);

static bool isMainExecutable(const char* image_base, const void* map_end) {
return _main_phdr != NULL && _main_phdr >= image_base && _main_phdr < map_end;
}

static bool isLoader(const char* image_base) {
return _ld_base != NULL && _ld_base == image_base;
}

class SymbolDesc {
private:
Expand Down Expand Up @@ -754,6 +776,14 @@ static void collectSharedLibraries(std::unordered_map<u64, SharedLibrary>& libs,
fclose(f);
}

// Strip " (deleted)" suffix so that removed library can be reopened
void stripDeletedSuffix(char* name) {
size_t len = strlen(name);
if (len > 10 && strcmp(name + len - 10, " (deleted)") == 0) {
name[len - 10] = 0;
}
}

void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
MutexLocker ml(_parse_lock);

Expand All @@ -776,29 +806,13 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
std::unordered_map<u64, SharedLibrary> libs;
collectSharedLibraries(libs, MAX_NATIVE_LIBS - array->count());

const char* ld_base = (const char*)getauxval(AT_BASE);
if (!ld_base) {
Log::warn("Cannot determine base address of the loader");
}

const void* main_phdr = NULL;
dl_iterate_phdr([](struct dl_phdr_info* info, size_t size, void* data) {
*(const void**)data = info->dlpi_phdr;
return 1;
}, &main_phdr);

for (auto& it : libs) {
u64 inode = it.first;
_parsed_inodes.insert(inode);

SharedLibrary& lib = it.second;
CodeCache* cc = new CodeCache(lib.file, array->count(), false, lib.map_start, lib.map_end);

// Strip " (deleted)" suffix so that removed library can be reopened
size_t len = strlen(lib.file);
if (len > 10 && strcmp(lib.file + len - 10, " (deleted)") == 0) {
lib.file[len - 10] = 0;
}
CodeCache* cc = new CodeCache(lib.file, array->count(), false, lib.map_start, lib.map_end, lib.image_base);
stripDeletedSuffix(lib.file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the original file has been deleted, I don't think we should attempt to parse a file with the similar name, because it can be a different file with different symbol layout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand, this seems to be replicating the original logic. Do you propose to skip parsing the library if the original file was deleted?


if (strchr(lib.file, ':') != NULL) {
// Do not try to parse pseudofiles like anon_inode:name, /memfd:name
Expand All @@ -812,24 +826,10 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
// Parse debug symbols first
ElfParser::parseFile(cc, lib.image_base, lib.file, true);

dlerror(); // reset any error from previous dl function calls

// Protect library from unloading while parsing in-memory ELF program headers.
// Also, dlopen() ensures the library is fully loaded.
// Main executable and ld-linux interpreter cannot be dlopen'ed, but dlerror() returns NULL for them on some systems.
void* handle = dlopen(lib.file, RTLD_LAZY | RTLD_NOLOAD);

// Parse main executable and the loader (ld.so) regardless of dlopen result, since they cannot be unloaded.
bool is_main_exe = main_phdr >= lib.image_base && main_phdr < lib.map_end;
bool is_loader = ld_base == lib.image_base;

if (handle != NULL || is_main_exe || is_loader) {
UnloadProtection handle(cc);
if (handle.isValid()) {
ElfParser::parseProgramHeaders(cc, lib.image_base, lib.map_end, OS::isMusl());
}

if (handle != NULL) {
dlclose(handle);
}
}

free(lib.file);
Expand All @@ -845,4 +845,39 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
}
}

static bool isValidHandle(const CodeCache* cc, void* handle) {
struct link_map* map;
// validate that the current loaded library is the same library that was observed during the /proc/self/maps processing
if (handle != NULL && dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0) {
return cc->imageBase() == (const char*)map->l_addr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this apply to shared objects whose virtual load address is non-zero?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, I think @Baraa-Hasheesh looked into this as part of #1261. Can you weigh in?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@apangin yes.
Is there a case where the virtual load address is zero?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm interested in a situation where a shared object has PT_LOAD program header with p_offset == 0 and p_vaddr != 0. Can you provide me with an evidence that this case is covered or that it never happens?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@apangin I will investigate this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dlinfo protection is only really needed if library is re-opened using a different thread after close

No, the problem can happen even in a single-threaded cases, for instance, if we attempt to do native memory profiling long after a library was first parsed.

I do think we need some level of protection against this situation, even if it is not 100% accurate. If comparing l_addr does not work, maybe we can check l_ld instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@apangin technically that's true but it will require that the library is reloaded into a different location in memory (could happen in JIT from what I'm reading)

But this raises the concern that the library will not be patched (skipped) or loose it's patching during these long profile sessions (profiling accuracy degrades with time) while being a valid behavior of the profiled process (Different issue that can be tracked separately)

Copy link
Contributor

@Baraa-Hasheesh Baraa-Hasheesh May 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fandreuz @apangin

How about we drop the dlinfo & switch to dladdr
https://man7.org/linux/man-pages/man3/dladdr.3.html

void *dli_fbase;  /* Base address at which shared object is loaded */

We can use the _imports inside the CodeCache to find an address to be used in the dladdr call
I.E. when we save imports during symbol parsing we set a pointer to the first symbol we find (Avoid double looping)

We use that pointer to call dladdr

Dl_info dl_info;
if (dladdr(entry, &dl_info)) {
 // Check that dl_info. dli_fbase == image_base
}

This solution should be also applicable to MacOs

Note: I initially didn't consider dladdr as you need an address in the lib to call it & missed the fact we already have the address inside _imports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just note that this is only valid on the patching side, while the mentioned case here will still be possible if lib was relocated after it was detected but before it was parsed

I think it's best if we have the dladdr side on the patching side as it should also protect MacOs

For the parsing side, for now I think it should be an acceptable risk & we can create a different thread to track & reproduce the possible crash

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bara's fix was implemented in 42879e3

}
return false;
}

UnloadProtection::UnloadProtection(const CodeCache *cc) {
_lib_handle = NULL;
_valid = false;

if (OS::isMusl() || isMainExecutable(cc->imageBase(), cc->maxAddress()) || isLoader(cc->imageBase())) {
_valid = true;
return;
}

char* nameCopy = strdup(cc->name());
stripDeletedSuffix(nameCopy);

// Protect library from unloading while parsing in-memory ELF program headers.
// Also, dlopen() ensures the library is fully loaded.
_lib_handle = dlopen(nameCopy, RTLD_LAZY | RTLD_NOLOAD);
_valid = isValidHandle(cc, _lib_handle);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not the best name, IMO.
Any non-null handle is valid, but what we really check here is whether it is the same shared library that was seen at CodeCache creation time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • checkHandleConsistency
  • isHandleConsistent

I'll think about it, let me know if you have any preference

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


free(nameCopy);
}

UnloadProtection::~UnloadProtection() {
if (_lib_handle != NULL) {
dlclose(_lib_handle);
}
}

#endif // __linux__
34 changes: 20 additions & 14 deletions src/symbols_macos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
#include "symbols.h"
#include "log.h"

UnloadProtection::UnloadProtection(const CodeCache *cc) {
// Protect library from unloading while parsing in-memory ELF program headers.
// Also, dlopen() ensures the library is fully loaded.
_lib_handle = dlopen(cc->name(), RTLD_LAZY | RTLD_NOLOAD);
_valid = _lib_handle != NULL;
}

UnloadProtection::~UnloadProtection() {
if (_lib_handle != NULL) {
dlclose(_lib_handle);
}
}

class MachOParser {
private:
Expand Down Expand Up @@ -152,22 +164,16 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
}

const char* path = _dyld_get_image_name(i);

// Protect the library from unloading while parsing symbols
void* handle = dlopen(path, RTLD_LAZY | RTLD_NOLOAD);
if (handle == NULL) {
continue;
}

CodeCache* cc = new CodeCache(path, count, true);
MachOParser parser(cc, image_base);
if (!parser.parse()) {
Log::warn("Could not parse symbols from %s", path);
UnloadProtection handle(cc);
if (handle.isValid()) {
MachOParser parser(cc, image_base);
if (!parser.parse()) {
Log::warn("Could not parse symbols from %s", path);
}
cc->sort();
array->add(cc);
}
dlclose(handle);

cc->sort();
array->add(cc);
}
}

Expand Down
6 changes: 6 additions & 0 deletions test/test/nativemem/NativememTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,10 @@ public void preloadMalloc(TestProcess p) throws Exception {

Assert.isEqual(sizeCounts.getOrDefault((long) MALLOC_SIZE, 0L), 1);
}

@Test(os = Os.LINUX, sh = "%testbin/nativemem_known_lib_crash %f.jfr", output = true, env = {"LD_LIBRARY_PATH=build/test/lib:build/lib"})
public void nativememKnownLibCrash(TestProcess p) throws Exception {
p.waitForExit();
Assert.isEqual(p.exitCode(), 0);
}
}
Loading
Loading