Skip to content
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

[PROF-9088] Fix symbolization for binaries with compressed debug information #395

Merged
merged 2 commits into from
Mar 28, 2024
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
9 changes: 8 additions & 1 deletion cmake/Helperfunc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ function(add_exe name)
set(exe_libraries "")
set(exe_definitions "")
set(exe_include_dirs "")
set(compress_debug_section OFF)

foreach(arg IN LISTS ARGN)
if(arg STREQUAL "LIBRARIES")
set(cur_var "libraries")
elseif(arg STREQUAL "DEFINITIONS")
set(cur_var "definitions")
elseif(arg STREQUAL "COMPRESS_DEBUG_SECTION")
set(compress_debug_section ON)
else()
list(APPEND exe_${cur_var} ${arg})

if(cur_var STREQUAL "sources")
get_filename_component(src_dir ${arg} DIRECTORY)
list(APPEND exe_include_dirs ${src_dir})
Expand All @@ -42,6 +44,11 @@ function(add_exe name)
target_link_libraries(${name} PRIVATE ${exe_libraries})
list(REMOVE_DUPLICATES exe_include_dirs)
target_include_directories(${name} PRIVATE ${exe_include_dirs})

if(${compress_debug_section})
target_compile_options(${name} PUBLIC "-gz=zlib")
target_link_options(${name} PRIVATE -gz=zlib)
endif()
endfunction()

# Set a target to statically link libstdc++
Expand Down
20 changes: 15 additions & 5 deletions include/symbolizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,34 @@ class Symbolizer {
};

struct BlazeSymbolizerWrapper {
static blaze_symbolizer_opts create_opts(bool inlined_fns) {
static blaze_symbolizer_opts create_opts_with_debug(bool inlined_fns) {
return blaze_symbolizer_opts{.type_size = sizeof(blaze_symbolizer_opts),
.auto_reload = false,
.code_info = true,
.inlined_fns = inlined_fns,
.demangle = false,
.reserved = {}};
}

explicit BlazeSymbolizerWrapper(std::string elf_src, bool inlined_fns)
: opts(create_opts(inlined_fns)),
static blaze_symbolizer_opts create_opts_no_debug() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think you need to change blaze_symbolizer_opts, calling blaze_symbolize_elf_virt_offsets with blaze_symbolize_src_elf.debug_syms set to false should be enough.

return blaze_symbolizer_opts{.type_size = sizeof(blaze_symbolizer_opts),
.auto_reload = false,
.code_info = false,
.inlined_fns = false,
.demangle = false,
.reserved = {}};
}
explicit BlazeSymbolizerWrapper(std::string elf_src, bool inlined_fns,
Copy link
Collaborator

Choose a reason for hiding this comment

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

consecutive bool arguments are error prone

bool use_debug = true)
: opts(use_debug ? create_opts_with_debug(inlined_fns)
: create_opts_no_debug()),
_symbolizer(blaze_symbolizer_new_opts(&opts)),
_elf_src(std::move(elf_src)) {}
_elf_src(std::move(elf_src)), _use_debug(use_debug) {}
blaze_symbolizer_opts opts;
std::unique_ptr<blaze_symbolizer, BlazeSymbolizerDeleter> _symbolizer;
ddprof::HeterogeneousLookupStringMap<std::string> _demangled_names;
std::string _elf_src;
bool _visited{true};
bool _use_debug;
Copy link
Collaborator

Choose a reason for hiding this comment

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

public members don't need an underscore prefix

};

std::unordered_map<FileInfoId_t, BlazeSymbolizerWrapper> _symbolizer_map;
Expand Down
48 changes: 30 additions & 18 deletions src/symbolizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,34 @@ DDRes Symbolizer::symbolize_pprof(std::span<ElfAddress_t> elf_addrs,
return ddres_warn(DD_WHAT_PPROF); // or some other error handling
}
ddprof::HeterogeneousLookupStringMap<std::string> *demangled_names = nullptr;
const auto it = _symbolizer_map.find(file_id);
const char *resolved_src = elf_src.c_str();
// This is to avoid we change the path at every call (for different pids)
// The cache takes into account the first path given
if (it != _symbolizer_map.end()) {
resolved_src = it->second._elf_src.c_str();
symbolizer = it->second._symbolizer.get();
it->second._visited = true;
demangled_names = &(it->second._demangled_names);
} else {
auto pair = _symbolizer_map.emplace(
file_id, BlazeSymbolizerWrapper(elf_src, inlined_functions));
DDPROF_DCHECK_FATAL(pair.second, "Unable to insert symbolizer object");
symbolizer = pair.first->second._symbolizer.get();
demangled_names = &(pair.first->second._demangled_names);
}
bool retry_symbolization = true;
bool use_debug = true;
const blaze_result *blaze_res = nullptr;
if (!_disable_symbolization) {
while (retry_symbolization && !_disable_symbolization) {
const auto it = _symbolizer_map.find(file_id);
Copy link
Collaborator

Choose a reason for hiding this comment

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

the inner loop could be refactored into another function

const char *resolved_src = elf_src.c_str();
// This is to avoid we change the path at every call (for different pids)
// The cache takes into account the first path given
if (it != _symbolizer_map.end()) {
resolved_src = it->second._elf_src.c_str();
symbolizer = it->second._symbolizer.get();
it->second._visited = true;
demangled_names = &(it->second._demangled_names);
retry_symbolization = false;
use_debug = it->second._use_debug;
} else {
auto pair = _symbolizer_map.emplace(
file_id,
BlazeSymbolizerWrapper(elf_src, inlined_functions, use_debug));
DDPROF_DCHECK_FATAL(pair.second, "Unable to insert symbolizer object");
symbolizer = pair.first->second._symbolizer.get();
demangled_names = &(pair.first->second._demangled_names);
}
// Initialize the src_elf structure
const blaze_symbolize_src_elf src_elf{
.type_size = sizeof(blaze_symbolize_src_elf),
.path = resolved_src,
.debug_syms = true,
.debug_syms = use_debug,
.reserved = {},
};

Expand All @@ -97,7 +102,14 @@ DDRes Symbolizer::symbolize_pprof(std::span<ElfAddress_t> elf_addrs,
_reported_addr_format == k_elf ? elf_addrs[i] : process_addrs[i],
(*demangled_names), map_info, *cur_sym, write_index, locations));
}
} else if (retry_symbolization && use_debug) {
LG_NTC("Unable to symbolize with debug symbols, retrying for %s",
elf_src.c_str());
_symbolizer_map.erase(file_id);
use_debug = false;
continue;
}
retry_symbolization = false;
}
// Handle the case of no blaze result
// This can happen when file descriptors are exhausted
Expand Down
4 changes: 2 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,10 @@ if(NOT CMAKE_BUILD_TYPE STREQUAL "SanitizedDebug")
add_exe(
simple_malloc-shared simple_malloc.cc
LIBRARIES dd_profiling-shared Threads::Threads CLI11 dl
DEFINITIONS USE_DD_PROFILING)
DEFINITIONS USE_DD_PROFILING COMPRESS_DEBUG_SECTION)
target_include_directories(simple_malloc-shared PRIVATE ${CMAKE_SOURCE_DIR}/include)

add_exe(simple_malloc simple_malloc.cc LIBRARIES Threads::Threads CLI11 dl)
add_exe(simple_malloc simple_malloc.cc LIBRARIES Threads::Threads CLI11 dl COMPRESS_DEBUG_SECTION)
target_include_directories(simple_malloc PRIVATE ${CMAKE_SOURCE_DIR}/include)

add_library(simple_malloc_lib SHARED simple_malloc.cc)
Expand Down