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

fix(symbolize): cleanup #1048

Merged
merged 1 commit into from
Jan 8, 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
75 changes: 39 additions & 36 deletions src/symbolize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,54 +57,53 @@
#if defined(HAVE_SYMBOLIZE)

# include <algorithm>
# include <cstdlib>
# include <cstring>
# include <limits>

# include "demangle.h"
# include "symbolize.h"

namespace google {

// We don't use assert() since it's not guaranteed to be
// async-signal-safe. Instead we define a minimal assertion
// macro. So far, we don't need pretty printing for __FILE__, etc.
# define GLOG_SAFE_ASSERT(expr) ((expr) ? 0 : (std::abort(), 0))

// A wrapper for abort() to make it callable in ? :.
static int AssertFail() {
abort();
return 0; // Should not reach.
}

# define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail())
namespace google {

static SymbolizeCallback g_symbolize_callback = nullptr;
void InstallSymbolizeCallback(SymbolizeCallback callback) {
g_symbolize_callback = callback;
}
namespace {

static SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback =
nullptr;
void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback) {
g_symbolize_open_object_file_callback = callback;
}
SymbolizeCallback g_symbolize_callback = nullptr;
SymbolizeOpenObjectFileCallback g_symbolize_open_object_file_callback = nullptr;

// This function wraps the Demangle function to provide an interface
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
// get inlined.
static ATTRIBUTE_NOINLINE void DemangleInplace(char* out, size_t out_size) {
ATTRIBUTE_NOINLINE
void DemangleInplace(char* out, size_t out_size) {
char demangled[256]; // Big enough for sane demangled symbols.
if (Demangle(out, demangled, sizeof(demangled))) {
// Demangling succeeded. Copy to out if the space allows.
size_t len = strlen(demangled);
if (len + 1 <= out_size) { // +1 for '\0'.
SAFE_ASSERT(len < sizeof(demangled));
GLOG_SAFE_ASSERT(len < sizeof(demangled));
memmove(out, demangled, len + 1);
}
}
}

} // namespace

void InstallSymbolizeCallback(SymbolizeCallback callback) {
g_symbolize_callback = callback;
}

void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback) {
g_symbolize_open_object_file_callback = callback;
}

} // namespace google

# if defined(__ELF__)
Expand Down Expand Up @@ -134,29 +133,33 @@ static ATTRIBUTE_NOINLINE void DemangleInplace(char* out, size_t out_size) {
# include "glog/raw_logging.h"
# include "symbolize.h"

namespace google {

namespace {

// Re-runs run until it doesn't cause EINTR.
// Similar to the TEMP_FAILURE_RETRY macro from GNU C.
template <class Functor>
auto FailureRetry(Functor run, int error = EINTR) noexcept(noexcept(run())) {
decltype(run()) result;

do {
} while ((result = run()) == -1 && errno == error);
while ((result = run()) == -1 && errno == error) {
}

return result;
}

namespace google {
} // namespace

// Read up to "count" bytes from "offset" in the file pointed by file
// descriptor "fd" into the buffer starting at "buf" while handling short reads
// and EINTR. On success, return the number of bytes read. Otherwise, return
// -1.
static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count,
const size_t offset) {
SAFE_ASSERT(fd >= 0);
SAFE_ASSERT(count <=
static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
GLOG_SAFE_ASSERT(fd >= 0);
GLOG_SAFE_ASSERT(count <=
static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
char* buf0 = reinterpret_cast<char*>(buf);
size_t num_bytes = 0;
while (num_bytes < count) {
Expand All @@ -172,7 +175,7 @@ static ssize_t ReadFromOffset(const int fd, void* buf, const size_t count,
}
num_bytes += static_cast<size_t>(len);
}
SAFE_ASSERT(num_bytes <= count);
GLOG_SAFE_ASSERT(num_bytes <= count);
return static_cast<ssize_t>(num_bytes);
}

Expand Down Expand Up @@ -219,9 +222,9 @@ static ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(const int fd,
if (len == -1) {
return false;
}
SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
GLOG_SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
const size_t num_headers_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0]));
GLOG_SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0]));
for (size_t j = 0; j < num_headers_in_buf; ++j) {
if (buf[j].sh_type == type) {
*out = buf[j];
Expand Down Expand Up @@ -315,9 +318,9 @@ static ATTRIBUTE_NOINLINE bool FindSymbol(uint64_t pc, const int fd, char* out,
size_t num_symbols_to_read = std::min(NUM_SYMBOLS, num_symbols - i);
const ssize_t len =
ReadFromOffset(fd, &buf, sizeof(buf[0]) * num_symbols_to_read, offset);
SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
GLOG_SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read);
GLOG_SAFE_ASSERT(num_symbols_in_buf <= num_symbols_to_read);
for (unsigned j = 0; j < num_symbols_in_buf; ++j) {
const ElfW(Sym)& symbol = buf[j];
uint64_t start_address = symbol.st_value;
Expand Down Expand Up @@ -416,8 +419,8 @@ class LineReader {
eod_ = buf_ + num_bytes;
bol_ = buf_;
} else {
bol_ = eol_ + 1; // Advance to the next line in the buffer.
SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
bol_ = eol_ + 1; // Advance to the next line in the buffer.
GLOG_SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
if (!HasCompleteLine()) {
const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_);
// Move the trailing incomplete line to the beginning.
Expand Down Expand Up @@ -492,7 +495,7 @@ static char* GetHex(const char* start, const char* end, uint64_t* hex) {
break;
}
}
SAFE_ASSERT(p <= end);
GLOG_SAFE_ASSERT(p <= end);
return const_cast<char*>(p);
}

Expand Down Expand Up @@ -715,7 +718,7 @@ static char* itoa_r(uintptr_t i, char* buf, size_t sz, unsigned base,
// buffer size |dest_size| and guarantees that |dest| is null-terminated.
static void SafeAppendString(const char* source, char* dest, size_t dest_size) {
size_t dest_string_length = strlen(dest);
SAFE_ASSERT(dest_string_length < dest_size);
GLOG_SAFE_ASSERT(dest_string_length < dest_size);
dest += dest_string_length;
dest_size -= dest_string_length;
strncpy(dest, source, dest_size);
Expand Down
3 changes: 2 additions & 1 deletion src/symbolize.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2006, Google Inc.
// Copyright (c) 2024, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -132,6 +132,7 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
// (including the null-terminator).
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&,
char*, size_t);
GLOG_EXPORT
void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback);

Expand Down