Skip to content

Dwarf and JVMFlag related downports #204

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 5 commits into from
Apr 15, 2025
Merged
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
70 changes: 59 additions & 11 deletions ddprof-lib/src/main/cpp/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ const int PERF_REG_PC = 8; // PERF_REG_X86_IP
#define flushCache(addr) \
asm volatile("mfence; clflush (%0); mfence" : : "r"(addr) : "memory")

#define callerFP() __builtin_frame_address(1)
#define callerSP() ((void**)__builtin_frame_address(0) + 2)

#elif defined(__arm__) || defined(__thumb__)

typedef unsigned int instruction_t;
Expand All @@ -97,6 +100,9 @@ const int PERF_REG_PC = 15; // PERF_REG_ARM_PC
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))

#define callerFP() __builtin_frame_address(1)
#define callerSP() __builtin_frame_address(1)

#elif defined(__aarch64__)

typedef unsigned int instruction_t;
Expand All @@ -116,6 +122,9 @@ const int PERF_REG_PC = 32; // PERF_REG_ARM64_PC
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))

#define callerFP() __builtin_frame_address(1)
#define callerSP() __builtin_frame_address(1)

#elif defined(__PPC64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)

typedef unsigned int instruction_t;
Expand All @@ -132,17 +141,56 @@ const int PLT_HEADER_SIZE = 24;
const int PLT_ENTRY_SIZE = 24;
const int PERF_REG_PC = 32; // PERF_REG_POWERPC_NIP

#define spinPause() \
asm volatile("yield") // does nothing, but using or 1,1,1 would lead to other
// problems
#define rmb() \
asm volatile("sync" \
: \
: \
: "memory") // lwsync would do but better safe than sorry
#define flushCache(addr) \
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))
#define spinPause() asm volatile("yield") // does nothing, but using or 1,1,1 would lead to other problems
#define rmb() asm volatile ("sync" : : : "memory") // lwsync would do but better safe than sorry
#define flushCache(addr) __builtin___clear_cache((char*)(addr), (char*)(addr) + sizeof(instruction_t))

#define callerFP() __builtin_frame_address(1)
#define callerSP() __builtin_frame_address(0)

#elif defined(__riscv) && (__riscv_xlen == 64)

typedef unsigned int instruction_t;
#if defined(__riscv_compressed)
const instruction_t BREAKPOINT = 0x9002; // EBREAK (compressed form)
#else
const instruction_t BREAKPOINT = 0x00100073; // EBREAK
#endif
const int BREAKPOINT_OFFSET = 0;

const int SYSCALL_SIZE = sizeof(instruction_t);
const int FRAME_PC_SLOT = 1; // return address is at -1 from FP
const int PROBE_SP_LIMIT = 0;
const int PLT_HEADER_SIZE = 24; // Best guess from examining readelf
const int PLT_ENTRY_SIZE = 24; // ...same...
const int PERF_REG_PC = 0; // PERF_REG_RISCV_PC

#define spinPause() // No architecture support
#define rmb() asm volatile ("fence" : : : "memory")
#define flushCache(addr) __builtin___clear_cache((char*)(addr), (char*)(addr) + sizeof(instruction_t))

#define callerFP() __builtin_frame_address(1)
#define callerSP() __builtin_frame_address(0)

#elif defined(__loongarch_lp64)

typedef unsigned int instruction_t;
const instruction_t BREAKPOINT = 0x002a0005; // EBREAK
const int BREAKPOINT_OFFSET = 0;

const int SYSCALL_SIZE = sizeof(instruction_t);
const int FRAME_PC_SLOT = 1;
const int PROBE_SP_LIMIT = 0;
const int PLT_HEADER_SIZE = 32;
const int PLT_ENTRY_SIZE = 16;
const int PERF_REG_PC = 0; // PERF_REG_LOONGARCH_PC

#define spinPause() asm volatile("ibar 0x0")
#define rmb() asm volatile("dbar 0x0" : : : "memory")
#define flushCache(addr) __builtin___clear_cache((char*)(addr), (char*)(addr) + sizeof(instruction_t))

#define callerFP() __builtin_frame_address(1)
#define callerSP() __builtin_frame_address(0)

#else

Expand Down
9 changes: 0 additions & 9 deletions ddprof-lib/src/main/cpp/codeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,6 @@ void CodeCache::sort() {
_max_address = _blobs[_count - 1]._end;
}

void CodeCache::mark(NamePredicate predicate) {
for (int i = 0; i < _count; i++) {
const char *blob_name = _blobs[i]._name;
if (blob_name != NULL && predicate(blob_name)) {
NativeFunc::mark(blob_name);
}
}
}

