Skip to content

Commit 8233289

Browse files
authored
Merge pull request ClickHouse#80545 from ClickHouse/sind
Fix build id lookup in SymbolIndex
2 parents ea378d6 + 9f76c9e commit 8233289

File tree

3 files changed

+27
-19
lines changed

3 files changed

+27
-19
lines changed

src/Common/StackTrace.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,10 @@ StackTrace::StackTrace(const ucontext_t & signal_context)
369369
/// Skip excessive stack frames that we have created while finding stack trace.
370370
for (size_t i = 0; i < size; ++i)
371371
{
372-
if (frame_pointers[i] == caller_address)
372+
if (frame_pointers[i] == caller_address ||
373+
/// This compensates for a hack in libunwind, see the "+ 1" in
374+
/// UnwindCursor<A, R>::stepThroughSigReturn.
375+
frame_pointers[i] == reinterpret_cast<void *>(reinterpret_cast<char *>(caller_address) + 1))
373376
{
374377
offset = i;
375378
break;

src/Common/SymbolIndex.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ String getBuildIDFromProgramHeaders(dl_phdr_info * info)
238238

239239
std::string_view view(reinterpret_cast<const char *>(info->dlpi_addr + phdr.p_vaddr), phdr.p_memsz);
240240
__msan_unpoison(view.data(), view.size());
241-
return Elf::getBuildID(view.data(), view.size());
241+
String build_id = Elf::getBuildID(view.data(), view.size());
242+
if (!build_id.empty()) // there may be multiple PT_NOTE segments
243+
return build_id;
242244
}
243245
return {};
244246
}
@@ -316,37 +318,38 @@ void collectSymbolsFromELF(
316318
dl_phdr_info * info,
317319
std::vector<SymbolIndex::Symbol> & symbols,
318320
std::vector<SymbolIndex::Object> & objects,
319-
String & build_id)
321+
String & self_build_id)
320322
{
321323
String object_name;
322-
String our_build_id;
324+
String build_id;
323325

324326
#if defined (USE_MUSL)
325327
object_name = "/proc/self/exe";
326-
our_build_id = Elf(object_name).getBuildID();
327-
build_id = our_build_id;
328+
build_id = Elf(object_name).getBuildID();
329+
self_build_id = build_id;
328330
#else
329331
/// MSan does not know that the program segments in memory are initialized.
330332
__msan_unpoison(info, sizeof(*info));
331333
__msan_unpoison_string(info->dlpi_name);
332334

333335
object_name = info->dlpi_name;
334-
our_build_id = getBuildIDFromProgramHeaders(info);
336+
build_id = getBuildIDFromProgramHeaders(info);
335337

336338
/// If the name is empty and there is a non-empty build-id - it's main executable.
337339
/// Find a elf file for the main executable and set the build-id.
338340
if (object_name.empty())
339341
{
340342
object_name = "/proc/self/exe";
341343

342-
if (our_build_id.empty())
343-
our_build_id = Elf(object_name).getBuildID();
344-
345344
if (build_id.empty())
346-
build_id = our_build_id;
345+
build_id = Elf(object_name).getBuildID();
346+
347+
if (self_build_id.empty())
348+
self_build_id = build_id;
347349
}
348350
#endif
349351

352+
/// Note: we load ELF from file; this doesn't work for vdso because it's only present in memory.
350353
std::error_code ec;
351354
std::filesystem::path canonical_path = std::filesystem::canonical(object_name, ec);
352355

@@ -405,17 +408,18 @@ void collectSymbolsFromELF(
405408

406409
String file_build_id = object.elf->getBuildID();
407410

408-
if (our_build_id != file_build_id)
411+
if (build_id != file_build_id)
409412
{
410-
/// If debug info doesn't correspond to our binary, fallback to the info in our binary.
413+
/// If the separate debuginfo binary doesn't correspond to the loaded binary, fallback to
414+
/// the info in the loaded binary.
411415
if (object_name != canonical_path)
412416
{
413417
object_name = canonical_path;
414418
object.elf = std::make_unique<Elf>(object_name);
415419

416420
/// But it can still be outdated, for example, if executable file was deleted from filesystem and replaced by another file.
417421
file_build_id = object.elf->getBuildID();
418-
if (our_build_id != file_build_id)
422+
if (build_id != file_build_id)
419423
return;
420424
}
421425
else
@@ -445,7 +449,7 @@ int collectSymbols(dl_phdr_info * info, size_t, void * data_ptr)
445449
SymbolIndex::Data & data = *reinterpret_cast<SymbolIndex::Data *>(data_ptr);
446450

447451
collectSymbolsFromProgramHeaders(info, data.symbols);
448-
collectSymbolsFromELF(info, data.symbols, data.objects, data.build_id);
452+
collectSymbolsFromELF(info, data.symbols, data.objects, data.self_build_id);
449453

450454
/* Continue iterations */
451455
return 0;
@@ -499,10 +503,10 @@ const SymbolIndex::Object * SymbolIndex::findObject(const void * address) const
499503
String SymbolIndex::getBuildIDHex() const
500504
{
501505
String build_id_hex;
502-
build_id_hex.resize(data.build_id.size() * 2);
506+
build_id_hex.resize(data.self_build_id.size() * 2);
503507

504508
char * pos = build_id_hex.data();
505-
for (auto c : data.build_id)
509+
for (auto c : data.self_build_id)
506510
{
507511
writeHexByteUppercase(c, pos);
508512
pos += 2;

src/Common/SymbolIndex.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ class SymbolIndex : private boost::noncopyable
4646
const std::vector<Object> & objects() const { return data.objects; }
4747

4848
/// The BuildID that is generated by compiler.
49-
String getBuildID() const { return data.build_id; }
49+
String getBuildID() const { return data.self_build_id; }
5050
String getBuildIDHex() const;
5151

5252
struct Data
5353
{
5454
std::vector<Symbol> symbols;
5555
std::vector<Object> objects;
56-
String build_id;
56+
/// BuildID from the Object corresponding to main executable (as opposed to dynamic libraries).
57+
String self_build_id;
5758
};
5859
private:
5960
Data data;

0 commit comments

Comments
 (0)