Skip to content

Commit eb0a9a1

Browse files
authored
[sanitizer] Implement __sanitizer_symbolize_frame (#67491)
__sanitizer_symbolize_frame is used by HWASAN for use after scope reports.
1 parent 1002a1d commit eb0a9a1

File tree

8 files changed

+87
-2
lines changed

8 files changed

+87
-2
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//===----------------------------------------------------------------------===//
1010
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code)
1111
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data)
12+
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_frame)
1213
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle)
1314
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush)
1415
INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle)

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res);
160160
// Used by LLVMSymbolizer and InternalSymbolizer.
161161
void ParseSymbolizeDataOutput(const char *str, DataInfo *info);
162162

163+
// Parses repeated strings in the following format:
164+
// <function_name>
165+
// <var_name>
166+
// <file_name>:<line_number>[:<column_number>]
167+
// [<frame_offset>|??] [<size>|??] [<tag_offset>|??]
168+
// Used by LLVMSymbolizer and InternalSymbolizer.
169+
void ParseSymbolizeFrameOutput(const char *str,
170+
InternalMmapVector<LocalInfo> *locals);
171+
163172
} // namespace __sanitizer
164173

165174
#endif // SANITIZER_SYMBOLIZER_INTERNAL_H

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,8 @@ void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
385385
str = ExtractUptr(str, "\n", &info->line);
386386
}
387387

388-
static void ParseSymbolizeFrameOutput(const char *str,
389-
InternalMmapVector<LocalInfo> *locals) {
388+
void ParseSymbolizeFrameOutput(const char *str,
389+
InternalMmapVector<LocalInfo> *locals) {
390390
if (internal_strncmp(str, "??", 2) == 0)
391391
return;
392392

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,9 @@ __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
324324
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
325325
__sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
326326
char *Buffer, int MaxLength);
327+
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
328+
__sanitizer_symbolize_frame(const char *ModuleName, u64 ModuleOffset,
329+
char *Buffer, int MaxLength);
327330
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void
328331
__sanitizer_symbolize_flush();
329332
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool
@@ -366,6 +369,16 @@ class InternalSymbolizer final : public SymbolizerTool {
366369
return result;
367370
}
368371

372+
bool SymbolizeFrame(uptr addr, FrameInfo *info) override {
373+
if (&__sanitizer_symbolize_frame == nullptr)
374+
return false;
375+
bool result = __sanitizer_symbolize_frame(info->module, info->module_offset,
376+
buffer_, sizeof(buffer_));
377+
if (result)
378+
ParseSymbolizeFrameOutput(buffer_, &info->locals);
379+
return result;
380+
}
381+
369382
void Flush() override {
370383
if (&__sanitizer_symbolize_flush)
371384
__sanitizer_symbolize_flush();

compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,29 @@ bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
115115
Result.c_str()) < MaxLength;
116116
}
117117

118+
bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,
119+
char *Buffer, int MaxLength) {
120+
std::string Result;
121+
{
122+
llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig();
123+
llvm::raw_string_ostream OS(Result);
124+
llvm::symbolize::Request Request{ModuleName, ModuleOffset};
125+
auto Printer = std::make_unique<llvm::symbolize::LLVMPrinter>(
126+
OS, symbolize_error_handler(OS), Config);
127+
128+
// TODO: it is neccessary to set proper SectionIndex here.
129+
// object::SectionedAddress::UndefSection works for only absolute addresses.
130+
auto ResOrErr = getDefaultSymbolizer()->symbolizeFrame(
131+
ModuleName,
132+
{ModuleOffset, llvm::object::SectionedAddress::UndefSection});
133+
if (!ResOrErr)
134+
return false;
135+
Printer->print(Request, ResOrErr.get());
136+
}
137+
return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",
138+
Result.c_str()) < MaxLength;
139+
}
140+
118141
void __sanitizer_symbolize_flush() {
119142
if (Symbolizer)
120143
Symbolizer->flush();

compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ $AR rc symbolizer.a sanitizer_symbolize.o sanitizer_wrappers.o
140140

141141
SYMBOLIZER_API_LIST=__sanitizer_symbolize_code
142142
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_data
143+
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_frame
143144
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_flush
144145
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_demangle
145146
SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_set_demangle

compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ __sanitizer_symbolize_code T
5959
__sanitizer_symbolize_data T
6060
__sanitizer_symbolize_demangle T
6161
__sanitizer_symbolize_flush T
62+
__sanitizer_symbolize_frame T
6263
__sanitizer_symbolize_set_demangle T
6364
__sanitizer_symbolize_set_inline_frames T
6465
__strdup U

compiler-rt/test/sanitizer_common/TestCases/Linux/internal_symbolizer.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset,
1717
bool SymbolizeInlineFrames);
1818
bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,
1919
char *Buffer, int MaxLength);
20+
bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,
21+
char *Buffer, int MaxLength);
2022
void __sanitizer_print_stack_trace();
2123
bool __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
2224
int MaxLength);
@@ -132,6 +134,40 @@ void TestData() {
132134
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]]
133135
}
134136

137+
__attribute__((noinline)) std::string SymbolizeLocalVars(FrameInfo frame) {
138+
auto modul_offset = GetModuleAndOffset(frame.address);
139+
char buffer[1024] = {};
140+
ScopedInSymbolizer in_symbolizer;
141+
__sanitizer_symbolize_frame(modul_offset.first, modul_offset.second, buffer,
142+
std::size(buffer));
143+
return buffer;
144+
}
145+
146+
__attribute__((
147+
noinline,
148+
no_sanitize_address /* Asan merges allocas destroying variable DI*/)) void
149+
TestFrame() {
150+
volatile int var = 1;
151+
void *address = GetPC();
152+
fprintf(stderr, "%s: %s\n", __FUNCTION__,
153+
SymbolizeLocalVars({
154+
0,
155+
"",
156+
"",
157+
reinterpret_cast<void *>(
158+
reinterpret_cast<uintptr_t>(address)),
159+
})
160+
.c_str());
161+
// CHECK-LABEL: TestFrame: TestFrame
162+
// CHECK-NEXT: var
163+
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]]
164+
// CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
165+
// CHECK-NEXT: TestFrame
166+
// CHECK-NEXT: address
167+
// CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 16]]
168+
// CHECK-NEXT: {{-?[0-9]+ +[0-9]+}}
169+
}
170+
135171
void TestDemangle() {
136172
char out[128];
137173
assert(!__sanitizer_symbolize_demangle("1A", out, sizeof(out)));
@@ -149,5 +185,6 @@ int main() {
149185
TestNoInline();
150186
TestLongFunctionNames();
151187
TestData();
188+
TestFrame();
152189
TestDemangle();
153190
}

0 commit comments

Comments
 (0)