From a2824a96722d57832664a833430fc4dff7cd8924 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 17 Mar 2026 17:13:03 +0000 Subject: [PATCH 01/11] v0 --- ddprof-lib/src/main/cpp/arguments.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ddprof-lib/src/main/cpp/arguments.h b/ddprof-lib/src/main/cpp/arguments.h index 3f2542705..e80dcbd52 100644 --- a/ddprof-lib/src/main/cpp/arguments.h +++ b/ddprof-lib/src/main/cpp/arguments.h @@ -202,6 +202,7 @@ class Arguments { _wall(-1), _wall_collapsing(false), _wall_threads_per_tick(DEFAULT_WALL_THREADS_PER_TICK), + _wallclock_sampler(ASGCT), _memory(-1), _record_allocations(false), _record_liveness(false), @@ -220,10 +221,10 @@ class Arguments { _clock(CLK_DEFAULT), _jfr_options(0), _context_attributes({}), - _wallclock_sampler(ASGCT), _lightweight(false), _enable_method_cleanup(true), - _remote_symbolication(false) {} + _remote_symbolication(false) { } + ~Arguments(); From 061c35aeae2a086aca7753320ecdbe07b37c15b4 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 18 Mar 2026 14:01:40 +0000 Subject: [PATCH 02/11] v1 --- ddprof-lib/src/main/cpp/context.cpp | 2 ++ ddprof-lib/src/main/cpp/context.h | 2 -- ddprof-lib/src/main/cpp/flightRecorder.cpp | 11 +++++----- ddprof-lib/src/main/cpp/javaApi.cpp | 6 ++--- ddprof-lib/src/main/cpp/jniHelper.h | 2 +- ddprof-lib/src/main/cpp/libraries.h | 3 ++- ddprof-lib/src/main/cpp/livenessTracker.cpp | 4 +--- ddprof-lib/src/main/cpp/os_linux.cpp | 2 +- ddprof-lib/src/main/cpp/perfEvents_linux.cpp | 2 +- ddprof-lib/src/main/cpp/pidController.h | 5 +++-- ddprof-lib/src/main/cpp/profiler.cpp | 1 - ddprof-lib/src/main/cpp/profiler.h | 23 +++++++++++--------- ddprof-lib/src/main/cpp/reservoirSampler.h | 8 +++---- ddprof-lib/src/main/cpp/symbols_linux.cpp | 15 +++---------- ddprof-lib/src/main/cpp/thread.h | 1 + ddprof-lib/src/main/cpp/threadState.h | 2 +- ddprof-lib/src/main/cpp/tsc.h | 4 ++-- ddprof-lib/src/main/cpp/vmStructs.cpp | 2 +- ddprof-lib/src/main/cpp/wallClock.cpp | 8 +++---- ddprof-lib/src/main/cpp/wallClock.h | 8 +++---- 20 files changed, 51 insertions(+), 60 deletions(-) diff --git a/ddprof-lib/src/main/cpp/context.cpp b/ddprof-lib/src/main/cpp/context.cpp index 3348c7e0f..fba530381 100644 --- a/ddprof-lib/src/main/cpp/context.cpp +++ b/ddprof-lib/src/main/cpp/context.cpp @@ -38,6 +38,8 @@ Context& Contexts::initializeContextTls() { return ctx; } +static Context DD_EMPTY_CONTEXT = {}; + Context& Contexts::get() { ProfiledThread* thrd = ProfiledThread::currentSignalSafe(); if (thrd == nullptr || !thrd->isContextTlsInitialized()) { diff --git a/ddprof-lib/src/main/cpp/context.h b/ddprof-lib/src/main/cpp/context.h index 8ad713afa..8d81b8b4c 100644 --- a/ddprof-lib/src/main/cpp/context.h +++ b/ddprof-lib/src/main/cpp/context.h @@ -39,8 +39,6 @@ class alignas(DEFAULT_CACHE_LINE_SIZE) Context { Tag get_tag(int i) { return tags[i]; } }; -static Context DD_EMPTY_CONTEXT = {}; - class Contexts { public: diff --git a/ddprof-lib/src/main/cpp/flightRecorder.cpp b/ddprof-lib/src/main/cpp/flightRecorder.cpp index 4adc5f727..3e392a4ef 100644 --- a/ddprof-lib/src/main/cpp/flightRecorder.cpp +++ b/ddprof-lib/src/main/cpp/flightRecorder.cpp @@ -808,7 +808,7 @@ void Recording::writeMetadata(Buffer *buf) { std::vector &strings = JfrMetadata::strings(); buf->putVar64(strings.size()); - for (int i = 0; i < strings.size(); i++) { + for (size_t i = 0; i < strings.size(); i++) { const char *string = strings[i].c_str(); int length = strlen(string); flushIfNeeded(buf, RECORDING_BUFFER_LIMIT - length); @@ -842,14 +842,14 @@ void Recording::writeElement(Buffer *buf, const Element *e) { buf->putVar64(e->_name); buf->putVar64(e->_attributes.size()); - for (int i = 0; i < e->_attributes.size(); i++) { + for (size_t i = 0; i < e->_attributes.size(); i++) { flushIfNeeded(buf); buf->putVar64(e->_attributes[i]._key); buf->putVar64(e->_attributes[i]._value); } buf->putVar64(e->_children.size()); - for (int i = 0; i < e->_children.size(); i++) { + for (size_t i = 0; i < e->_children.size(); i++) { flushIfNeeded(buf); writeElement(buf, e->_children[i]); } @@ -1426,7 +1426,7 @@ void Recording::writeCounters(Buffer *buf) { long long *counters = Counters::getCounters(); if (counters) { std::vector names = Counters::describeCounters(); - for (int i = 0; i < names.size(); i++) { + for (size_t i = 0; i < names.size(); i++) { int start = buf->skip(1); buf->putVar64(T_DATADOG_COUNTER); buf->putVar64(_start_ticks); @@ -1683,10 +1683,11 @@ void FlightRecorder::stop() { } Error FlightRecorder::dump(const char *filename, const int length) { + assert(length >= 0); ExclusiveLockGuard locker(&_rec_lock); Recording* rec = _rec; if (rec != nullptr) { - if (_filename.length() != length || + if (_filename.length() != size_t(length) || strncmp(filename, _filename.c_str(), length) != 0) { // if the filename to dump the recording to is specified move the current // working file there diff --git a/ddprof-lib/src/main/cpp/javaApi.cpp b/ddprof-lib/src/main/cpp/javaApi.cpp index 355fcd512..df957e11a 100644 --- a/ddprof-lib/src/main/cpp/javaApi.cpp +++ b/ddprof-lib/src/main/cpp/javaApi.cpp @@ -440,9 +440,6 @@ Java_com_datadoghq_profiler_JVMAccess_healthCheck0(JNIEnv *env, return true; } -// Static variable to track the current published context -static otel_process_ctx_result* current_published_context = nullptr; - extern "C" DLLEXPORT void JNICALL Java_com_datadoghq_profiler_OTelContext_setProcessCtx0(JNIEnv *env, jclass unused, @@ -577,7 +574,8 @@ Java_com_datadoghq_profiler_JavaProfiler_testlog(JNIEnv* env, jclass unused, jst extern "C" DLLEXPORT void JNICALL Java_com_datadoghq_profiler_JavaProfiler_dumpContext(JNIEnv* env, jclass unused) { +#ifdef DEBUG Context& ctx = Contexts::get(); - TEST_LOG("===> Context: tid:%lu, spanId=%lu, rootSpanId=%lu, checksum=%lu", OS::threadId(), ctx.spanId, ctx.rootSpanId, ctx.checksum); +#endif // DEBUG } diff --git a/ddprof-lib/src/main/cpp/jniHelper.h b/ddprof-lib/src/main/cpp/jniHelper.h index 3bcca7048..2ccda72dd 100644 --- a/ddprof-lib/src/main/cpp/jniHelper.h +++ b/ddprof-lib/src/main/cpp/jniHelper.h @@ -3,7 +3,7 @@ #include -static bool jniExceptionCheck(JNIEnv *jni, bool describe = false) { +inline bool jniExceptionCheck(JNIEnv *jni, bool describe = false) { if (jni->ExceptionCheck()) { if (describe) { jni->ExceptionDescribe(); diff --git a/ddprof-lib/src/main/cpp/libraries.h b/ddprof-lib/src/main/cpp/libraries.h index 8b626ad9b..cf1a147fb 100644 --- a/ddprof-lib/src/main/cpp/libraries.h +++ b/ddprof-lib/src/main/cpp/libraries.h @@ -23,7 +23,8 @@ class Libraries { // Get library by index (used for remote symbolication unpacking) // Note: Parameter is uint32_t to match lib_index packing (17 bits = max 131K libraries) CodeCache *getLibraryByIndex(uint32_t index) const { - if (index < _native_libs.count()) { + assert(_native_libs.count() >= 0); + if (index < (uint32_t)_native_libs.count()) { return _native_libs[index]; // may be NULL during concurrent add() } return nullptr; diff --git a/ddprof-lib/src/main/cpp/livenessTracker.cpp b/ddprof-lib/src/main/cpp/livenessTracker.cpp index d44f072f2..bcd9f1a71 100644 --- a/ddprof-lib/src/main/cpp/livenessTracker.cpp +++ b/ddprof-lib/src/main/cpp/livenessTracker.cpp @@ -97,7 +97,7 @@ void LivenessTracker::flush_table(std::set *tracked_thread_ids) { _table_lock.lock(); u32 sz; - for (int i = 0; i < (sz = _table_size); i++) { + for (u32 i = 0; i < (sz = _table_size); i++) { jobject ref = env->NewLocalRef(_table[i].ref); if (ref != nullptr) { if (tracked_thread_ids != nullptr) { @@ -208,8 +208,6 @@ void LivenessTracker::stop() { // multiple recordings } -static int _min(int a, int b) { return a < b ? a : b; } - Error LivenessTracker::initialize(Arguments &args) { _enabled = args._gc_generations || args._record_liveness; diff --git a/ddprof-lib/src/main/cpp/os_linux.cpp b/ddprof-lib/src/main/cpp/os_linux.cpp index 7bb054311..4e6a6aa4d 100644 --- a/ddprof-lib/src/main/cpp/os_linux.cpp +++ b/ddprof-lib/src/main/cpp/os_linux.cpp @@ -344,7 +344,7 @@ bool OS::getCpuDescription(char* buf, size_t size) { if (r <= 0) { return false; } - buf[r < size ? r : size - 1] = 0; + buf[size_t(r) < size ? r : size - 1] = 0; char* c; do { diff --git a/ddprof-lib/src/main/cpp/perfEvents_linux.cpp b/ddprof-lib/src/main/cpp/perfEvents_linux.cpp index e311f5db7..94a4256ec 100644 --- a/ddprof-lib/src/main/cpp/perfEvents_linux.cpp +++ b/ddprof-lib/src/main/cpp/perfEvents_linux.cpp @@ -123,7 +123,7 @@ static void resolvePmuEventName(const char *device, char *event, size_t size) { } ssize_t r = read(fd, event, size); - if (r > 0 && (r == size || event[r - 1] == '\n')) { + if (r > 0 && (size_t(r) == size || event[r - 1] == '\n')) { event[r - 1] = 0; } close(fd); diff --git a/ddprof-lib/src/main/cpp/pidController.h b/ddprof-lib/src/main/cpp/pidController.h index 8c44d370a..030530b3b 100644 --- a/ddprof-lib/src/main/cpp/pidController.h +++ b/ddprof-lib/src/main/cpp/pidController.h @@ -50,9 +50,10 @@ class PidController { int sampling_window, double cutoff_secs) : _target(target_per_second * sampling_window), _proportional_gain(proportional_gain), - _integral_gain(integral_gain * sampling_window), _derivative_gain(derivative_gain / sampling_window), - _alpha(computeAlpha(sampling_window / cutoff_secs)), _avg_error(0), + _integral_gain(integral_gain * sampling_window), + _alpha(computeAlpha(sampling_window / cutoff_secs)), + _avg_error(0), _integral_value(0) {} double compute(u64 input, double time_delta_seconds); diff --git a/ddprof-lib/src/main/cpp/profiler.cpp b/ddprof-lib/src/main/cpp/profiler.cpp index fedb7e1d6..efe6b9cc8 100644 --- a/ddprof-lib/src/main/cpp/profiler.cpp +++ b/ddprof-lib/src/main/cpp/profiler.cpp @@ -47,7 +47,6 @@ Profiler *const Profiler::_instance = new Profiler(); volatile bool Profiler::_signals_initialized = false; volatile bool Profiler::_need_JDK_8313796_workaround = true; -static void (*orig_trapHandler)(int signo, siginfo_t *siginfo, void *ucontext); static void (*orig_segvHandler)(int signo, siginfo_t *siginfo, void *ucontext); static void (*orig_busHandler)(int signo, siginfo_t *siginfo, void *ucontext); diff --git a/ddprof-lib/src/main/cpp/profiler.h b/ddprof-lib/src/main/cpp/profiler.h index 285c64805..1137918bf 100644 --- a/ddprof-lib/src/main/cpp/profiler.h +++ b/ddprof-lib/src/main/cpp/profiler.h @@ -200,19 +200,22 @@ class alignas(alignof(SpinLock)) Profiler { public: Profiler() - : _state(NEW), _class_unload_hook_trap(2), - _notify_class_unloaded_func(NULL), _thread_filter(), _call_trace_storage(), _jfr(), - _start_time(0), _epoch(0), _timer_id(NULL), - _max_stack_depth(0), _safe_mode(0), _thread_events_state(JVMTI_DISABLE), - _libs(Libraries::instance()), _stubs_lock(), _runtime_stubs("[stubs]"), - _call_stub_begin(NULL), _call_stub_end(NULL), _dlopen_entry(NULL), - _num_context_attributes(0), _class_map(1), _string_label_map(2), - _context_value_map(3), _cpu_engine(), _alloc_engine(), _event_mask(0), - _stop_time(), _total_samples(0), _failures(), _cstack(CSTACK_NO), - _omit_stacktraces(false) { + : _state_lock(), _state(NEW), _class_unload_hook_trap(2), + _notify_class_unloaded_func(NULL), _thread_info(), _class_map(1), + _string_label_map(2), _context_value_map(3), _thread_filter(), + _call_trace_storage(), _jfr(), _cpu_engine(NULL), _wall_engine(NULL), + _alloc_engine(NULL), _event_mask(0), + _start_time(0), _stop_time(0), _epoch(0), _timer_id(NULL), + _total_samples(0), _failures(), _class_map_lock(), + _max_stack_depth(0), _features(), _safe_mode(0), _cstack(CSTACK_NO), + _thread_events_state(JVMTI_DISABLE), _libs(Libraries::instance()), _stubs_lock(), + _runtime_stubs("[stubs]"), _call_stub_begin(NULL), _call_stub_end(NULL), + _num_context_attributes(0), _omit_stacktraces(false), _remote_symbolication(false), + _dlopen_entry(NULL) { for (int i = 0; i < CONCURRENCY_LEVEL; i++) { _calltrace_buffer[i] = NULL; + new (&_locks[i])SpinLock(); } } diff --git a/ddprof-lib/src/main/cpp/reservoirSampler.h b/ddprof-lib/src/main/cpp/reservoirSampler.h index 96c7b3ec0..848ba4e28 100644 --- a/ddprof-lib/src/main/cpp/reservoirSampler.h +++ b/ddprof-lib/src/main/cpp/reservoirSampler.h @@ -25,14 +25,14 @@ template class ReservoirSampler { private: - const int _size; + const size_t _size; std::mt19937 _generator; std::uniform_real_distribution _uniform; std::uniform_int_distribution _random_index; std::vector _reservoir; public: - ReservoirSampler(const int size) : + ReservoirSampler(const size_t size) : _size(size), _generator([]() { std::random_device rd; @@ -46,11 +46,11 @@ class ReservoirSampler { std::vector& sample(const std::vector &input) { _reservoir.clear(); - for (int i = 0; i < _size && i < input.size(); i++) { + for (size_t i = 0; i < _size && i < input.size(); i++) { _reservoir.push_back(input[i]); } double weight = exp(log(_uniform(_generator)) / _size); - int target = _size + (int) (log(_uniform(_generator)) / log(1 - weight)); + size_t target = _size + (int) (log(_uniform(_generator)) / log(1 - weight)); while (target < input.size()) { _reservoir[_random_index(_generator)] = input[target]; weight *= exp(log(_uniform(_generator)) / _size); diff --git a/ddprof-lib/src/main/cpp/symbols_linux.cpp b/ddprof-lib/src/main/cpp/symbols_linux.cpp index 8b6a7cf22..7ebd87f84 100644 --- a/ddprof-lib/src/main/cpp/symbols_linux.cpp +++ b/ddprof-lib/src/main/cpp/symbols_linux.cpp @@ -135,14 +135,6 @@ static void ensure_main_phdr_initialized() { pthread_once(&_main_phdr_once, init_main_phdr_once); } -static Range range_for_fbase(void* fbase) { - Range r = {0, 0}; - if (!fbase) return r; - UnifiedCtx ctx = {fbase, &r, NULL, NULL, NULL, NULL, NULL}; - dl_iterate_phdr(&unified_phdr_cb, &ctx); - return r; -} - static void init_lib_ranges_once() { if (g_lib_ranges_inited) return; g_lib_ranges_inited = true; @@ -663,15 +655,14 @@ const char* ElfParser::getDebuginfodCache() { const char* env_vars[] = {"DEBUGINFOD_CACHE_PATH", "XDG_CACHE_HOME", "HOME"}; const char* suffixes[] = {"/", "debuginfod_client/", ".cache/debuginfod_client/"}; - for (int i = 0; i < sizeof(env_vars) / sizeof(env_vars[0]); i++) { + for (size_t i = 0; i < sizeof(env_vars) / sizeof(env_vars[0]); i++) { const char* env_val = getenv(env_vars[i]); if (!env_val || !env_val[0]) { continue; } - if (snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]) < sizeof(_debuginfod_cache_buf)) { - return _debuginfod_cache_buf; - } + snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]); + return _debuginfod_cache_buf; } _debuginfod_cache_buf[0] = '\0'; diff --git a/ddprof-lib/src/main/cpp/thread.h b/ddprof-lib/src/main/cpp/thread.h index 4cb12d0ca..188a592f1 100644 --- a/ddprof-lib/src/main/cpp/thread.h +++ b/ddprof-lib/src/main/cpp/thread.h @@ -78,6 +78,7 @@ class ProfiledThread : public ThreadLocalData { void releaseFromBuffer(); + virtual ~ProfiledThread() { } public: static ProfiledThread *forTid(int tid) { return new ProfiledThread(-1, tid); } static ProfiledThread *inBuffer(int buffer_pos) { diff --git a/ddprof-lib/src/main/cpp/threadState.h b/ddprof-lib/src/main/cpp/threadState.h index 33553a267..0b666c243 100644 --- a/ddprof-lib/src/main/cpp/threadState.h +++ b/ddprof-lib/src/main/cpp/threadState.h @@ -26,7 +26,7 @@ enum class ExecutionMode : int { SYSCALL = 5 }; -static ExecutionMode convertJvmExecutionState(int state) { +inline ExecutionMode convertJvmExecutionState(int state) { switch (state) { case 4: case 5: diff --git a/ddprof-lib/src/main/cpp/tsc.h b/ddprof-lib/src/main/cpp/tsc.h index 70e7e2a28..ac8047029 100644 --- a/ddprof-lib/src/main/cpp/tsc.h +++ b/ddprof-lib/src/main/cpp/tsc.h @@ -33,7 +33,7 @@ static inline u64 rdtsc() { } // Returns true if this CPU has a good ("invariant") timestamp counter -static bool cpuHasGoodTimestampCounter() { +inline bool cpuHasGoodTimestampCounter() { unsigned int eax, ebx, ecx, edx; // Check if CPUID supports misc feature flags @@ -59,7 +59,7 @@ static inline u64 rdtsc() { return value; } -static bool cpuHasGoodTimestampCounter() { +inline bool cpuHasGoodTimestampCounter() { // AARCH64 always has a good timestamp counter. return true; } diff --git a/ddprof-lib/src/main/cpp/vmStructs.cpp b/ddprof-lib/src/main/cpp/vmStructs.cpp index e220dd2db..d68f0d412 100644 --- a/ddprof-lib/src/main/cpp/vmStructs.cpp +++ b/ddprof-lib/src/main/cpp/vmStructs.cpp @@ -1216,7 +1216,7 @@ HeapUsage HeapUsage::get(bool allow_jmx) { usage._maxSize = summary.maxSize(); } } - if (usage._maxSize == -1 && _memory_usage_func != NULL && allow_jmx && isJMXSupported()) { + if (usage._maxSize == size_t(-1) && _memory_usage_func != NULL && allow_jmx && isJMXSupported()) { // this path is for non-hotspot JVMs // we need to patch the native method binding for JMX GetMemoryUsage to // capture the native method pointer first also, it requires JMX and diff --git a/ddprof-lib/src/main/cpp/wallClock.cpp b/ddprof-lib/src/main/cpp/wallClock.cpp index 60f44da41..848afe628 100644 --- a/ddprof-lib/src/main/cpp/wallClock.cpp +++ b/ddprof-lib/src/main/cpp/wallClock.cpp @@ -116,12 +116,12 @@ Error BaseWallClock::start(Arguments &args) { if (interval < 0) { return Error("interval must be positive"); } + _interval = interval ? interval : DEFAULT_WALL_INTERVAL; - _reservoir_size = + _reservoir_size = args._wall_threads_per_tick ? - args._wall_threads_per_tick - : DEFAULT_WALL_THREADS_PER_TICK; + args._wall_threads_per_tick : DEFAULT_WALL_THREADS_PER_TICK; initialize(args); @@ -223,8 +223,6 @@ void WallClockJVMTI::timerLoop() { }; auto sampleThreads = [&](ThreadEntry& thread_entry, int& num_failures, int& threads_already_exited, int& permission_denied) { - static jint max_stack_depth = (jint)Profiler::instance()->max_stack_depth(); - ExecutionEvent event; VMThread* vm_thread = thread_entry.native; int raw_thread_state = vm_thread->state(); diff --git a/ddprof-lib/src/main/cpp/wallClock.h b/ddprof-lib/src/main/cpp/wallClock.h index 2530c8b2d..2512d1a0e 100644 --- a/ddprof-lib/src/main/cpp/wallClock.h +++ b/ddprof-lib/src/main/cpp/wallClock.h @@ -30,9 +30,9 @@ class BaseWallClock : public Engine { // Profiler::recordSample(). int _reservoir_size; - pthread_t _thread; - virtual void timerLoop() = 0; - virtual void initialize(Arguments& args) {}; + pthread_t _thread; + virtual void timerLoop() = 0; + virtual void initialize(Arguments& args) {}; static void *threadEntry(void *wall_clock) { ((BaseWallClock *)wall_clock)->timerLoop(); @@ -114,9 +114,9 @@ class BaseWallClock : public Engine { public: BaseWallClock() : + _running(false), _interval(LONG_MAX), _reservoir_size(0), - _running(false), _thread(0) {} virtual ~BaseWallClock() = default; From f260c942a41e8e2f923f596cfb7b9ca14c43695d Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 18 Mar 2026 18:39:29 +0000 Subject: [PATCH 03/11] v2 --- ddprof-lib/src/main/cpp/callTraceHashTable.cpp | 2 +- ddprof-lib/src/main/cpp/callTraceStorage.h | 6 ------ ddprof-lib/src/main/cpp/codeCache.cpp | 2 +- ddprof-lib/src/main/cpp/dwarf.h | 2 +- ddprof-lib/src/main/cpp/os_linux.cpp | 3 ++- ddprof-lib/src/main/cpp/perfEvents_linux.cpp | 2 +- ddprof-lib/src/main/cpp/reservoirSampler.h | 11 ++++++----- ddprof-lib/src/main/cpp/symbols_linux.cpp | 5 +++-- ddprof-lib/src/main/cpp/vmStructs.cpp | 6 +++--- ddprof-lib/src/main/cpp/vmStructs.h | 4 ++-- 10 files changed, 20 insertions(+), 23 deletions(-) diff --git a/ddprof-lib/src/main/cpp/callTraceHashTable.cpp b/ddprof-lib/src/main/cpp/callTraceHashTable.cpp index 39837eed0..f14e370bb 100644 --- a/ddprof-lib/src/main/cpp/callTraceHashTable.cpp +++ b/ddprof-lib/src/main/cpp/callTraceHashTable.cpp @@ -85,7 +85,7 @@ static void init_overflow_trace() { CallTraceHashTable::_overflow_trace.frames[0] = {BCI_ERROR, LP64_ONLY(0 COMMA) (jmethodID)"storage_overflow"}; } -CallTraceHashTable::CallTraceHashTable() : _allocator(CALL_TRACE_CHUNK), _instance_id(0), _parent_storage(nullptr) { +CallTraceHashTable::CallTraceHashTable() : _instance_id(0), _parent_storage(nullptr), _allocator(CALL_TRACE_CHUNK) { // Instance ID will be set externally via setInstanceId() // Start with initial capacity, allowing expansion as needed diff --git a/ddprof-lib/src/main/cpp/callTraceStorage.h b/ddprof-lib/src/main/cpp/callTraceStorage.h index 4fd6cf8e8..77bbcce8b 100644 --- a/ddprof-lib/src/main/cpp/callTraceStorage.h +++ b/ddprof-lib/src/main/cpp/callTraceStorage.h @@ -142,12 +142,6 @@ class CallTraceStorage { std::unordered_set _traces_buffer; // All traces for JFR processing std::unordered_set _preserve_set_buffer; // Preserve set for current cycle - -private: - - - - public: CallTraceStorage(); ~CallTraceStorage(); diff --git a/ddprof-lib/src/main/cpp/codeCache.cpp b/ddprof-lib/src/main/cpp/codeCache.cpp index a8a360160..c6ce7c59e 100644 --- a/ddprof-lib/src/main/cpp/codeCache.cpp +++ b/ddprof-lib/src/main/cpp/codeCache.cpp @@ -282,7 +282,7 @@ void CodeCache::findSymbolsByPrefix(std::vector &prefixes, for (int i = 0; i < _count; i++) { const char *blob_name = _blobs[i]._name; if (blob_name != NULL) { - for (int i = 0; i < prefixes.size(); i++) { + for (size_t i = 0; i < prefixes.size(); i++) { if (strncmp(blob_name, prefixes[i], prefix_lengths[i]) == 0) { symbols.push_back(_blobs[i]._start); } diff --git a/ddprof-lib/src/main/cpp/dwarf.h b/ddprof-lib/src/main/cpp/dwarf.h index 0a62ab40d..0185bf084 100644 --- a/ddprof-lib/src/main/cpp/dwarf.h +++ b/ddprof-lib/src/main/cpp/dwarf.h @@ -74,7 +74,7 @@ const int INITIAL_PC_OFFSET = DW_LINK_REGISTER; struct FrameDesc { u32 loc; - int cfa; + u32 cfa; int fp_off; int pc_off; diff --git a/ddprof-lib/src/main/cpp/os_linux.cpp b/ddprof-lib/src/main/cpp/os_linux.cpp index 4e6a6aa4d..df047e62a 100644 --- a/ddprof-lib/src/main/cpp/os_linux.cpp +++ b/ddprof-lib/src/main/cpp/os_linux.cpp @@ -269,7 +269,8 @@ SigAction OS::installSignalHandler(int signo, SigAction action, SigHandler handl } else { sa.sa_sigaction = action; sa.sa_flags = SA_SIGINFO | SA_RESTART; - if (signo > 0 && signo < sizeof(installed_sigaction) / sizeof(installed_sigaction[0])) { + int num = sizeof(installed_sigaction) / sizeof(installed_sigaction[0]); + if (signo > 0 && signo < num) { installed_sigaction[signo] = action; } } diff --git a/ddprof-lib/src/main/cpp/perfEvents_linux.cpp b/ddprof-lib/src/main/cpp/perfEvents_linux.cpp index 94a4256ec..ab8cd6992 100644 --- a/ddprof-lib/src/main/cpp/perfEvents_linux.cpp +++ b/ddprof-lib/src/main/cpp/perfEvents_linux.cpp @@ -147,7 +147,7 @@ static bool setPmuConfig(const char *device, const char *param, __u64 *config, ssize_t r = read(fd, buf, sizeof(buf)); close(fd); - if (r > 0 && r < sizeof(buf)) { + if (r > 0 && r < (int)sizeof(buf)) { if (strncmp(buf, "config:", 7) == 0) { config[0] |= val << atoi(buf + 7); return true; diff --git a/ddprof-lib/src/main/cpp/reservoirSampler.h b/ddprof-lib/src/main/cpp/reservoirSampler.h index 848ba4e28..5963c6036 100644 --- a/ddprof-lib/src/main/cpp/reservoirSampler.h +++ b/ddprof-lib/src/main/cpp/reservoirSampler.h @@ -25,14 +25,14 @@ template class ReservoirSampler { private: - const size_t _size; + const int _size; std::mt19937 _generator; std::uniform_real_distribution _uniform; std::uniform_int_distribution _random_index; std::vector _reservoir; public: - ReservoirSampler(const size_t size) : + ReservoirSampler(const int size) : _size(size), _generator([]() { std::random_device rd; @@ -46,12 +46,13 @@ class ReservoirSampler { std::vector& sample(const std::vector &input) { _reservoir.clear(); - for (size_t i = 0; i < _size && i < input.size(); i++) { + for (int i = 0; i < _size && i < (int)input.size(); i++) { _reservoir.push_back(input[i]); } double weight = exp(log(_uniform(_generator)) / _size); - size_t target = _size + (int) (log(_uniform(_generator)) / log(1 - weight)); - while (target < input.size()) { + int target = _size + (int) (log(_uniform(_generator)) / log(1 - weight)); + assert(target >= 0); + while (target < (int)input.size()) { _reservoir[_random_index(_generator)] = input[target]; weight *= exp(log(_uniform(_generator)) / _size); target += (int) (log(_uniform(_generator)) / log(1 - weight)); diff --git a/ddprof-lib/src/main/cpp/symbols_linux.cpp b/ddprof-lib/src/main/cpp/symbols_linux.cpp index 7ebd87f84..631300858 100644 --- a/ddprof-lib/src/main/cpp/symbols_linux.cpp +++ b/ddprof-lib/src/main/cpp/symbols_linux.cpp @@ -661,8 +661,9 @@ const char* ElfParser::getDebuginfodCache() { continue; } - snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]); - return _debuginfod_cache_buf; + if (snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]) < (int)sizeof(_debuginfod_cache_buf)) { + return _debuginfod_cache_buf; + } } _debuginfod_cache_buf[0] = '\0'; diff --git a/ddprof-lib/src/main/cpp/vmStructs.cpp b/ddprof-lib/src/main/cpp/vmStructs.cpp index d68f0d412..a9ec791fe 100644 --- a/ddprof-lib/src/main/cpp/vmStructs.cpp +++ b/ddprof-lib/src/main/cpp/vmStructs.cpp @@ -117,7 +117,7 @@ DECLARE_TYPES_DO(INIT_TYPE_SIZE) jfieldID VMStructs::_eetop; jfieldID VMStructs::_tid; jfieldID VMStructs::_klass = NULL; -int VMStructs::_tls_index = -1; +pthread_key_t VMStructs::_tls_index = pthread_key_t(-1); intptr_t VMStructs::_env_offset = -1; void* VMStructs::_java_thread_vtbl[6]; @@ -632,7 +632,7 @@ void VMStructs::patchSafeFetch() { void VMStructs::initTLS(void* vm_thread) { for (int i = 0; i < 1024; i++) { if (pthread_getspecific((pthread_key_t)i) == vm_thread) { - _tls_index = i; + _tls_index = (pthread_key_t)i; break; } } @@ -802,7 +802,7 @@ void VMStructs::checkNativeBinding(jvmtiEnv *jvmti, JNIEnv *jni, } VMThread* VMThread::current() { - return _tls_index >= 0 ? (VMThread*)pthread_getspecific((pthread_key_t)_tls_index) : NULL; + return _tls_index >= 0 ? (VMThread*)pthread_getspecific(_tls_index) : NULL; } int VMThread::nativeThreadId(JNIEnv* jni, jthread thread) { diff --git a/ddprof-lib/src/main/cpp/vmStructs.h b/ddprof-lib/src/main/cpp/vmStructs.h index 72299538f..98f9c257b 100644 --- a/ddprof-lib/src/main/cpp/vmStructs.h +++ b/ddprof-lib/src/main/cpp/vmStructs.h @@ -182,7 +182,7 @@ class VMStructs { static jfieldID _eetop; static jfieldID _tid; static jfieldID _klass; - static int _tls_index; + static pthread_key_t _tls_index; static intptr_t _env_offset; static void* _java_thread_vtbl[6]; @@ -521,7 +521,7 @@ DECLARE(VMThread) public: static VMThread* current(); - static int key() { + static pthread_key_t key() { return _tls_index; } From d8673d2de03975da8c7b5c3d7d6781730be6b039 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 20 Mar 2026 18:10:47 +0000 Subject: [PATCH 04/11] fix buffer --- ddprof-lib/src/main/cpp/buffers.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/ddprof-lib/src/main/cpp/buffers.h b/ddprof-lib/src/main/cpp/buffers.h index 66af4b539..322b45d2d 100644 --- a/ddprof-lib/src/main/cpp/buffers.h +++ b/ddprof-lib/src/main/cpp/buffers.h @@ -29,17 +29,18 @@ typedef ssize_t (*FlushCallback)(char *data, int len); class Buffer { private: int _offset; - static const int _limit = BUFFER_SIZE - sizeof(int); protected: // this array is 'extended' by the RecordingBuffer // this will confuse sanitizers and most of the sane people but it seems to // work - char _data[_limit]; + char* _data; + Buffer() : _offset(0) { } public: - Buffer() : _offset(0) { memset(_data, 0, _limit); } - virtual int limit() const { return _limit; } + int limit() const { + return BUFFER_SIZE - sizeof(Buffer); + } bool flushIfNeeded(FlushCallback callback, int limit = BUFFER_LIMIT) { if (_offset > limit) { @@ -218,21 +219,24 @@ class Buffer { class RecordingBuffer : public Buffer { private: - static const int _limit = RECORDING_BUFFER_SIZE - sizeof(Buffer); // we reserve 8KiB to overflow in to in case event serialisers in // the flight recorder are buggy. If we ever use the overflow, // which is sized to accommodate the largest possible string, we // will truncate and may produce a corrupt recording, but we will // not write into arbitrary memory. - char _buf[_limit + RECORDING_BUFFER_OVERFLOW]; + static const int LIMIT = RECORDING_BUFFER_SIZE - sizeof(Buffer); public: RecordingBuffer() : Buffer() { - new (_data + sizeof(_data)) char[sizeof(_buf)]; - memset(_buf, 0, _limit); + _data = (char*)malloc(LIMIT * sizeof(char)); + memset(_data, 0, LIMIT * sizeof(char)); + } + + virtual ~RecordingBuffer() { + free(_data); } - int limit() const override { return _limit; } + int limit() const { return LIMIT; } bool flushIfNeeded(FlushCallback callback, int limit = RECORDING_BUFFER_LIMIT) { From 617186a45bfda1a4f288d790a1ba4d36bc4abf20 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Thu, 26 Mar 2026 11:51:48 -0400 Subject: [PATCH 05/11] Revert buffer changes --- ddprof-lib/src/main/cpp/buffers.h | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/ddprof-lib/src/main/cpp/buffers.h b/ddprof-lib/src/main/cpp/buffers.h index 322b45d2d..9380473de 100644 --- a/ddprof-lib/src/main/cpp/buffers.h +++ b/ddprof-lib/src/main/cpp/buffers.h @@ -29,18 +29,17 @@ typedef ssize_t (*FlushCallback)(char *data, int len); class Buffer { private: int _offset; + static const int _limit = BUFFER_SIZE - sizeof(int); protected: // this array is 'extended' by the RecordingBuffer // this will confuse sanitizers and most of the sane people but it seems to // work - char* _data; + char _data[_limit]; - Buffer() : _offset(0) { } public: + Buffer() : _offset(0) { memset(_data, 0, _limit); } - int limit() const { - return BUFFER_SIZE - sizeof(Buffer); - } + virtual int limit() const { return _limit; } bool flushIfNeeded(FlushCallback callback, int limit = BUFFER_LIMIT) { if (_offset > limit) { @@ -219,24 +218,21 @@ class Buffer { class RecordingBuffer : public Buffer { private: + static const int _limit = RECORDING_BUFFER_SIZE - sizeof(Buffer); // we reserve 8KiB to overflow in to in case event serialisers in // the flight recorder are buggy. If we ever use the overflow, // which is sized to accommodate the largest possible string, we // will truncate and may produce a corrupt recording, but we will // not write into arbitrary memory. - static const int LIMIT = RECORDING_BUFFER_SIZE - sizeof(Buffer); + char _buf[_limit + RECORDING_BUFFER_OVERFLOW]; public: RecordingBuffer() : Buffer() { - _data = (char*)malloc(LIMIT * sizeof(char)); - memset(_data, 0, LIMIT * sizeof(char)); - } - - virtual ~RecordingBuffer() { - free(_data); + new (_data + sizeof(_data)) char[sizeof(_buf)]; + memset(_buf, 0, _limit); } - int limit() const { return LIMIT; } + int limit() const override { return _limit; } bool flushIfNeeded(FlushCallback callback, int limit = RECORDING_BUFFER_LIMIT) { From 592b9f8a28b8aa8f24965f63a2bc830fa213d4bc Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Thu, 26 Mar 2026 19:53:37 +0000 Subject: [PATCH 06/11] Fix --- ddprof-lib/src/main/cpp/javaApi.cpp | 2 +- ddprof-lib/src/main/cpp/otel_process_ctx.cpp | 48 +++++++++++++++---- ddprof-lib/src/test/make/Makefile | 2 +- .../profiler/queue/QueueTimeTest.java | 2 +- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/ddprof-lib/src/main/cpp/javaApi.cpp b/ddprof-lib/src/main/cpp/javaApi.cpp index 836c5029a..4fea0ed79 100644 --- a/ddprof-lib/src/main/cpp/javaApi.cpp +++ b/ddprof-lib/src/main/cpp/javaApi.cpp @@ -587,6 +587,6 @@ extern "C" DLLEXPORT void JNICALL Java_com_datadoghq_profiler_JavaProfiler_dumpContext(JNIEnv* env, jclass unused) { #ifdef DEBUG Context& ctx = Contexts::get(); - TEST_LOG("===> Context: tid:%lu, spanId=%lu, rootSpanId=%lu, checksum=%lu", OS::threadId(), ctx.spanId, ctx.rootSpanId, ctx.checksum); + TEST_LOG("===> Context: tid:%u, spanId=%llu, rootSpanId=%llu, checksum=%llu", OS::threadId(), ctx.spanId, ctx.rootSpanId, ctx.checksum); #endif // DEBUG } diff --git a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp index ef9b8559f..7763d8b9f 100644 --- a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp +++ b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp @@ -279,7 +279,7 @@ static otel_process_ctx_result otel_process_ctx_update(uint64_t monotonic_publis // Step: Prepare the new payload to be published // The payload SHOULD be ready and valid before trying to actually update the mapping. uint32_t payload_size = 0; - char *payload; + char *payload = nullptr; otel_process_ctx_result result = otel_process_ctx_encode_protobuf_payload(&payload, &payload_size, *data); if (!result.success) return result; @@ -756,6 +756,21 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o } } + // Helper to free thread_ctx_config and its contents on failure paths. + // This prevents scan-build false positives: the struct and its heap fields + // are freed here so the caller's otel_process_ctx_read_data_drop sees null. + auto free_thread_ctx_config = [&]() { + if (!data_out->thread_ctx_config) return; + auto *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; + if (cfg->schema_version) free((void*)cfg->schema_version); + if (cfg->attribute_key_map) { + for (size_t i = 0; cfg->attribute_key_map[i]; i++) free((void*)cfg->attribute_key_map[i]); + free((void*)cfg->attribute_key_map); + } + free(cfg); + data_out->thread_ctx_config = nullptr; + }; + // Parse extra attributes (field 2) while (ptr < end_ptr) { uint8_t extra_ctx_field; @@ -773,12 +788,21 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o uint8_t kv_field; if (!read_protobuf_tag(&ptr, kv_end, &kv_field) || kv_field != 1) return false; if (!read_protobuf_string(&ptr, kv_end, key_buffer)) return false; - if (!data_out->thread_ctx_config) { - otel_thread_ctx_config_data *setup = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); - if (!setup) return false; - data_out->thread_ctx_config = setup; + otel_thread_ctx_config_data *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; + if (!cfg) { + cfg = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); + if (!cfg) return false; + if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &cfg->attribute_key_map)) { + free(cfg); + return false; + } + data_out->thread_ctx_config = cfg; + } else { + if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &cfg->attribute_key_map)) { + free_thread_ctx_config(); + return false; + } } - if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &((otel_thread_ctx_config_data *)data_out->thread_ctx_config)->attribute_key_map)) return false; } else { if (!read_protobuf_keyvalue(&ptr, kv_end, key_buffer, value_buffer)) return false; @@ -787,15 +811,19 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o // Dispatch based on key if (strcmp(key_buffer, "threadlocal.schema_version") == 0) { - otel_thread_ctx_config_data *setup = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); - if (!setup) { free(value); return false; } - setup->schema_version = value; - data_out->thread_ctx_config = setup; + if (!data_out->thread_ctx_config) { + data_out->thread_ctx_config = (const otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); + if (!data_out->thread_ctx_config) { free(value); return false; } + } + auto *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; + if (cfg->schema_version) free((void*)cfg->schema_version); + cfg->schema_version = value; } else { char *key = strdup(key_buffer); if (!key || extra_attributes_index + 2 >= extra_attributes_capacity) { free(key); free(value); + free_thread_ctx_config(); return false; } data_out->extra_attributes[extra_attributes_index] = key; diff --git a/ddprof-lib/src/test/make/Makefile b/ddprof-lib/src/test/make/Makefile index 5329170bb..6501481aa 100644 --- a/ddprof-lib/src/test/make/Makefile +++ b/ddprof-lib/src/test/make/Makefile @@ -26,7 +26,7 @@ $(OBJDIR): mkdir -p $(OBJDIR) $(OBJDIR)/%.o : ${SRCDIR}/%.cpp | $(OBJDIR) - ${CC} ${CFLAGS} -DEBUG -DPROFILER_VERSION=\"snapshot\" ${INCLUDES} -c $< -o $@ + ${CC} ${CFLAGS} -DDEBUG -DPROFILER_VERSION=\"snapshot\" ${INCLUDES} -c $< -o $@ clean : @rm -rf $(OBJDIR) diff --git a/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java b/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java index f16912930..8c0760917 100644 --- a/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java +++ b/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java @@ -45,7 +45,7 @@ public void run() { profiler.setContext(1, 2); long now = profiler.getCurrentTicks(); if (profiler.isThresholdExceeded(9, start, now)) { - profiler.recordQueueTime(start, now, getClass(), QueueTimeTest.class, ArrayBlockingQueue.class, 10, origin); +1 profiler.recordQueueTime(start, now, getClass(), QueueTimeTest.class, ArrayBlockingQueue.class, 10, origin); } profiler.clearContext(); } From 88620246e00107aa8b18fe85c42f0220d2b505b0 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Thu, 26 Mar 2026 16:26:56 -0400 Subject: [PATCH 07/11] Fix --- .../test/java/com/datadoghq/profiler/queue/QueueTimeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java b/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java index 8c0760917..f16912930 100644 --- a/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java +++ b/ddprof-test/src/test/java/com/datadoghq/profiler/queue/QueueTimeTest.java @@ -45,7 +45,7 @@ public void run() { profiler.setContext(1, 2); long now = profiler.getCurrentTicks(); if (profiler.isThresholdExceeded(9, start, now)) { -1 profiler.recordQueueTime(start, now, getClass(), QueueTimeTest.class, ArrayBlockingQueue.class, 10, origin); + profiler.recordQueueTime(start, now, getClass(), QueueTimeTest.class, ArrayBlockingQueue.class, 10, origin); } profiler.clearContext(); } From 96dcb319b8bd308f600f83abe42eefb448eeeb54 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Fri, 27 Mar 2026 09:10:57 -0400 Subject: [PATCH 08/11] Revert otel_process_ctx.cpp --- ddprof-lib/src/main/cpp/otel_process_ctx.cpp | 48 ++++---------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp index 7763d8b9f..ef9b8559f 100644 --- a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp +++ b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp @@ -279,7 +279,7 @@ static otel_process_ctx_result otel_process_ctx_update(uint64_t monotonic_publis // Step: Prepare the new payload to be published // The payload SHOULD be ready and valid before trying to actually update the mapping. uint32_t payload_size = 0; - char *payload = nullptr; + char *payload; otel_process_ctx_result result = otel_process_ctx_encode_protobuf_payload(&payload, &payload_size, *data); if (!result.success) return result; @@ -756,21 +756,6 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o } } - // Helper to free thread_ctx_config and its contents on failure paths. - // This prevents scan-build false positives: the struct and its heap fields - // are freed here so the caller's otel_process_ctx_read_data_drop sees null. - auto free_thread_ctx_config = [&]() { - if (!data_out->thread_ctx_config) return; - auto *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; - if (cfg->schema_version) free((void*)cfg->schema_version); - if (cfg->attribute_key_map) { - for (size_t i = 0; cfg->attribute_key_map[i]; i++) free((void*)cfg->attribute_key_map[i]); - free((void*)cfg->attribute_key_map); - } - free(cfg); - data_out->thread_ctx_config = nullptr; - }; - // Parse extra attributes (field 2) while (ptr < end_ptr) { uint8_t extra_ctx_field; @@ -788,21 +773,12 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o uint8_t kv_field; if (!read_protobuf_tag(&ptr, kv_end, &kv_field) || kv_field != 1) return false; if (!read_protobuf_string(&ptr, kv_end, key_buffer)) return false; - otel_thread_ctx_config_data *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; - if (!cfg) { - cfg = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); - if (!cfg) return false; - if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &cfg->attribute_key_map)) { - free(cfg); - return false; - } - data_out->thread_ctx_config = cfg; - } else { - if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &cfg->attribute_key_map)) { - free_thread_ctx_config(); - return false; - } + if (!data_out->thread_ctx_config) { + otel_thread_ctx_config_data *setup = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); + if (!setup) return false; + data_out->thread_ctx_config = setup; } + if (!read_protobuf_array_value_strings(&ptr, kv_end, value_buffer, &((otel_thread_ctx_config_data *)data_out->thread_ctx_config)->attribute_key_map)) return false; } else { if (!read_protobuf_keyvalue(&ptr, kv_end, key_buffer, value_buffer)) return false; @@ -811,19 +787,15 @@ static otel_process_ctx_result otel_process_ctx_encode_protobuf_payload(char **o // Dispatch based on key if (strcmp(key_buffer, "threadlocal.schema_version") == 0) { - if (!data_out->thread_ctx_config) { - data_out->thread_ctx_config = (const otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); - if (!data_out->thread_ctx_config) { free(value); return false; } - } - auto *cfg = (otel_thread_ctx_config_data *)data_out->thread_ctx_config; - if (cfg->schema_version) free((void*)cfg->schema_version); - cfg->schema_version = value; + otel_thread_ctx_config_data *setup = (otel_thread_ctx_config_data *) calloc(1, sizeof(otel_thread_ctx_config_data)); + if (!setup) { free(value); return false; } + setup->schema_version = value; + data_out->thread_ctx_config = setup; } else { char *key = strdup(key_buffer); if (!key || extra_attributes_index + 2 >= extra_attributes_capacity) { free(key); free(value); - free_thread_ctx_config(); return false; } data_out->extra_attributes[extra_attributes_index] = key; From 9fb1098690ab5edb852e4ce1cb9f8fea98a12b6c Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 31 Mar 2026 00:03:43 +0000 Subject: [PATCH 09/11] Fix uninitialized varible --- ddprof-lib/src/main/cpp/otel_process_ctx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp index ef9b8559f..96cf918fb 100644 --- a/ddprof-lib/src/main/cpp/otel_process_ctx.cpp +++ b/ddprof-lib/src/main/cpp/otel_process_ctx.cpp @@ -279,7 +279,7 @@ static otel_process_ctx_result otel_process_ctx_update(uint64_t monotonic_publis // Step: Prepare the new payload to be published // The payload SHOULD be ready and valid before trying to actually update the mapping. uint32_t payload_size = 0; - char *payload; + char *payload = nullptr; otel_process_ctx_result result = otel_process_ctx_encode_protobuf_payload(&payload, &payload_size, *data); if (!result.success) return result; From c14703d53478e80a5d8019dc08c2ff52ca0fd176 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 31 Mar 2026 13:08:24 +0000 Subject: [PATCH 10/11] scanBuild to include subdirectories --- ddprof-lib/src/test/make/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ddprof-lib/src/test/make/Makefile b/ddprof-lib/src/test/make/Makefile index 32715774c..c2fe3c9e5 100644 --- a/ddprof-lib/src/test/make/Makefile +++ b/ddprof-lib/src/test/make/Makefile @@ -2,8 +2,8 @@ CC := g++ SRCDIR := ../../main/cpp OBJDIR := ./../../../build/scanbuild_obj CFLAGS := -O0 -Wall -std=c++17 -fno-omit-frame-pointer -momit-leaf-frame-pointer -fvisibility=hidden -SRCS := ${wildcard ${SRCDIR}/*.cpp } -OBJS=${patsubst ${SRCDIR}/%.cpp,${OBJDIR}/%.o,${SRCS}} +SRCS := $(shell find ${SRCDIR} -name '*.cpp') +OBJS := $(patsubst ${SRCDIR}/%.cpp,${OBJDIR}/%.o,$(SRCS)) INCLUDES := -I$(SRCDIR) -I$(JAVA_HOME)/include -I../../../../malloc-shim/src/main/public OS := $(shell uname -s) @@ -26,7 +26,8 @@ $(OBJDIR): mkdir -p $(OBJDIR) $(OBJDIR)/%.o : ${SRCDIR}/%.cpp | $(OBJDIR) - ${CC} ${CFLAGS} -DDEBUG -DPROFILER_VERSION=\"snapshot\" ${INCLUDES} -c $< -o $@ + @mkdir -p $(dir $@) + ${CC} ${CFLAGS} -DDEBUG -DPROFILER_VERSION=\"snapshot\" ${INCLUDES} -c $< -o $@ clean : @rm -rf $(OBJDIR) From 10ea89c1429b483063641237bc2c6367749d21fc Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 31 Mar 2026 15:32:46 +0000 Subject: [PATCH 11/11] Changes based on comments --- ddprof-lib/src/main/cpp/flightRecorder.cpp | 2 +- ddprof-lib/src/main/cpp/libraries.h | 2 +- ddprof-lib/src/main/cpp/os_linux.cpp | 2 +- ddprof-lib/src/main/cpp/profiler.h | 1 - ddprof-lib/src/main/cpp/symbols_linux.cpp | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ddprof-lib/src/main/cpp/flightRecorder.cpp b/ddprof-lib/src/main/cpp/flightRecorder.cpp index b0909ac94..1351ba966 100644 --- a/ddprof-lib/src/main/cpp/flightRecorder.cpp +++ b/ddprof-lib/src/main/cpp/flightRecorder.cpp @@ -1687,7 +1687,7 @@ Error FlightRecorder::dump(const char *filename, const int length) { ExclusiveLockGuard locker(&_rec_lock); Recording* rec = _rec; if (rec != nullptr) { - if (_filename.length() != size_t(length) || + if (_filename.length() != static_cast(length) || strncmp(filename, _filename.c_str(), length) != 0) { // if the filename to dump the recording to is specified move the current // working file there diff --git a/ddprof-lib/src/main/cpp/libraries.h b/ddprof-lib/src/main/cpp/libraries.h index 2ef25ff49..4abd980aa 100644 --- a/ddprof-lib/src/main/cpp/libraries.h +++ b/ddprof-lib/src/main/cpp/libraries.h @@ -24,7 +24,7 @@ class Libraries { // Note: Parameter is uint32_t to match lib_index packing (17 bits = max 131K libraries) CodeCache *getLibraryByIndex(uint32_t index) const { assert(_native_libs.count() >= 0); - if (index < (uint32_t)_native_libs.count()) { + if (index < static_cast(_native_libs.count())) { return _native_libs[index]; } return nullptr; diff --git a/ddprof-lib/src/main/cpp/os_linux.cpp b/ddprof-lib/src/main/cpp/os_linux.cpp index 46f5636ee..8786b2644 100644 --- a/ddprof-lib/src/main/cpp/os_linux.cpp +++ b/ddprof-lib/src/main/cpp/os_linux.cpp @@ -346,7 +346,7 @@ bool OS::getCpuDescription(char* buf, size_t size) { if (r <= 0) { return false; } - buf[size_t(r) < size ? r : size - 1] = 0; + buf[static_cast(r) < size ? r : size - 1] = 0; char* c; do { diff --git a/ddprof-lib/src/main/cpp/profiler.h b/ddprof-lib/src/main/cpp/profiler.h index 489663d45..31260784f 100644 --- a/ddprof-lib/src/main/cpp/profiler.h +++ b/ddprof-lib/src/main/cpp/profiler.h @@ -215,7 +215,6 @@ class alignas(alignof(SpinLock)) Profiler { for (int i = 0; i < CONCURRENCY_LEVEL; i++) { _calltrace_buffer[i] = NULL; - new (&_locks[i])SpinLock(); } } diff --git a/ddprof-lib/src/main/cpp/symbols_linux.cpp b/ddprof-lib/src/main/cpp/symbols_linux.cpp index 643a11aea..bcf08b080 100644 --- a/ddprof-lib/src/main/cpp/symbols_linux.cpp +++ b/ddprof-lib/src/main/cpp/symbols_linux.cpp @@ -664,7 +664,7 @@ const char* ElfParser::getDebuginfodCache() { continue; } - if (snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]) < (int)sizeof(_debuginfod_cache_buf)) { + if (snprintf(_debuginfod_cache_buf, sizeof(_debuginfod_cache_buf), "%s/%s", env_val, suffixes[i]) < static_cast(sizeof(_debuginfod_cache_buf))) { return _debuginfod_cache_buf; } }