Skip to content

[sanitizer] Implement __sanitizer_symbolize_frame #67491

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 1 commit into from
Sep 26, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_frame)
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
// Used by LLVMSymbolizer and InternalSymbolizer.
void ParseSymbolizeDataOutput(const char *str, DataInfo *info);

// Parses repeated strings in the following format:
// <function_name>
// <var_name>
// <file_name>:<line_number>[:<column_number>]
// [<frame_offset>|??] [<size>|??] [<tag_offset>|??]
// Used by LLVMSymbolizer and InternalSymbolizer.
void ParseSymbolizeFrameOutput(const char *str,
InternalMmapVector<LocalInfo> *locals);

} // namespace __sanitizer

#endif // SANITIZER_SYMBOLIZER_INTERNAL_H
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
str = ExtractUptr(str, "\n", &info->line);
}

static void ParseSymbolizeFrameOutput(const char *str,
InternalMmapVector<LocalInfo> *locals) {
void ParseSymbolizeFrameOutput(const char *str,
InternalMmapVector<LocalInfo> *locals) {
if (internal_strncmp(str, "??", 2) == 0)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
__sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
char *Buffer, int MaxLength);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
__sanitizer_symbolize_frame(const char *ModuleName, u64 ModuleOffset,
char *Buffer, int MaxLength);
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
__sanitizer_symbolize_flush();
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
Expand Down Expand Up @@ -366,6 +369,16 @@ class InternalSymbolizer final : public SymbolizerTool {
return result;
}

bool SymbolizeFrame(uptr addr, FrameInfo *info) override {
if (&__sanitizer_symbolize_frame == nullptr)
return false;
bool result = __sanitizer_symbolize_frame(info->module, info->module_offset,
buffer_, sizeof(buffer_));
if (result)
ParseSymbolizeFrameOutput(buffer_, &info->locals);
return result;
}

void Flush() override {
if (&__sanitizer_symbolize_flush)
__sanitizer_symbolize_flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,29 @@ bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
Result.c_str()) < MaxLength;
}

bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,
char *Buffer, int MaxLength) {
std::string Result;
{
llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig();
llvm::raw_string_ostream OS(Result);
llvm::symbolize::Request Request{ModuleName, ModuleOffset};
auto Printer = std::make_unique<llvm::symbolize::LLVMPrinter>(
OS, symbolize_error_handler(OS), Config);

// TODO: it is neccessary to set proper SectionIndex here.
// object::SectionedAddress::UndefSection works for only absolute addresses.
auto ResOrErr = getDefaultSymbolizer()->symbolizeFrame(
ModuleName,
{ModuleOffset, llvm::object::SectionedAddress::UndefSection});
if (!ResOrErr)
return false;
Printer->print(Request, ResOrErr.get());
}
return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",
Result.c_str()) < MaxLength;
}

void __sanitizer_symbolize_flush() {
if (Symbolizer)
Symbolizer->flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ $AR rc symbolizer.a sanitizer_symbolize.o sanitizer_wrappers.o

SYMBOLIZER_API_LIST=__sanitizer_symbolize_code
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_data
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_frame
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_flush
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_demangle
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_set_demangle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ __sanitizer_symbolize_code T
__sanitizer_symbolize_data T
__sanitizer_symbolize_demangle T
__sanitizer_symbolize_flush T
__sanitizer_symbolize_frame T
__sanitizer_symbolize_set_demangle T
__sanitizer_symbolize_set_inline_frames T
__strdup U
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset,
bool SymbolizeInlineFrames);
bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
char *Buffer, int MaxLength);
bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,
char *Buffer, int MaxLength);
void __sanitizer_print_stack_trace();
bool __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
int MaxLength);
Expand Down Expand Up @@ -132,6 +134,40 @@ void TestData() {
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]]
}

__attribute__((noinline)) std::string SymbolizeLocalVars(FrameInfo frame) {
auto modul_offset = GetModuleAndOffset(frame.address);
char buffer[1024] = {};
ScopedInSymbolizer in_symbolizer;
__sanitizer_symbolize_frame(modul_offset.first, modul_offset.second, buffer,
std::size(buffer));
return buffer;
}

__attribute__((
noinline,
no_sanitize_address /* Asan merges allocas destroying variable DI*/)) void
TestFrame() {
volatile int var = 1;
void *address = GetPC();
fprintf(stderr, "%s: %s\n", __FUNCTION__,
SymbolizeLocalVars({
0,
"",
"",
reinterpret_cast<void *>(
reinterpret_cast<uintptr_t>(address)),
})
.c_str());
// CHECK-LABEL: TestFrame: TestFrame
// CHECK-NEXT: var
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]]
// CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
// CHECK-NEXT: TestFrame
// CHECK-NEXT: address
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 16]]
// CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
}

void TestDemangle() {
char out[128];
assert(!__sanitizer_symbolize_demangle("1A", out, sizeof(out)));
Expand All @@ -149,5 +185,6 @@ int main() {
TestNoInline();
TestLongFunctionNames();
TestData();
TestFrame();
TestDemangle();
}