Skip to content

Commit 7a36e61

Browse files
author
Alexey Samsonov
committed
[Sanitizer] Refactor symbolization interface: use class instead of several functions. Move some code around to get rid of extra source files
llvm-svn: 190410
1 parent 74c652e commit 7a36e61

26 files changed

+725
-866
lines changed

compiler-rt/lib/asan/asan_report.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ static bool IsASCII(unsigned char c) {
180180
static const char *MaybeDemangleGlobalName(const char *name) {
181181
// We can spoil names of globals with C linkage, so use an heuristic
182182
// approach to check if the name should be demangled.
183-
return (name[0] == '_' && name[1] == 'Z') ? Demangle(name) : name;
183+
return (name[0] == '_' && name[1] == 'Z') ? getSymbolizer()->Demangle(name)
184+
: name;
184185
}
185186

186187
// Check if the global is a zero-terminated ASCII string. If so, print it.
@@ -550,12 +551,12 @@ class ScopedInErrorReport {
550551

551552
static void ReportSummary(const char *error_type, StackTrace *stack) {
552553
if (!stack->size) return;
553-
if (IsSymbolizerAvailable()) {
554+
if (getSymbolizer()->IsAvailable()) {
554555
AddressInfo ai;
555556
// Currently, we include the first stack frame into the report summary.
556557
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
557558
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
558-
SymbolizeCode(pc, &ai, 1);
559+
getSymbolizer()->SymbolizeCode(pc, &ai, 1);
559560
ReportErrorSummary(error_type,
560561
StripPathPrefix(ai.file,
561562
common_flags()->strip_path_prefix),

compiler-rt/lib/asan/asan_rtl.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,8 @@ void __asan_init() {
532532

533533
// Start symbolizer process if necessary.
534534
if (common_flags()->symbolize) {
535-
InitializeExternalSymbolizer(common_flags()->external_symbolizer_path);
535+
getSymbolizer()
536+
->InitializeExternal(common_flags()->external_symbolizer_path);
536537
}
537538

538539
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited

compiler-rt/lib/lsan/lsan.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ void Init() {
5353

5454
// Start symbolizer process if necessary.
5555
if (common_flags()->symbolize) {
56-
InitializeExternalSymbolizer(common_flags()->external_symbolizer_path);
56+
getSymbolizer()
57+
->InitializeExternal(common_flags()->external_symbolizer_path);
5758
}
5859

5960
InitCommonLsan();

compiler-rt/lib/lsan/lsan_common.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,8 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
402402
static const uptr kMaxAddrFrames = 16;
403403
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
404404
for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
405-
uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
406-
kMaxAddrFrames);
405+
uptr addr_frames_num =
406+
getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
407407
for (uptr i = 0; i < addr_frames_num; i++) {
408408
Suppression* s;
409409
if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||

compiler-rt/lib/msan/msan.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,8 @@ void __msan_init() {
324324
}
325325

326326
const char *external_symbolizer = common_flags()->external_symbolizer_path;
327-
bool symbolizer_started = InitializeExternalSymbolizer(external_symbolizer);
327+
bool symbolizer_started =
328+
getSymbolizer()->InitializeExternal(external_symbolizer);
328329
if (external_symbolizer && external_symbolizer[0]) {
329330
CHECK(symbolizer_started);
330331
}

compiler-rt/lib/msan/msan_report.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ static void DescribeOrigin(u32 origin) {
5252
Printf("%s", d.Origin());
5353
Printf(" %sUninitialized value was created by an allocation of '%s%s%s'"
5454
" in the stack frame of function '%s%s%s'%s\n",
55-
d.Origin(), d.Name(), s, d.Origin(), d.Name(), Demangle(sep + 1),
56-
d.Origin(), d.End());
55+
d.Origin(), d.Name(), s, d.Origin(), d.Name(),
56+
getSymbolizer()->Demangle(sep + 1), d.Origin(), d.End());
5757
InternalFree(s);
5858
} else {
5959
uptr size = 0;
@@ -65,12 +65,12 @@ static void DescribeOrigin(u32 origin) {
6565
}
6666

6767
static void ReportSummary(const char *error_type, StackTrace *stack) {
68-
if (!stack->size || !IsSymbolizerAvailable()) return;
68+
if (!stack->size || !getSymbolizer()->IsAvailable()) return;
6969
AddressInfo ai;
7070
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
7171
{
7272
SymbolizerScope sym_scope;
73-
SymbolizeCode(pc, &ai, 1);
73+
getSymbolizer()->SymbolizeCode(pc, &ai, 1);
7474
}
7575
ReportErrorSummary(error_type,
7676
StripPathPrefix(ai.file,

compiler-rt/lib/sanitizer_common/CMakeLists.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ set(SANITIZER_SOURCES
1515
sanitizer_stackdepot.cc
1616
sanitizer_stacktrace.cc
1717
sanitizer_suppressions.cc
18-
sanitizer_symbolizer_itanium.cc
19-
sanitizer_symbolizer_linux.cc
20-
sanitizer_symbolizer_mac.cc
2118
sanitizer_symbolizer_win.cc
2219
sanitizer_thread_registry.cc
2320
sanitizer_win.cc)
@@ -27,8 +24,6 @@ set(SANITIZER_LIBCDEP_SOURCES
2724
sanitizer_linux_libcdep.cc
2825
sanitizer_posix_libcdep.cc
2926
sanitizer_stoptheworld_linux_libcdep.cc
30-
sanitizer_symbolizer_libcdep.cc
31-
sanitizer_symbolizer_linux_libcdep.cc
3227
sanitizer_symbolizer_posix_libcdep.cc)
3328

3429
# Explicitly list all sanitizer_common headers. Not all of these are

compiler-rt/lib/sanitizer_common/sanitizer_common.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,27 @@ void ReportErrorSummary(const char *error_type, const char *file,
146146
__sanitizer_report_error_summary(buff.data());
147147
}
148148

149+
LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
150+
full_name_ = internal_strdup(module_name);
151+
base_address_ = base_address;
152+
n_ranges_ = 0;
153+
}
154+
155+
void LoadedModule::addAddressRange(uptr beg, uptr end) {
156+
CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
157+
ranges_[n_ranges_].beg = beg;
158+
ranges_[n_ranges_].end = end;
159+
n_ranges_++;
160+
}
161+
162+
bool LoadedModule::containsAddress(uptr address) const {
163+
for (uptr i = 0; i < n_ranges_; i++) {
164+
if (ranges_[i].beg <= address && address < ranges_[i].end)
165+
return true;
166+
}
167+
return false;
168+
}
169+
149170
} // namespace __sanitizer
150171

151172
using namespace __sanitizer; // NOLINT

compiler-rt/lib/sanitizer_common/sanitizer_common.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,37 @@ uptr InternalBinarySearch(const Container &v, uptr first, uptr last,
402402
return not_found;
403403
}
404404

405+
// Represents a binary loaded into virtual memory (e.g. this can be an
406+
// executable or a shared object).
407+
class LoadedModule {
408+
public:
409+
LoadedModule(const char *module_name, uptr base_address);
410+
void addAddressRange(uptr beg, uptr end);
411+
bool containsAddress(uptr address) const;
412+
413+
const char *full_name() const { return full_name_; }
414+
uptr base_address() const { return base_address_; }
415+
416+
private:
417+
struct AddressRange {
418+
uptr beg;
419+
uptr end;
420+
};
421+
char *full_name_;
422+
uptr base_address_;
423+
static const uptr kMaxNumberOfAddressRanges = 6;
424+
AddressRange ranges_[kMaxNumberOfAddressRanges];
425+
uptr n_ranges_;
426+
};
427+
428+
// OS-dependent function that fills array with descriptions of at most
429+
// "max_modules" currently loaded modules. Returns the number of
430+
// initialized modules. If filter is nonzero, ignores modules for which
431+
// filter(full_name) is false.
432+
typedef bool (*string_predicate_t)(const char *);
433+
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
434+
string_predicate_t filter);
435+
405436
} // namespace __sanitizer
406437

407438
#endif // SANITIZER_COMMON_H

compiler-rt/lib/sanitizer_common/sanitizer_linux.cc

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void PrepareForSandboxing() {
310310
// cached mappings.
311311
MemoryMappingLayout::CacheMemoryMappings();
312312
// Same for /proc/self/exe in the symbolizer.
313-
SymbolizerPrepareForSandboxing();
313+
getSymbolizer()->PrepareForSandboxing();
314314
}
315315

316316
// ----------------- sanitizer_procmaps.h
@@ -676,6 +676,39 @@ uptr GetPageSize() {
676676
#endif
677677
}
678678

679+
static char proc_self_exe_cache_str[kMaxPathLength];
680+
static uptr proc_self_exe_cache_len = 0;
681+
682+
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
683+
uptr module_name_len = internal_readlink(
684+
"/proc/self/exe", buf, buf_len);
685+
int readlink_error;
686+
if (internal_iserror(buf_len, &readlink_error)) {
687+
if (proc_self_exe_cache_len) {
688+
// If available, use the cached module name.
689+
CHECK_LE(proc_self_exe_cache_len, buf_len);
690+
internal_strncpy(buf, proc_self_exe_cache_str, buf_len);
691+
module_name_len = internal_strlen(proc_self_exe_cache_str);
692+
} else {
693+
// We can't read /proc/self/exe for some reason, assume the name of the
694+
// binary is unknown.
695+
Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
696+
"some stack frames may not be symbolized\n", readlink_error);
697+
module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
698+
}
699+
CHECK_LT(module_name_len, buf_len);
700+
buf[module_name_len] = '\0';
701+
}
702+
return module_name_len;
703+
}
704+
705+
void CacheBinaryName() {
706+
if (!proc_self_exe_cache_len) {
707+
proc_self_exe_cache_len =
708+
ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
709+
}
710+
}
711+
679712
// Match full names of the form /path/to/base_name{-,.}*
680713
bool LibraryNameIs(const char *full_name, const char *base_name) {
681714
const char *name = full_name;

compiler-rt/lib/sanitizer_common/sanitizer_linux.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SANITIZER_LINUX_H
1414
#define SANITIZER_LINUX_H
1515

16+
#include "sanitizer_platform.h"
17+
#if SANITIZER_LINUX
1618
#include "sanitizer_common.h"
1719
#include "sanitizer_internal_defs.h"
1820

@@ -69,10 +71,13 @@ bool LibraryNameIs(const char *full_name, const char *base_name);
6971

7072
// Read the name of the current binary from /proc/self/exe.
7173
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
74+
// Cache the value of /proc/self/exe.
75+
void CacheBinaryName();
7276

7377
// Call cb for each region mapped by map.
7478
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
7579

7680
} // namespace __sanitizer
7781

82+
#endif // SANITIZER_LINUX
7883
#endif // SANITIZER_LINUX_H

compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#if SANITIZER_LINUX
1717

1818
#include "sanitizer_common.h"
19+
#include "sanitizer_linux.h"
20+
#include "sanitizer_placement_new.h"
1921
#include "sanitizer_procmaps.h"
2022
#include "sanitizer_stacktrace.h"
2123

@@ -25,6 +27,11 @@
2527
#include <sys/resource.h>
2628
#include <unwind.h>
2729

30+
#if !SANITIZER_ANDROID
31+
#include <elf.h>
32+
#include <link.h>
33+
#endif
34+
2835
namespace __sanitizer {
2936

3037
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
@@ -284,6 +291,63 @@ void AdjustStackSizeLinux(void *attr_, int verbosity) {
284291
}
285292
}
286293

294+
#if SANITIZER_ANDROID
295+
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
296+
string_predicate_t filter) {
297+
return 0;
298+
}
299+
#else // SANITIZER_ANDROID
300+
typedef ElfW(Phdr) Elf_Phdr;
301+
302+
struct DlIteratePhdrData {
303+
LoadedModule *modules;
304+
uptr current_n;
305+
bool first;
306+
uptr max_n;
307+
string_predicate_t filter;
308+
};
309+
310+
static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
311+
DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
312+
if (data->current_n == data->max_n)
313+
return 0;
314+
InternalScopedBuffer<char> module_name(kMaxPathLength);
315+
module_name.data()[0] = '\0';
316+
if (data->first) {
317+
data->first = false;
318+
// First module is the binary itself.
319+
ReadBinaryName(module_name.data(), module_name.size());
320+
} else if (info->dlpi_name) {
321+
internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
322+
}
323+
if (module_name.data()[0] == '\0')
324+
return 0;
325+
if (data->filter && !data->filter(module_name.data()))
326+
return 0;
327+
void *mem = &data->modules[data->current_n];
328+
LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
329+
info->dlpi_addr);
330+
data->current_n++;
331+
for (int i = 0; i < info->dlpi_phnum; i++) {
332+
const Elf_Phdr *phdr = &info->dlpi_phdr[i];
333+
if (phdr->p_type == PT_LOAD) {
334+
uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
335+
uptr cur_end = cur_beg + phdr->p_memsz;
336+
cur_module->addAddressRange(cur_beg, cur_end);
337+
}
338+
}
339+
return 0;
340+
}
341+
342+
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
343+
string_predicate_t filter) {
344+
CHECK(modules);
345+
DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
346+
dl_iterate_phdr(dl_iterate_phdr_cb, &data);
347+
return data.current_n;
348+
}
349+
#endif // SANITIZER_ANDROID
350+
287351
} // namespace __sanitizer
288352

