Skip to content
Merged
Prev Previous commit
Next Next commit
Use root symbols
  • Loading branch information
jbachorik committed Mar 25, 2025
commit 4882ffd8e2545a1bd2c9f2dade0889f1178d397d
12 changes: 4 additions & 8 deletions ddprof-lib/src/main/cpp/stackWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "profiler.h"
#include "safeAccess.h"
#include "stackFrame.h"
#include "symbols.h"
#include "vmStructs.h"

#include <ucontext.h>
Expand Down Expand Up @@ -288,9 +289,6 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
NMethod *nm = CodeHeap::findNMethod(pc);
if (nm == NULL) {
fillErrorFrame(frames[depth++], "unknown_nmethod", truncated);
// we are somewhere in JVM code heap and have no idea what is this frame
// might be good to bail out since it would be a challenge to unwind properly?
break;
} else {
if (nm->isNMethod()) {
int level = nm->level();
Expand Down Expand Up @@ -485,11 +483,9 @@ int StackWalker::walkVM(void* ucontext, ASGCT_CallFrame* frames, int max_depth,
const char *name = cc == NULL ? NULL : cc->binarySearch(pc);

fillFrame(frames[depth++], BCI_NATIVE_FRAME, name);
// _start should be the process entry point; any attempt to unwind from there will fail
if (name) {
if (!strcmp("_start", name) || !strcmp("start_thread", name) || !strcmp("_ZL19thread_native_entryP6Thread", name) || !strcmp("_thread_start", name) || !strcmp("thread_start", name)) {
break;
}

if (Symbols::isRootSymbol(pc)) {
break;
}
prev_pc = pc;
}
Expand Down
3 changes: 3 additions & 0 deletions ddprof-lib/src/main/cpp/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class Symbols {
// There are internal caches that are not associated to the array
static void clearParsingCaches();
static bool haveKernelSymbols() { return _have_kernel_symbols; }

// Some symbols are always roots - eg. no unwinding should be attempted once they are encountered
static bool isRootSymbol(const void* address);
};

#endif // _SYMBOLS_H
37 changes: 34 additions & 3 deletions ddprof-lib/src/main/cpp/symbols_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define _FILE_OFFSET_BITS 64
#include <unistd.h>

uintptr_t ElfParser::_root_symbols[LAST_ROOT_SYMBOL_KIND] = {0};

ElfSection *ElfParser::findSection(uint32_t type, const char *name) {
if (_header == NULL) {
return NULL;
Expand Down Expand Up @@ -348,6 +350,26 @@ void ElfParser::loadSymbols(bool use_debug) {
}
}

void ElfParser::addSymbol(const void *start, int length, const char *name, bool update_bounds) {
_cc->add(start, length, name, update_bounds);
if (!strcmp("_start", name)) {
Comment thread
jbachorik marked this conversation as resolved.
Outdated
TEST_LOG("===> found _start");
_root_symbols[_start] = (uintptr_t)start;
} else if (!strcmp("start_thread", name)) {
TEST_LOG("===> found start_thread");
_root_symbols[start_thread] = (uintptr_t)start;
} else if (!strcmp("_ZL19thread_native_entryP6Thread", name)) {
TEST_LOG("===> found _ZL19thread_native_entryP6Thread");
_root_symbols[_ZL19thread_native_entryP6Thread] = (uintptr_t)start;
} else if (!strcmp("_thread_start", name)) {
TEST_LOG("===> found _thread_start");
_root_symbols[_thread_start] = (uintptr_t)start;
} else if (!strcmp("thread_start", name)) {
TEST_LOG("===> found thread_start");
_root_symbols[thread_start] = (uintptr_t)start;
}
}

// Load symbols from /usr/lib/debug/.build-id/ab/cdef1234.debug, where
// abcdef1234 is Build ID
bool ElfParser::loadSymbolsUsingBuildId() {
Expand Down Expand Up @@ -427,8 +449,7 @@ void ElfParser::loadSymbolTable(const char *symbols, size_t total_size,
// Skip special AArch64 mapping symbols: $x and $d
if (sym->st_size != 0 || sym->st_info != 0 ||
strings[sym->st_name] != '$') {
_cc->add(_base + sym->st_value, (int)sym->st_size,
strings + sym->st_name);
addSymbol(_base + sym->st_value, (int)sym->st_size, strings + sym->st_name);
}
}
}
Expand Down Expand Up @@ -458,7 +479,7 @@ void ElfParser::addRelocationSymbols(ElfSection *reltab, const char *plt) {
name[sizeof(name) - 1] = 0;
}

_cc->add(plt, PLT_ENTRY_SIZE, name);
addSymbol(plt, PLT_ENTRY_SIZE, name);
plt += PLT_ENTRY_SIZE;
}
}
Expand Down Expand Up @@ -612,6 +633,16 @@ void Symbols::parseLibraries(CodeCacheArray *array, bool kernel_symbols) {
// concurrent loading and unloading of shared libraries.
// Without it, we may access memory of a library that is being unloaded.
dl_iterate_phdr(parseLibrariesCallback, array);
TEST_LOG("Parsed %d libraries", array->count());
}

bool Symbols::isRootSymbol(const void* address) {
for (int i = 0; i < LAST_ROOT_SYMBOL_KIND; i++) {
if (ElfParser::_root_symbols[i] == (uintptr_t)address) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

minor, the ordering could be smart (per code blob)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, probably. I'll just let it dangling here. We are doing at most 5 comparisons which (I hope) compiler would just unroll anyway, and possibly vectorize.

return true;
}
}
return false;
}

#endif // __linux__
10 changes: 10 additions & 0 deletions ddprof-lib/src/main/cpp/symbols_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,16 @@ static const bool MUSL = true;
static const bool MUSL = false;
#endif // __musl__

enum RootSymbolKind {
_start, start_thread, _ZL19thread_native_entryP6Thread, _thread_start, thread_start,
LAST_ROOT_SYMBOL_KIND
};

class ElfParser {
friend Symbols;
private:
static uintptr_t _root_symbols[LAST_ROOT_SYMBOL_KIND];

CodeCache *_cc;
const char *_base;
const char *_file_name;
Expand Down Expand Up @@ -194,6 +202,8 @@ class ElfParser {
const char *strings);
void addRelocationSymbols(ElfSection *reltab, const char *plt);

void addSymbol(const void *start, int length, const char *name, bool update_bounds = false);

public:
static void parseProgramHeaders(CodeCache *cc, const char *base,
const char *end, bool relocate_dyn);
Expand Down
5 changes: 5 additions & 0 deletions ddprof-lib/src/main/cpp/symbols_macos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,9 @@ void Symbols::parseLibraries(CodeCacheArray *array, bool kernel_symbols) {
}
}

bool Symbols::isRootSymbol(const void* address) {
// no known 'always-root' symbols
return false;
}

#endif // __APPLE__