CodeBlob *CodeCache::findBlob(const char *name) {
for (int i = 0; i < _count; i++) {
const char *blob_name = _blobs[i]._name;
Expand Down
30 changes: 28 additions & 2 deletions ddprof-lib/src/main/cpp/codeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ enum ImportType {
NUM_IMPORT_TYPES
};

enum Mark {
MARK_VM_RUNTIME = 1,
MARK_INTERPRETER = 2,
MARK_COMPILER_ENTRY = 3,
MARK_ASYNC_PROFILER = 4, // async-profiler internals such as native hooks.
};

class NativeFunc {
private:
short _lib_index;
Expand All @@ -63,7 +70,13 @@ class NativeFunc {

static bool isMarked(const char *name) { return from(name)->_mark != 0; }

static void mark(const char *name) { from(name)->_mark = 1; }
static char mark(const char* name) {
return from(name)->_mark;
}

static void mark(const char* name, char value) {
from(name)->_mark = value;
}
};

class CodeBlob {
Expand Down Expand Up @@ -154,7 +167,20 @@ class CodeCache {
bool update_bounds = false);
void updateBounds(const void *start, const void *end);
void sort();
void mark(NamePredicate predicate);
template <typename NamePredicate>
inline void mark(NamePredicate predicate, char value) {
for (int i = 0; i < _count; i++) {
const char* blob_name = _blobs[i]._name;
if (blob_name != NULL && predicate(blob_name)) {
NativeFunc::mark(blob_name, value);
}
}

if (value == MARK_VM_RUNTIME && _name != NULL) {
// In case a library has no debug symbols
NativeFunc::mark(_name, value);
}
}

void addImport(void **entry, const char *name);
void **findImport(ImportId id);
Expand Down
3 changes: 1 addition & 2 deletions ddprof-lib/src/main/cpp/flightRecorder.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*
* Copyright The async-profiler authors
* SPDX-License-Identifier: Apache-2.0
* Copyright 2021, 2025 Datadog, Inc
*/

#include <assert.h>
Expand Down Expand Up @@ -754,7 +753,7 @@ void Recording::writeSettings(Buffer *buf, Arguments &args) {
Profiler::instance()->cpuEngine()->name());
writeStringSetting(buf, T_ACTIVE_RECORDING, "wallEngine",
Profiler::instance()->wallEngine()->name());
writeStringSetting(buf, T_ACTIVE_RECORDING, "cstack",
writeStringSetting(buf, T_ACTIVE_RECORDING, "cstack",
Profiler::instance()->cstack());
flushIfNeeded(buf);
}
Expand Down
54 changes: 36 additions & 18 deletions ddprof-lib/src/main/cpp/javaApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,12 @@ Java_com_datadoghq_profiler_JVMAccess_findStringJVMFlag0(JNIEnv *env,
jobject unused,
jstring flagName) {
JniString flag_str(env, flagName);
char** value = static_cast<char**>(JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::String}));
if (value != NULL && *value != NULL) {
return env->NewStringUTF(*value);
JVMFlag *f = JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::String});
if (f) {
char** value = static_cast<char**>(f->addr());
if (value != NULL && *value != NULL) {
return env->NewStringUTF(*value);
}
}
return NULL;
}
Expand All @@ -326,9 +329,12 @@ Java_com_datadoghq_profiler_JVMAccess_setStringJVMFlag0(JNIEnv *env,
jstring flagValue) {
JniString flag_str(env, flagName);
JniString value_str(env, flagValue);
char** value = static_cast<char**>(JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::String}));
if (value != NULL) {
*value = strdup(value_str.c_str());
JVMFlag *f = JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::String});
if (f) {
char** value = static_cast<char**>(f->addr());
if (value != NULL) {
*value = strdup(value_str.c_str());
}
}
}

Expand All @@ -337,9 +343,12 @@ Java_com_datadoghq_profiler_JVMAccess_findBooleanJVMFlag0(JNIEnv *env,
jobject unused,
jstring flagName) {
JniString flag_str(env, flagName);
char* value = static_cast<char*>(JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Bool}));
if (value != NULL) {
return ((*value) & 0xff) == 1;
JVMFlag *f = JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Bool});
if (f) {
char* value = static_cast<char*>(f->addr());
if (value != NULL) {
return ((*value) & 0xff) == 1;
}
}
return false;
}
Expand All @@ -350,9 +359,12 @@ Java_com_datadoghq_profiler_JVMAccess_setBooleanJVMFlag0(JNIEnv *env,
jstring flagName,
jboolean flagValue) {
JniString flag_str(env, flagName);
char* value = static_cast<char*>(JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Bool}));
if (value != NULL) {
*value = flagValue ? 1 : 0;
JVMFlag *f = JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Bool});
if (f) {
char* value = static_cast<char*>(f->addr());
if (value != NULL) {
*value = flagValue ? 1 : 0;
}
}
}

Expand All @@ -361,9 +373,12 @@ Java_com_datadoghq_profiler_JVMAccess_findIntJVMFlag0(JNIEnv *env,
jobject unused,
jstring flagName) {
JniString flag_str(env, flagName);
long* value = static_cast<long*>(JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Int, JVMFlag::Type::Uint, JVMFlag::Type::Intx, JVMFlag::Type::Uintx, JVMFlag::Type::Uint64_t, JVMFlag::Type::Size_t}));
if (value != NULL) {
return *value;
JVMFlag *f = JVMFlag::find(flag_str.c_str(), {JVMFlag::Type::Int, JVMFlag::Type::Uint, JVMFlag::Type::Intx, JVMFlag::Type::Uintx, JVMFlag::Type::Uint64_t, JVMFlag::Type::Size_t});
if (f) {
long* value = static_cast<long*>(f->addr());
if (value != NULL) {
return *value;
}
}
return 0;
}
Expand All @@ -373,9 +388,12 @@ Java_com_datadoghq_profiler_JVMAccess_findFloatJVMFlag0(JNIEnv *env,
jobject unused,
jstring flagName) {
JniString flag_str(env, flagName);
double* value = static_cast<double*>(JVMFlag::find(flag_str.c_str(),{ JVMFlag::Type::Double}));
if (value != NULL) {
return *value;
JVMFlag *f = JVMFlag::find(flag_str.c_str(),{ JVMFlag::Type::Double});
if (f) {
double* value = static_cast<double*>(f->addr());
if (value != NULL) {
return *value;
}
}
return 0.0;
}
Expand Down
Loading
Loading