289353
#endif // SANITIZER_LINUX

compiler-rt/lib/sanitizer_common/sanitizer_mac.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sanitizer_common.h"
2626
#include "sanitizer_internal_defs.h"
2727
#include "sanitizer_libc.h"
28+
#include "sanitizer_placement_new.h"
2829
#include "sanitizer_procmaps.h"
2930

3031
#include <crt_externs.h> // for _NSGetEnviron
@@ -371,6 +372,37 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
371372
#endif
372373
}
373374

375+
uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
376+
string_predicate_t filter) {
377+
MemoryMappingLayout memory_mapping(false);
378+
memory_mapping.Reset();
379+
uptr cur_beg, cur_end, cur_offset;
380+
InternalScopedBuffer<char> module_name(kMaxPathLength);
381+
uptr n_modules = 0;
382+
for (uptr i = 0;
383+
n_modules < max_modules &&
384+
memory_mapping.Next(&cur_beg, &cur_end, &cur_offset,
385+
module_name.data(), module_name.size(), 0);
386+
i++) {
387+
const char *cur_name = module_name.data();
388+
if (cur_name[0] == '\0')
389+
continue;
390+
if (filter && !filter(cur_name))
391+
continue;
392+
LoadedModule *cur_module = 0;
393+
if (n_modules > 0 &&
394+
0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
395+
cur_module = &modules[n_modules - 1];
396+
} else {
397+
void *mem = &modules[n_modules];
398+
cur_module = new(mem) LoadedModule(cur_name, cur_beg);
399+
n_modules++;
400+
}
401+
cur_module->addAddressRange(cur_beg, cur_end);
402+
}
403+
return n_modules;
404+
}
405+
374406
} // namespace __sanitizer
375407

376408
#endif // SANITIZER_MAC

compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ void StackTrace::PrintStack(const uptr *addr, uptr size,
8686
frame_num++;
8787
}
8888
}
89-
if (symbolize && addr_frames_num == 0 && &SymbolizeCode) {
89+
if (symbolize && addr_frames_num == 0 && &getSymbolizer) {
9090
// Use our own (online) symbolizer, if necessary.
91-
addr_frames_num = SymbolizeCode(pc, addr_frames.data(),
92-
addr_frames.size());
91+
addr_frames_num = getSymbolizer()->SymbolizeCode(
92+
pc, addr_frames.data(), addr_frames.size());
9393
for (uptr j = 0; j < addr_frames_num; j++) {
9494
AddressInfo &info = addr_frames[j];
9595
PrintStackFramePrefix(frame_num, pc);

0 commit comments

Comments
 (0)