summaryrefslogtreecommitdiff
path: root/libsanitizer/sanitizer_common
diff options
context:
space:
mode:
authorkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-13 20:41:38 +0000
committerkcc <kcc@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-13 20:41:38 +0000
commit0328398d933acf544888379949eb5c061dfcfe02 (patch)
tree5275c09e09235f15fe0ae824d5bbef4151a7d1f9 /libsanitizer/sanitizer_common
parent85f72a88010a2885f602ca074c084e55759943ed (diff)
downloadgcc-0328398d933acf544888379949eb5c061dfcfe02.tar.gz
libsanitizer merge from upstream r221802
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217518 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer/sanitizer_common')
-rw-r--r--libsanitizer/sanitizer_common/Makefile.am2
-rw-r--r--libsanitizer/sanitizer_common/Makefile.in5
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator.h15
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.cc34
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.h9
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_coverage_libcdep.cc97
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.cc12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.h3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.cc3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.h3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform.h10
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h6
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc3
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc18
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h61
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix.cc5
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_printf.cc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.cc89
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.h11
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.cc47
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.h56
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc56
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cc130
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.h60
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer.h12
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc14
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_unwind_posix_libcdep.cc18
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_win.cc8
32 files changed, 531 insertions, 271 deletions
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
index bc1f18c2a18..c5da0c15119 100644
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -6,6 +6,7 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros
AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS)
+AM_CXXFLAGS += -std=c++11
if LIBBACKTRACE_SUPPORTED
AM_CXXFLAGS += -DSANITIZER_LIBBACKTRACE -DSANITIZER_CP_DEMANGLE \
-I $(top_srcdir)/../libbacktrace \
@@ -44,6 +45,7 @@ sanitizer_common_files = \
sanitizer_stackdepot.cc \
sanitizer_stacktrace.cc \
sanitizer_stacktrace_libcdep.cc \
+ sanitizer_stacktrace_printer.cc \
sanitizer_stoptheworld_linux_libcdep.cc \
sanitizer_suppressions.cc \
sanitizer_symbolizer.cc \
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index d82b4834efc..db02613eb81 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -78,6 +78,7 @@ am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \
sanitizer_procmaps_linux.lo sanitizer_procmaps_mac.lo \
sanitizer_stackdepot.lo sanitizer_stacktrace.lo \
sanitizer_stacktrace_libcdep.lo \
+ sanitizer_stacktrace_printer.lo \
sanitizer_stoptheworld_linux_libcdep.lo \
sanitizer_suppressions.lo sanitizer_symbolizer.lo \
sanitizer_symbolizer_libbacktrace.lo \
@@ -252,7 +253,7 @@ gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \
-Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti \
-fomit-frame-pointer -funwind-tables -fvisibility=hidden \
- -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS) \
+ -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS) -std=c++11 \
$(am__append_1)
ACLOCAL_AMFLAGS = -I m4
noinst_LTLIBRARIES = libsanitizer_common.la
@@ -283,6 +284,7 @@ sanitizer_common_files = \
sanitizer_stackdepot.cc \
sanitizer_stacktrace.cc \
sanitizer_stacktrace_libcdep.cc \
+ sanitizer_stacktrace_printer.cc \
sanitizer_stoptheworld_linux_libcdep.cc \
sanitizer_suppressions.cc \
sanitizer_symbolizer.cc \
@@ -414,6 +416,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace_libcdep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace_printer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stoptheworld_linux_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_suppressions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer.Plo@am__quote@
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.h b/libsanitizer/sanitizer_common/sanitizer_allocator.h
index fb394129202..dd5539a2087 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator.h
@@ -459,6 +459,11 @@ class SizeClassAllocator64 {
}
}
+ static uptr AdditionalSize() {
+ return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
+ GetPageSizeCached());
+ }
+
typedef SizeClassMap SizeClassMapT;
static const uptr kNumClasses = SizeClassMap::kNumClasses;
static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;
@@ -488,11 +493,6 @@ class SizeClassAllocator64 {
};
COMPILER_CHECK(sizeof(RegionInfo) >= kCacheLineSize);
- static uptr AdditionalSize() {
- return RoundUpTo(sizeof(RegionInfo) * kNumClassesRounded,
- GetPageSizeCached());
- }
-
RegionInfo *GetRegionInfo(uptr class_id) {
CHECK_LT(class_id, kNumClasses);
RegionInfo *regions = reinterpret_cast<RegionInfo*>(kSpaceBeg + kSpaceSize);
@@ -1013,12 +1013,15 @@ class LargeMmapAllocator {
if (map_size < size) return AllocatorReturnNull(); // Overflow.
uptr map_beg = reinterpret_cast<uptr>(
MmapOrDie(map_size, "LargeMmapAllocator"));
+ CHECK(IsAligned(map_beg, page_size_));
MapUnmapCallback().OnMap(map_beg, map_size);
uptr map_end = map_beg + map_size;
uptr res = map_beg + page_size_;
if (res & (alignment - 1)) // Align.
res += alignment - (res & (alignment - 1));
- CHECK_EQ(0, res & (alignment - 1));
+ CHECK(IsAligned(res, alignment));
+ CHECK(IsAligned(res, page_size_));
+ CHECK_GE(res + size, map_beg);
CHECK_LE(res + size, map_end);
Header *h = GetHeader(res);
h->size = size;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc
index d4da3206e13..f06efffb325 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_common.cc
@@ -153,23 +153,12 @@ const char *StripPathPrefix(const char *filepath,
return pos;
}
-void PrintSourceLocation(InternalScopedString *buffer, const char *file,
- int line, int column) {
- CHECK(file);
- buffer->append("%s",
- StripPathPrefix(file, common_flags()->strip_path_prefix));
- if (line > 0) {
- buffer->append(":%d", line);
- if (column > 0)
- buffer->append(":%d", column);
- }
-}
-
-void PrintModuleAndOffset(InternalScopedString *buffer, const char *module,
- uptr offset) {
- buffer->append("(%s+0x%zx)",
- StripPathPrefix(module, common_flags()->strip_path_prefix),
- offset);
+const char *StripModuleName(const char *module) {
+ if (module == 0)
+ return 0;
+ if (const char *slash_pos = internal_strrchr(module, '/'))
+ return slash_pos + 1;
+ return module;
}
void ReportErrorSummary(const char *error_message) {
@@ -215,17 +204,6 @@ bool LoadedModule::containsAddress(uptr address) const {
return false;
}
-char *StripModuleName(const char *module) {
- if (module == 0)
- return 0;
- const char *short_module_name = internal_strrchr(module, '/');
- if (short_module_name)
- short_module_name += 1;
- else
- short_module_name = module;
- return internal_strdup(short_module_name);
-}
-
static atomic_uintptr_t g_total_mmaped;
void IncreaseTotalMmap(uptr size) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
index a9db1082f48..a8924913872 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -170,10 +170,8 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size);
// Error report formatting.
const char *StripPathPrefix(const char *filepath,
const char *strip_file_prefix);
-void PrintSourceLocation(InternalScopedString *buffer, const char *file,
- int line, int column);
-void PrintModuleAndOffset(InternalScopedString *buffer,
- const char *module, uptr offset);
+// Strip the directories from the module name.
+const char *StripModuleName(const char *module);
// OS
void DisableCoreDumperIfNecessary();
@@ -207,9 +205,6 @@ void SleepForMillis(int millis);
u64 NanoTime();
int Atexit(void (*function)(void));
void SortArray(uptr *array, uptr size);
-// Strip the directories from the module name, return a new string allocated
-// with internal_strdup.
-char *StripModuleName(const char *module);
// Exit
void NORETURN Abort();
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index f55a31de77e..10f321838e8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -39,6 +39,10 @@
#define va_copy(dst, src) ((dst) = (src))
#endif // _WIN32
+#if SANITIZER_FREEBSD
+#define pthread_setname_np pthread_set_name_np
+#endif
+
#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep.cc
index 9b02cd75017..214e8a98d0f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -36,6 +36,7 @@
#include "sanitizer_mutex.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_symbolizer.h"
#include "sanitizer_flags.h"
atomic_uint32_t dump_once_guard; // Ensure that CovDump runs only once.
@@ -61,6 +62,9 @@ class CoverageData {
void AfterFork(int child_pid);
void Extend(uptr npcs);
void Add(uptr pc);
+ void IndirCall(uptr caller, uptr callee, uptr callee_cache[],
+ uptr cache_size);
+ void DumpCallerCalleePairs();
uptr *data();
uptr size();
@@ -83,6 +87,14 @@ class CoverageData {
uptr pc_array_mapped_size;
// Descriptor of the file mapped pc array.
int pc_fd;
+
+ // Caller-Callee (cc) array, size and current index.
+ static const uptr kCcArrayMaxSize = FIRST_32_SECOND_64(1 << 18, 1 << 24);
+ uptr **cc_array;
+ atomic_uintptr_t cc_array_index;
+ atomic_uintptr_t cc_array_size;
+
+
StaticSpinMutex mu;
void DirectOpen();
@@ -116,6 +128,11 @@ void CoverageData::Init() {
atomic_store(&pc_array_size, kPcArrayMaxSize, memory_order_relaxed);
atomic_store(&pc_array_index, 0, memory_order_relaxed);
}
+
+ cc_array = reinterpret_cast<uptr **>(MmapNoReserveOrDie(
+ sizeof(uptr *) * kCcArrayMaxSize, "CovInit::cc_array"));
+ atomic_store(&cc_array_size, kCcArrayMaxSize, memory_order_relaxed);
+ atomic_store(&cc_array_index, 0, memory_order_relaxed);
}
void CoverageData::ReInit() {
@@ -184,6 +201,38 @@ void CoverageData::Add(uptr pc) {
pc_array[idx] = pc;
}
+// Registers a pair caller=>callee.
+// When a given caller is seen for the first time, the callee_cache is added
+// to the global array cc_array, callee_cache[0] is set to caller and
+// callee_cache[1] is set to cache_size.
+// Then we are trying to add callee to callee_cache [2,cache_size) if it is
+// not there yet.
+// If the cache is full we drop the callee (may want to fix this later).
+void CoverageData::IndirCall(uptr caller, uptr callee, uptr callee_cache[],
+ uptr cache_size) {
+ if (!cc_array) return;
+ atomic_uintptr_t *atomic_callee_cache =
+ reinterpret_cast<atomic_uintptr_t *>(callee_cache);
+ uptr zero = 0;
+ if (atomic_compare_exchange_strong(&atomic_callee_cache[0], &zero, caller,
+ memory_order_seq_cst)) {
+ uptr idx = atomic_fetch_add(&cc_array_index, 1, memory_order_relaxed);
+ CHECK_LT(idx * sizeof(uptr),
+ atomic_load(&cc_array_size, memory_order_acquire));
+ callee_cache[1] = cache_size;
+ cc_array[idx] = callee_cache;
+ }
+ CHECK_EQ(atomic_load(&atomic_callee_cache[0], memory_order_relaxed), caller);
+ for (uptr i = 2; i < cache_size; i++) {
+ uptr was = 0;
+ if (atomic_compare_exchange_strong(&atomic_callee_cache[i], &was, callee,
+ memory_order_seq_cst))
+ return;
+ if (was == callee) // Already have this callee.
+ return;
+ }
+}
+
uptr *CoverageData::data() {
return pc_array;
}
@@ -266,6 +315,45 @@ static int CovOpenFile(bool packed, const char* name) {
return fd;
}
+// This function dumps the caller=>callee pairs into a file as a sequence of
+// lines like "module_name offset".
+void CoverageData::DumpCallerCalleePairs() {
+ uptr max_idx = atomic_load(&cc_array_index, memory_order_relaxed);
+ if (!max_idx) return;
+ auto sym = Symbolizer::GetOrInit();
+ if (!sym)
+ return;
+ InternalScopedString out(32 << 20);
+ uptr total = 0;
+ for (uptr i = 0; i < max_idx; i++) {
+ uptr *cc_cache = cc_array[i];
+ CHECK(cc_cache);
+ uptr caller = cc_cache[0];
+ uptr n_callees = cc_cache[1];
+ const char *caller_module_name = "<unknown>";
+ uptr caller_module_address = 0;
+ sym->GetModuleNameAndOffsetForPC(caller, &caller_module_name,
+ &caller_module_address);
+ for (uptr j = 2; j < n_callees; j++) {
+ uptr callee = cc_cache[j];
+ if (!callee) break;
+ total++;
+ const char *callee_module_name = "<unknown>";
+ uptr callee_module_address = 0;
+ sym->GetModuleNameAndOffsetForPC(callee, &callee_module_name,
+ &callee_module_address);
+ out.append("%s 0x%zx\n%s 0x%zx\n", caller_module_name,
+ caller_module_address, callee_module_name,
+ callee_module_address);
+ }
+ }
+ int fd = CovOpenFile(false, "caller-callee");
+ if (fd < 0) return;
+ internal_write(fd, out.data(), out.length());
+ internal_close(fd);
+ VReport(1, " CovDump: %zd caller-callee pairs written\n", total);
+}
+
// Dump the coverage on disk.
static void CovDump() {
if (!common_flags()->coverage || common_flags()->coverage_direct) return;
@@ -297,7 +385,7 @@ static void CovDump() {
CHECK_LE(diff, 0xffffffffU);
offsets.push_back(static_cast<u32>(diff));
}
- char *module_name = StripModuleName(module.data());
+ const char *module_name = StripModuleName(module.data());
if (cov_sandboxed) {
if (cov_fd >= 0) {
CovWritePacked(internal_getpid(), module_name, offsets.data(),
@@ -317,11 +405,11 @@ static void CovDump() {
vb - old_vb);
}
}
- InternalFree(module_name);
}
}
if (cov_fd >= 0)
internal_close(cov_fd);
+ coverage_data.DumpCallerCalleePairs();
#endif // !SANITIZER_WINDOWS
}
@@ -357,6 +445,11 @@ extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov() {
coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()));
}
+SANITIZER_INTERFACE_ATTRIBUTE void
+__sanitizer_cov_indir_call16(uptr callee, uptr callee_cache16[]) {
+ coverage_data.IndirCall(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()),
+ callee, callee_cache16, 16);
+}
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() {
coverage_data.Init();
diff --git a/libsanitizer/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
index a134053a719..b88814b8167 100644
--- a/libsanitizer/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc
@@ -78,7 +78,7 @@ void CovUpdateMapping(uptr caller_pc) {
text.append("%d\n", sizeof(uptr) * 8);
for (int i = 0; i < n_modules; ++i) {
- char *module_name = StripModuleName(modules[i].full_name());
+ const char *module_name = StripModuleName(modules[i].full_name());
for (unsigned j = 0; j < modules[i].n_ranges(); ++j) {
if (modules[i].address_range_executable(j)) {
uptr start = modules[i].address_range_start(j);
@@ -89,7 +89,6 @@ void CovUpdateMapping(uptr caller_pc) {
cached_mapping.SetModuleRange(start, end);
}
}
- InternalFree(module_name);
}
int err;
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cc b/libsanitizer/sanitizer_common/sanitizer_flags.cc
index 476f793c27d..d7e7118212e 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.cc
@@ -37,6 +37,7 @@ void SetCommonFlagsDefaults(CommonFlags *f) {
f->external_symbolizer_path = 0;
f->allow_addr2line = false;
f->strip_path_prefix = "";
+ f->fast_unwind_on_check = false;
f->fast_unwind_on_fatal = false;
f->fast_unwind_on_malloc = true;
f->handle_ioctl = false;
@@ -64,6 +65,8 @@ void SetCommonFlagsDefaults(CommonFlags *f) {
f->suppressions = "";
f->print_suppressions = true;
f->disable_coredump = (SANITIZER_WORDSIZE == 64);
+ f->symbolize_inline_frames = true;
+ f->stack_trace_format = "DEFAULT";
}
void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
@@ -79,6 +82,9 @@ void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
"unavailable.");
ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix",
"Strips this prefix from file paths in error reports.");
+ ParseFlag(str, &f->fast_unwind_on_check, "fast_unwind_on_check",
+ "If available, use the fast frame-pointer-based unwinder on "
+ "internal CHECK failures.");
ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal",
"If available, use the fast frame-pointer-based unwinder on fatal "
"errors.");
@@ -152,6 +158,12 @@ void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
"Disable core dumping. By default, disable_core=1 on 64-bit to avoid "
"dumping a 16T+ core file. Ignored on OSes that don't dump core by"
"default and for sanitizers that don't reserve lots of virtual memory.");
+ ParseFlag(str, &f->symbolize_inline_frames, "symbolize_inline_frames",
+ "Print inlined frames in stacktraces. Defaults to true.");
+ ParseFlag(str, &f->stack_trace_format, "stack_trace_format",
+ "Format string used to render stack frames. "
+ "See sanitizer_stacktrace_printer.h for the format description. "
+ "Use DEFAULT to get default format.");
// Do a sanity check for certain flags.
if (f->malloc_context_size < 1)
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.h b/libsanitizer/sanitizer_common/sanitizer_flags.h
index a906c9e4535..b7a50131811 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.h
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.h
@@ -30,6 +30,7 @@ struct CommonFlags {
const char *external_symbolizer_path;
bool allow_addr2line;
const char *strip_path_prefix;
+ bool fast_unwind_on_check;
bool fast_unwind_on_fatal;
bool fast_unwind_on_malloc;
bool handle_ioctl;
@@ -58,6 +59,8 @@ struct CommonFlags {
const char *suppressions;
bool print_suppressions;
bool disable_coredump;
+ bool symbolize_inline_frames;
+ const char *stack_trace_format;
};
inline CommonFlags *common_flags() {
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index 2c2a1d74be7..17b931cb535 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -158,7 +158,7 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
// pthread_get_stacksize_np() returns an incorrect stack size for the main
// thread on Mavericks. See
// https://code.google.com/p/address-sanitizer/issues/detail?id=261
- if ((GetMacosVersion() == MACOS_VERSION_MAVERICKS) && at_initialization &&
+ if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
stacksize == (1 << 19)) {
struct rlimit rl;
CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
@@ -295,6 +295,7 @@ MacosVersion GetMacosVersionInternal() {
case '1': return MACOS_VERSION_LION;
case '2': return MACOS_VERSION_MOUNTAIN_LION;
case '3': return MACOS_VERSION_MAVERICKS;
+ case '4': return MACOS_VERSION_YOSEMITE;
default: return MACOS_VERSION_UNKNOWN;
}
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.h b/libsanitizer/sanitizer_common/sanitizer_mac.h
index 63055297fef..47739f71c3c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.h
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.h
@@ -23,7 +23,8 @@ enum MacosVersion {
MACOS_VERSION_SNOW_LEOPARD,
MACOS_VERSION_LION,
MACOS_VERSION_MOUNTAIN_LION,
- MACOS_VERSION_MAVERICKS
+ MACOS_VERSION_MAVERICKS,
+ MACOS_VERSION_YOSEMITE,
};
MacosVersion GetMacosVersion();
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h
index 14594d5ce55..7064b7166b0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -47,7 +47,7 @@
# define SANITIZER_WINDOWS 0
#endif
-#if defined(__ANDROID__) || defined(ANDROID)
+#if defined(__ANDROID__)
# define SANITIZER_ANDROID 1
#else
# define SANITIZER_ANDROID 0
@@ -79,7 +79,7 @@
// For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
// change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
#ifndef SANITIZER_CAN_USE_ALLOCATOR64
-# if defined(__aarch64__)
+# if defined(__aarch64__) || defined(__mips64)
# define SANITIZER_CAN_USE_ALLOCATOR64 0
# else
# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64)
@@ -107,4 +107,10 @@
# endif
#endif
+#ifdef __mips__
+# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 10)
+#else
+# define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12)
+#endif
+
#endif // SANITIZER_PLATFORM_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
index 81a09927d79..fc2d7ba990c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -204,7 +204,8 @@
#define SANITIZER_INTERCEPT__EXIT SI_LINUX || SI_FREEBSD
#define SANITIZER_INTERCEPT_PHTREAD_MUTEX SI_NOT_WINDOWS
-#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \
+ SI_FREEBSD || SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_TLS_GET_ADDR SI_LINUX_NOT_ANDROID
@@ -226,7 +227,8 @@
#define SANITIZER_INTERCEPT_OBSTACK SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_FFLUSH SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_FCLOSE SI_NOT_WINDOWS
-#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE SI_LINUX_NOT_ANDROID || SI_MAC
+#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \
+ SI_FREEBSD || SI_LINUX_NOT_ANDROID || SI_MAC
#define SANITIZER_INTERCEPT_GETPASS SI_LINUX_NOT_ANDROID || SI_MAC
#define SANITIZER_INTERCEPT_TIMERFD SI_LINUX_NOT_ANDROID
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
index a1f04325033..8779d8adf72 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
@@ -36,7 +36,6 @@
#define uid_t __kernel_uid_t
#define gid_t __kernel_gid_t
#define off_t __kernel_off_t
-#define time_t __kernel_time_t
// This header seems to contain the definitions of _kernel_ stat* structs.
#include <asm/stat.h>
#undef ino_t
@@ -61,7 +60,7 @@ namespace __sanitizer {
} // namespace __sanitizer
#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
- && !defined(__mips__) && !defined(__sparc__)
+ && !defined(__mips__)
COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
index f5678dceccc..13d908e9f8c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -13,7 +13,19 @@
#include "sanitizer_platform.h"
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC
-
+// Tests in this file assume that off_t-dependent data structures match the
+// libc ABI. For example, struct dirent here is what readdir() function (as
+// exported from libc) returns, and not the user-facing "dirent", which
+// depends on _FILE_OFFSET_BITS setting.
+// To get this "true" dirent definition, we undefine _FILE_OFFSET_BITS below.
+#ifdef _FILE_OFFSET_BITS
+#undef _FILE_OFFSET_BITS
+#endif
+#if SANITIZER_FREEBSD
+#define _WANT_RTENTRY
+#include <sys/param.h>
+#include <sys/socketvar.h>
+#endif
#include <arpa/inet.h>
#include <dirent.h>
#include <errno.h>
@@ -551,7 +563,9 @@ namespace __sanitizer {
unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
+ unsigned IOCTL_SIOCADDRT = SIOCADDRT;
unsigned IOCTL_SIOCDARP = SIOCDARP;
+ unsigned IOCTL_SIOCDELRT = SIOCDELRT;
unsigned IOCTL_SIOCDRARP = SIOCDRARP;
unsigned IOCTL_SIOCGARP = SIOCGARP;
unsigned IOCTL_SIOCGIFENCAP = SIOCGIFENCAP;
@@ -637,8 +651,6 @@ namespace __sanitizer {
#if SANITIZER_LINUX || SANITIZER_FREEBSD
unsigned IOCTL_MTIOCGET = MTIOCGET;
unsigned IOCTL_MTIOCTOP = MTIOCTOP;
- unsigned IOCTL_SIOCADDRT = SIOCADDRT;
- unsigned IOCTL_SIOCDELRT = SIOCDELRT;
unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
index 284be11cb5f..139fe0a1821 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -72,14 +72,6 @@ namespace __sanitizer {
const unsigned struct_kernel_stat_sz = 144;
#endif
const unsigned struct_kernel_stat64_sz = 104;
-#elif defined(__sparc__) && defined(__arch64__)
- const unsigned struct___old_kernel_stat_sz = 0;
- const unsigned struct_kernel_stat_sz = 104;
- const unsigned struct_kernel_stat64_sz = 144;
-#elif defined(__sparc__) && !defined(__arch64__)
- const unsigned struct___old_kernel_stat_sz = 0;
- const unsigned struct_kernel_stat_sz = 64;
- const unsigned struct_kernel_stat64_sz = 104;
#endif
struct __sanitizer_perf_event_attr {
unsigned type;
@@ -102,7 +94,7 @@ namespace __sanitizer {
#if defined(__powerpc64__)
const unsigned struct___old_kernel_stat_sz = 0;
-#elif !defined(__sparc__)
+#else
const unsigned struct___old_kernel_stat_sz = 32;
#endif
@@ -181,18 +173,6 @@ namespace __sanitizer {
unsigned short __pad1;
unsigned long __unused1;
unsigned long __unused2;
-#elif defined(__sparc__)
-# if defined(__arch64__)
- unsigned mode;
- unsigned short __pad1;
-# else
- unsigned short __pad1;
- unsigned short mode;
- unsigned short __pad2;
-# endif
- unsigned short __seq;
- unsigned long long __unused1;
- unsigned long long __unused2;
#else
unsigned short mode;
unsigned short __pad1;
@@ -210,26 +190,6 @@ namespace __sanitizer {
struct __sanitizer_shmid_ds {
__sanitizer_ipc_perm shm_perm;
- #if defined(__sparc__)
- # if !defined(__arch64__)
- u32 __pad1;
- # endif
- long shm_atime;
- # if !defined(__arch64__)
- u32 __pad2;
- # endif
- long shm_dtime;
- # if !defined(__arch64__)
- u32 __pad3;
- # endif
- long shm_ctime;
- uptr shm_segsz;
- int shm_cpid;
- int shm_lpid;
- unsigned long shm_nattch;
- unsigned long __glibc_reserved1;
- unsigned long __glibc_reserved2;
- #else
#ifndef __powerpc__
uptr shm_segsz;
#elif !defined(__powerpc64__)
@@ -267,7 +227,6 @@ namespace __sanitizer {
uptr __unused4;
uptr __unused5;
#endif
-#endif
};
#elif SANITIZER_FREEBSD
struct __sanitizer_ipc_perm {
@@ -511,7 +470,7 @@ namespace __sanitizer {
typedef long __sanitizer___kernel_off_t;
#endif
-#if defined(__powerpc__) || defined(__aarch64__) || defined(__mips__)
+#if defined(__powerpc__) || defined(__mips__)
typedef unsigned int __sanitizer___kernel_old_uid_t;
typedef unsigned int __sanitizer___kernel_old_gid_t;
#else
@@ -564,13 +523,9 @@ namespace __sanitizer {
#else
__sanitizer_sigset_t sa_mask;
#ifndef __mips__
-#if defined(__sparc__)
- unsigned long sa_flags;
-#else
int sa_flags;
#endif
#endif
-#endif
#if SANITIZER_LINUX
void (*sa_restorer)();
#endif
@@ -790,7 +745,7 @@ struct __sanitizer_obstack {
#define IOC_NRBITS 8
#define IOC_TYPEBITS 8
-#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || defined(__sparc__)
+#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__)
#define IOC_SIZEBITS 13
#define IOC_DIRBITS 3
#define IOC_NONE 1U
@@ -820,17 +775,7 @@ struct __sanitizer_obstack {
#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK)
#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK)
#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK)
-
-#if defined(__sparc__)
-// In sparc the 14 bits SIZE field overlaps with the
-// least significant bit of DIR, so either IOC_READ or
-// IOC_WRITE shall be 1 in order to get a non-zero SIZE.
-# define IOC_SIZE(nr) \
- ((((((nr) >> 29) & 0x7) & (4U|2U)) == 0)? \
- 0 : (((nr) >> 16) & 0x3fff))
-#else
#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK)
-#endif
extern unsigned struct_arpreq_sz;
extern unsigned struct_ifreq_sz;
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc
index 24e99f9472d..229870e00dc 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc
@@ -82,9 +82,12 @@ uptr GetMaxVirtualAddress() {
// one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
// Note that with 'ulimit -s unlimited' the stack is moved away from the top
// of the address space, so simply checking the stack address is not enough.
- return (1ULL << 44) - 1; // 0x00000fffffffffffUL
+ // This should (does) work for both PowerPC64 Endian modes.
+ return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
# elif defined(__aarch64__)
return (1ULL << 39) - 1;
+# elif defined(__mips64)
+ return (1ULL << 40) - 1;
# else
return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
# endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cc b/libsanitizer/sanitizer_common/sanitizer_printf.cc
index fc0c357ba86..599f2c5d7c6 100644
--- a/libsanitizer/sanitizer_common/sanitizer_printf.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_printf.cc
@@ -111,7 +111,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
int result = 0;
result += AppendString(buff, buff_end, -1, "0x");
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
- (SANITIZER_WORDSIZE == 64) ? 12 : 8, true);
+ SANITIZER_POINTER_FORMAT_LENGTH, true);
return result;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
index e1915cb808f..a3c9c0677e2 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
@@ -16,31 +16,6 @@
namespace __sanitizer {
-struct StackDepotDesc {
- const uptr *stack;
- uptr size;
- u32 hash() const {
- // murmur2
- const u32 m = 0x5bd1e995;
- const u32 seed = 0x9747b28c;
- const u32 r = 24;
- u32 h = seed ^ (size * sizeof(uptr));
- for (uptr i = 0; i < size; i++) {
- u32 k = stack[i];
- k *= m;
- k ^= k >> r;
- k *= m;
- h *= m;
- h ^= k;
- }
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
- return h;
- }
- bool is_valid() { return size > 0 && stack; }
-};
-
struct StackDepotNode {
StackDepotNode *link;
u32 id;
@@ -56,28 +31,49 @@ struct StackDepotNode {
static const u32 kUseCountMask = (1 << kUseCountBits) - 1;
static const u32 kHashMask = ~kUseCountMask;
- typedef StackDepotDesc args_type;
+ typedef StackTrace args_type;
bool eq(u32 hash, const args_type &args) const {
u32 hash_bits =
atomic_load(&hash_and_use_count, memory_order_relaxed) & kHashMask;
if ((hash & kHashMask) != hash_bits || args.size != size) return false;
uptr i = 0;
for (; i < size; i++) {
- if (stack[i] != args.stack[i]) return false;
+ if (stack[i] != args.trace[i]) return false;
}
return true;
}
static uptr storage_size(const args_type &args) {
return sizeof(StackDepotNode) + (args.size - 1) * sizeof(uptr);
}
+ static u32 hash(const args_type &args) {
+ // murmur2
+ const u32 m = 0x5bd1e995;
+ const u32 seed = 0x9747b28c;
+ const u32 r = 24;
+ u32 h = seed ^ (args.size * sizeof(uptr));
+ for (uptr i = 0; i < args.size; i++) {
+ u32 k = args.trace[i];
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+ h *= m;
+ h ^= k;
+ }
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+ return h;
+ }
+ static bool is_valid(const args_type &args) {
+ return args.size > 0 && args.trace;
+ }
void store(const args_type &args, u32 hash) {
atomic_store(&hash_and_use_count, hash & kHashMask, memory_order_relaxed);
size = args.size;
- internal_memcpy(stack, args.stack, size * sizeof(uptr));
+ internal_memcpy(stack, args.trace, size * sizeof(uptr));
}
args_type load() const {
- args_type ret = {&stack[0], size};
- return ret;
+ return args_type(&stack[0], size);
}
StackDepotHandle get_handle() { return StackDepotHandle(this); }
@@ -97,8 +93,6 @@ void StackDepotHandle::inc_use_count_unsafe() {
StackDepotNode::kUseCountMask;
CHECK_LT(prev + 1, StackDepotNode::kMaxUseCount);
}
-uptr StackDepotHandle::size() { return node_->size; }
-uptr *StackDepotHandle::stack() { return &node_->stack[0]; }
// FIXME(dvyukov): this single reserved bit is used in TSan.
typedef StackDepotBase<StackDepotNode, 1, StackDepotNode::kTabSizeLog>
@@ -109,21 +103,17 @@ StackDepotStats *StackDepotGetStats() {
return theDepot.GetStats();
}
-u32 StackDepotPut(const uptr *stack, uptr size) {
- StackDepotDesc desc = {stack, size};
- StackDepotHandle h = theDepot.Put(desc);
+u32 StackDepotPut(StackTrace stack) {
+ StackDepotHandle h = theDepot.Put(stack);
return h.valid() ? h.id() : 0;
}
-StackDepotHandle StackDepotPut_WithHandle(const uptr *stack, uptr size) {
- StackDepotDesc desc = {stack, size};
- return theDepot.Put(desc);
+StackDepotHandle StackDepotPut_WithHandle(StackTrace stack) {
+ return theDepot.Put(stack);
}
-const uptr *StackDepotGet(u32 id, uptr *size) {
- StackDepotDesc desc = theDepot.Get(id);
- *size = desc.size;
- return desc.stack;
+StackTrace StackDepotGet(u32 id) {
+ return theDepot.Get(id);
}
void StackDepotLockAll() {
@@ -154,18 +144,15 @@ StackDepotReverseMap::StackDepotReverseMap()
InternalSort(&map_, map_.size(), IdDescPair::IdComparator);
}
-const uptr *StackDepotReverseMap::Get(u32 id, uptr *size) {
- if (!map_.size()) return 0;
+StackTrace StackDepotReverseMap::Get(u32 id) {
+ if (!map_.size())
+ return StackTrace();
IdDescPair pair = {id, 0};
uptr idx = InternalBinarySearch(map_, 0, map_.size(), pair,
IdDescPair::IdComparator);
- if (idx > map_.size()) {
- *size = 0;
- return 0;
- }
- StackDepotNode *desc = map_[idx].desc;
- *size = desc->size;
- return desc->stack;
+ if (idx > map_.size())
+ return StackTrace();
+ return map_[idx].desc->load();
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
index 2b1da4ee14f..aad9bfb8d35 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
@@ -13,6 +13,7 @@
#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
+#include "sanitizer_stacktrace.h"
namespace __sanitizer {
@@ -26,17 +27,15 @@ struct StackDepotHandle {
u32 id();
int use_count();
void inc_use_count_unsafe();
- uptr size();
- uptr *stack();
};
const int kStackDepotMaxUseCount = 1U << 20;
StackDepotStats *StackDepotGetStats();
-u32 StackDepotPut(const uptr *stack, uptr size);
-StackDepotHandle StackDepotPut_WithHandle(const uptr *stack, uptr size);
+u32 StackDepotPut(StackTrace stack);
+StackDepotHandle StackDepotPut_WithHandle(StackTrace stack);
// Retrieves a stored stack trace by the id.
-const uptr *StackDepotGet(u32 id, uptr *size);
+StackTrace StackDepotGet(u32 id);
void StackDepotLockAll();
void StackDepotUnlockAll();
@@ -48,7 +47,7 @@ void StackDepotUnlockAll();
class StackDepotReverseMap {
public:
StackDepotReverseMap();
- const uptr *Get(u32 id, uptr *size);
+ StackTrace Get(u32 id);
private:
struct IdDescPair {
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h b/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
index b9dedec2621..05b63092b80 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepotbase.h
@@ -95,8 +95,8 @@ typename StackDepotBase<Node, kReservedBits, kTabSizeLog>::handle_type
StackDepotBase<Node, kReservedBits, kTabSizeLog>::Put(args_type args,
bool *inserted) {
if (inserted) *inserted = false;
- if (!args.is_valid()) return handle_type();
- uptr h = args.hash();
+ if (!Node::is_valid(args)) return handle_type();
+ uptr h = Node::hash(args);
atomic_uintptr_t *p = &tab[h % kTabSize];
uptr v = atomic_load(p, memory_order_consume);
Node *s = (Node *)(v & ~1);
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
index 0ce5ae475f6..9b99b5bb201 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
@@ -23,7 +23,7 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) {
#if defined(__powerpc__) || defined(__powerpc64__)
// PCs are always 4 byte aligned.
return pc - 4;
-#elif defined(__sparc__)
+#elif defined(__sparc__) || defined(__mips__)
return pc - 8;
#else
return pc - 1;
@@ -34,6 +34,15 @@ uptr StackTrace::GetCurrentPc() {
return GET_CALLER_PC();
}
+void BufferedStackTrace::Init(const uptr *pcs, uptr cnt, uptr extra_top_pc) {
+ size = cnt + !!extra_top_pc;
+ CHECK_LE(size, kStackTraceMax);
+ internal_memcpy(trace_buffer, pcs, cnt * sizeof(trace_buffer[0]));
+ if (extra_top_pc)
+ trace_buffer[cnt] = extra_top_pc;
+ top_frame_bp = 0;
+}
+
// Check if given pointer points into allocated stack area.
static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr);
@@ -49,32 +58,40 @@ static inline uhwptr *GetCanonicFrame(uptr bp,
if (!IsValidFrame(bp, stack_top, stack_bottom)) return 0;
uhwptr *bp_prev = (uhwptr *)bp;
if (IsValidFrame((uptr)bp_prev[0], stack_top, stack_bottom)) return bp_prev;
- return bp_prev - 1;
+ // The next frame pointer does not look right. This could be a GCC frame, step
+ // back by 1 word and try again.
+ if (IsValidFrame((uptr)bp_prev[-1], stack_top, stack_bottom))
+ return bp_prev - 1;
+ // Nope, this does not look right either. This means the frame after next does
+ // not have a valid frame pointer, but we can still extract the caller PC.
+ // Unfortunately, there is no way to decide between GCC and LLVM frame
+ // layouts. Assume LLVM.
+ return bp_prev;
#else
return (uhwptr*)bp;
#endif
}
-void StackTrace::FastUnwindStack(uptr pc, uptr bp,
- uptr stack_top, uptr stack_bottom,
- uptr max_depth) {
+void BufferedStackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top,
+ uptr stack_bottom, uptr max_depth) {
CHECK_GE(max_depth, 2);
- trace[0] = pc;
+ trace_buffer[0] = pc;
size = 1;
if (stack_top < 4096) return; // Sanity check for stack top.
uhwptr *frame = GetCanonicFrame(bp, stack_top, stack_bottom);
- uhwptr *prev_frame = 0;
+ // Lowest possible address that makes sense as the next frame pointer.
+ // Goes up as we walk the stack.
+ uptr bottom = stack_bottom;
// Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
- while (frame > prev_frame &&
- IsValidFrame((uptr)frame, stack_top, stack_bottom) &&
+ while (IsValidFrame((uptr)frame, stack_top, bottom) &&
IsAligned((uptr)frame, sizeof(*frame)) &&
size < max_depth) {
uhwptr pc1 = frame[1];
if (pc1 != pc) {
- trace[size++] = (uptr) pc1;
+ trace_buffer[size++] = (uptr) pc1;
}
- prev_frame = frame;
- frame = GetCanonicFrame((uptr)frame[0], stack_top, stack_bottom);
+ bottom = (uptr)frame;
+ frame = GetCanonicFrame((uptr)frame[0], stack_top, bottom);
}
}
@@ -82,15 +99,15 @@ static bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) {
return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold;
}
-void StackTrace::PopStackFrames(uptr count) {
+void BufferedStackTrace::PopStackFrames(uptr count) {
CHECK_LT(count, size);
size -= count;
for (uptr i = 0; i < size; ++i) {
- trace[i] = trace[i + count];
+ trace_buffer[i] = trace_buffer[i + count];
}
}
-uptr StackTrace::LocatePcInTrace(uptr pc) {
+uptr BufferedStackTrace::LocatePcInTrace(uptr pc) {
// Use threshold to find PC in stack trace, as PC we want to unwind from may
// slightly differ from return address in the actual unwinded stack trace.
const int kPcThreshold = 288;
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
index 0e0f1702228..31495cfc568 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
@@ -27,44 +27,49 @@ static const uptr kStackTraceMax = 256;
# define SANITIZER_CAN_FAST_UNWIND 1
#endif
+// Fast unwind is the only option on Mac for now; we will need to
+// revisit this macro when slow unwind works on Mac, see
+// https://code.google.com/p/address-sanitizer/issues/detail?id=137
+#if SANITIZER_MAC
+# define SANITIZER_CAN_SLOW_UNWIND 0
+#else
+# define SANITIZER_CAN_SLOW_UNWIND 1
+#endif
+
struct StackTrace {
- typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
- int out_size);
- uptr top_frame_bp;
+ const uptr *trace;
uptr size;
- uptr trace[kStackTraceMax];
- // Prints a symbolized stacktrace, followed by an empty line.
- static void PrintStack(const uptr *addr, uptr size);
- void Print() const {
- PrintStack(trace, size);
- }
+ StackTrace() : trace(nullptr), size(0) {}
+ StackTrace(const uptr *trace, uptr size) : trace(trace), size(size) {}
- void CopyFrom(const uptr *src, uptr src_size) {
- top_frame_bp = 0;
- size = src_size;
- if (size > kStackTraceMax) size = kStackTraceMax;
- for (uptr i = 0; i < size; i++)
- trace[i] = src[i];
- }
+ // Prints a symbolized stacktrace, followed by an empty line.
+ void Print() const;
static bool WillUseFastUnwind(bool request_fast_unwind) {
- // Check if fast unwind is available. Fast unwind is the only option on Mac.
- // It is also the only option on FreeBSD as the slow unwinding that
- // leverages _Unwind_Backtrace() yields the call stack of the signal's
- // handler and not of the code that raised the signal (as it does on Linux).
if (!SANITIZER_CAN_FAST_UNWIND)
return false;
- else if (SANITIZER_MAC != 0 || SANITIZER_FREEBSD != 0)
+ else if (!SANITIZER_CAN_SLOW_UNWIND)
return true;
return request_fast_unwind;
}
- void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
- uptr stack_bottom, bool request_fast_unwind);
-
static uptr GetCurrentPc();
static uptr GetPreviousInstructionPc(uptr pc);
+ typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
+ int out_size);
+};
+
+// StackTrace that owns the buffer used to store the addresses.
+struct BufferedStackTrace : public StackTrace {
+ uptr trace_buffer[kStackTraceMax];
+ uptr top_frame_bp; // Optional bp of a top frame.
+
+ BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {}
+
+ void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
+ void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
+ uptr stack_bottom, bool request_fast_unwind);
private:
void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom,
@@ -74,6 +79,9 @@ struct StackTrace {
uptr max_depth);
void PopStackFrames(uptr count);
uptr LocatePcInTrace(uptr pc);
+
+ BufferedStackTrace(const BufferedStackTrace &);
+ void operator=(const BufferedStackTrace &);
};
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
index 5dcc0e9ed15..2d55b73f03a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -10,58 +10,40 @@
//===----------------------------------------------------------------------===//
#include "sanitizer_common.h"
+#include "sanitizer_placement_new.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_stacktrace_printer.h"
#include "sanitizer_symbolizer.h"
namespace __sanitizer {
-static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
- uptr pc) {
- buffer->append(" #%zu 0x%zx", frame_num, pc);
-}
-
-void StackTrace::PrintStack(const uptr *addr, uptr size) {
- if (addr == 0 || size == 0) {
+void StackTrace::Print() const {
+ if (trace == nullptr || size == 0) {
Printf(" <empty stack>\n\n");
return;
}
- InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
- InternalScopedBuffer<AddressInfo> addr_frames(64);
+ const int kMaxAddrFrames = 64;
+ InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
+ for (uptr i = 0; i < kMaxAddrFrames; i++)
+ new(&addr_frames[i]) AddressInfo();
InternalScopedString frame_desc(GetPageSizeCached() * 2);
uptr frame_num = 0;
- for (uptr i = 0; i < size && addr[i]; i++) {
+ for (uptr i = 0; i < size && trace[i]; i++) {
// PCs in stack traces are actually the return addresses, that is,
// addresses of the next instructions after the call.
- uptr pc = GetPreviousInstructionPc(addr[i]);
+ uptr pc = GetPreviousInstructionPc(trace[i]);
uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
- pc, addr_frames.data(), addr_frames.size());
+ pc, addr_frames.data(), kMaxAddrFrames);
if (addr_frames_num == 0) {
- frame_desc.clear();
- PrintStackFramePrefix(&frame_desc, frame_num, pc);
- frame_desc.append(" (<unknown module>)");
- Printf("%s\n", frame_desc.data());
- frame_num++;
- continue;
+ addr_frames[0].address = pc;
+ addr_frames_num = 1;
}
for (uptr j = 0; j < addr_frames_num; j++) {
AddressInfo &info = addr_frames[j];
frame_desc.clear();
- PrintStackFramePrefix(&frame_desc, frame_num, pc);
- if (info.function) {
- frame_desc.append(" in %s", info.function);
- // Print offset in function if we don't know the source file.
- if (!info.file && info.function_offset != AddressInfo::kUnknown)
- frame_desc.append("+0x%zx", info.function_offset);
- }
- if (info.file) {
- frame_desc.append(" ");
- PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
- } else if (info.module) {
- frame_desc.append(" ");
- PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
- }
+ RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++,
+ info, common_flags()->strip_path_prefix);
Printf("%s\n", frame_desc.data());
- frame_num++;
info.Clear();
}
}
@@ -69,9 +51,9 @@ void StackTrace::PrintStack(const uptr *addr, uptr size) {
Printf("\n");
}
-void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
- uptr stack_top, uptr stack_bottom,
- bool request_fast_unwind) {
+void BufferedStackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
+ uptr stack_top, uptr stack_bottom,
+ bool request_fast_unwind) {
top_frame_bp = (max_depth > 0) ? bp : 0;
// Avoid doing any work for small max_depth.
if (max_depth == 0) {
@@ -80,7 +62,7 @@ void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
}
if (max_depth == 1) {
size = 1;
- trace[0] = pc;
+ trace_buffer[0] = pc;
return;
}
if (!WillUseFastUnwind(request_fast_unwind)) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cc
new file mode 100644
index 00000000000..300b4904c54
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cc
@@ -0,0 +1,130 @@
+//===-- sanitizer_common.cc -----------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers' run-time libraries.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_stacktrace_printer.h"
+
+namespace __sanitizer {
+
+static const char *StripFunctionName(const char *function, const char *prefix) {
+ if (function == 0) return 0;
+ if (prefix == 0) return function;
+ uptr prefix_len = internal_strlen(prefix);
+ if (0 == internal_strncmp(function, prefix, prefix_len))
+ return function + prefix_len;
+ return function;
+}
+
+static const char kDefaultFormat[] = " #%n %p %F %L";
+
+void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
+ const AddressInfo &info, const char *strip_path_prefix,
+ const char *strip_func_prefix) {
+ if (0 == internal_strcmp(format, "DEFAULT"))
+ format = kDefaultFormat;
+ for (const char *p = format; *p != '\0'; p++) {
+ if (*p != '%') {
+ buffer->append("%c", *p);
+ continue;
+ }
+ p++;
+ switch (*p) {
+ case '%':
+ buffer->append("%%");
+ break;
+ // Frame number and all fields of AddressInfo structure.
+ case 'n':
+ buffer->append("%zu", frame_no);
+ break;
+ case 'p':
+ buffer->append("0x%zx", info.address);
+ break;
+ case 'm':
+ buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
+ break;
+ case 'o':
+ buffer->append("0x%zx", info.module_offset);
+ break;
+ case 'f':
+ buffer->append("%s", StripFunctionName(info.function, strip_func_prefix));
+ break;
+ case 'q':
+ buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
+ ? info.function_offset
+ : 0x0);
+ break;
+ case 's':
+ buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
+ break;
+ case 'l':
+ buffer->append("%d", info.line);
+ break;
+ case 'c':
+ buffer->append("%d", info.column);
+ break;
+ // Smarter special cases.
+ case 'F':
+ // Function name and offset, if file is unknown.
+ if (info.function) {
+ buffer->append("in %s",
+ StripFunctionName(info.function, strip_func_prefix));
+ if (!info.file && info.function_offset != AddressInfo::kUnknown)
+ buffer->append("+0x%zx", info.function_offset);
+ }
+ break;
+ case 'S':
+ // File/line information.
+ RenderSourceLocation(buffer, info.file, info.line, info.column,
+ strip_path_prefix);
+ break;
+ case 'L':
+ // Source location, or module location.
+ if (info.file) {
+ RenderSourceLocation(buffer, info.file, info.line, info.column,
+ strip_path_prefix);
+ } else if (info.module) {
+ RenderModuleLocation(buffer, info.module, info.module_offset,
+ strip_path_prefix);
+ } else {
+ buffer->append("(<unknown module>)");
+ }
+ break;
+ case 'M':
+ // Module basename and offset, or PC.
+ if (info.module)
+ buffer->append("(%s+%p)", StripModuleName(info.module),
+ (void *)info.module_offset);
+ else
+ buffer->append("(%p)", (void *)info.address);
+ break;
+ default:
+ Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n",
+ *p, *p);
+ Die();
+ }
+ }
+}
+
+void RenderSourceLocation(InternalScopedString *buffer, const char *file,
+ int line, int column, const char *strip_path_prefix) {
+ buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
+ if (line > 0) {
+ buffer->append(":%d", line);
+ if (column > 0)
+ buffer->append(":%d", column);
+ }
+}
+
+void RenderModuleLocation(InternalScopedString *buffer, const char *module,
+ uptr offset, const char *strip_path_prefix) {
+ buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
+ offset);
+}
+
+} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.h
new file mode 100644
index 00000000000..54e2fb024df
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.h
@@ -0,0 +1,60 @@
+//===-- sanitizer_stacktrace_printer.h --------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizers' run-time libraries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_STACKTRACE_PRINTER_H
+#define SANITIZER_STACKTRACE_PRINTER_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_symbolizer.h"
+
+namespace __sanitizer {
+
+// Render the contents of "info" structure, which represents the contents of
+// stack frame "frame_no" and appends it to the "buffer". "format" is a
+// string with placeholders, which is copied to the output with
+// placeholders substituted with the contents of "info". For example,
+// format string
+// " frame %n: function %F at %S"
+// will be turned into
+// " frame 10: function foo::bar() at my/file.cc:10"
+// You may additionally pass "strip_path_prefix" to strip prefixes of paths to
+// source files and modules, and "strip_func_prefix" to strip prefixes of
+// function names.
+// Here's the full list of available placeholders:
+// %% - represents a '%' character;
+// %n - frame number (copy of frame_no);
+// %p - PC in hex format;
+// %m - path to module (binary or shared object);
+// %o - offset in the module in hex format;
+// %f - function name;
+// %q - offset in the function in hex format (*if available*);
+// %s - path to source file;
+// %l - line in the source file;
+// %c - column in the source file;
+// %F - if function is known to be <foo>, prints "in <foo>", possibly
+// followed by the offset in this function, but only if source file
+// is unknown;
+// %S - prints file/line/column information;
+// %L - prints location information: file/line/column, if it is known, or
+// module+offset if it is known, or (<unknown module>) string.
+// %M - prints module basename and offset, if it is known, or PC.
+void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
+ const AddressInfo &info, const char *strip_path_prefix = "",
+ const char *strip_func_prefix = "");
+
+void RenderSourceLocation(InternalScopedString *buffer, const char *file,
+ int line, int column, const char *strip_path_prefix);
+
+void RenderModuleLocation(InternalScopedString *buffer, const char *module,
+ uptr offset, const char *strip_path_prefix);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STACKTRACE_PRINTER_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
index 73a68b2ee11..2ff99372da9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
@@ -59,13 +59,23 @@ struct AddressInfo {
}
};
+// For now, DataInfo is used to describe global variable.
struct DataInfo {
- uptr address;
char *module;
uptr module_offset;
char *name;
uptr start;
uptr size;
+
+ DataInfo() {
+ internal_memset(this, 0, sizeof(DataInfo));
+ }
+
+ void Clear() {
+ InternalFree(module);
+ InternalFree(name);
+ internal_memset(this, 0, sizeof(DataInfo));
+ }
};
class Symbolizer {
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
index 86d32e529ec..905079475b8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
@@ -166,7 +166,7 @@ uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames,
}
bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
- backtrace_syminfo((backtrace_state *)state_, info->address,
+ backtrace_syminfo((backtrace_state *)state_, info->start,
SymbolizeDataCallback, ErrorCallback, info);
return true;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
index 4f30225a4c8..ccd2d70f0f0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -339,12 +339,19 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
const char* const kSymbolizerArch = "--default-arch=x86_64";
#elif defined(__i386__)
const char* const kSymbolizerArch = "--default-arch=i386";
-#elif defined(__powerpc64__)
+#elif defined(__powerpc64__) && defined(__BIG_ENDIAN__)
const char* const kSymbolizerArch = "--default-arch=powerpc64";
+#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__)
+ const char* const kSymbolizerArch = "--default-arch=powerpc64le";
#else
const char* const kSymbolizerArch = "--default-arch=unknown";
#endif
- execl(path_to_binary, path_to_binary, kSymbolizerArch, (char *)0);
+
+ const char *const inline_flag = common_flags()->symbolize_inline_frames
+ ? "--inlining=true"
+ : "--inlining=false";
+ execl(path_to_binary, path_to_binary, inline_flag, kSymbolizerArch,
+ (char *)0);
}
};
@@ -580,8 +587,7 @@ class POSIXSymbolizer : public Symbolizer {
return false;
const char *module_name = module->full_name();
uptr module_offset = addr - module->base_address();
- internal_memset(info, 0, sizeof(*info));
- info->address = addr;
+ info->Clear();
info->module = internal_strdup(module_name);
info->module_offset = module_offset;
// First, try to use libbacktrace symbolizer (if it's available).
diff --git a/libsanitizer/sanitizer_common/sanitizer_unwind_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_unwind_posix_libcdep.cc
index c49113e1d0b..b2ca931e9d9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_unwind_posix_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_unwind_posix_libcdep.cc
@@ -93,7 +93,7 @@ uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
}
struct UnwindTraceArg {
- StackTrace *stack;
+ BufferedStackTrace *stack;
uptr max_depth;
};
@@ -101,27 +101,27 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
UnwindTraceArg *arg = (UnwindTraceArg*)param;
CHECK_LT(arg->stack->size, arg->max_depth);
uptr pc = Unwind_GetIP(ctx);
- arg->stack->trace[arg->stack->size++] = pc;
+ arg->stack->trace_buffer[arg->stack->size++] = pc;
if (arg->stack->size == arg->max_depth) return UNWIND_STOP;
return UNWIND_CONTINUE;
}
-void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
+void BufferedStackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
CHECK_GE(max_depth, 2);
size = 0;
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
_Unwind_Backtrace(Unwind_Trace, &arg);
// We need to pop a few frames so that pc is on top.
uptr to_pop = LocatePcInTrace(pc);
- // trace[0] belongs to the current function so we always pop it.
- if (to_pop == 0)
+ // trace_buffer[0] belongs to the current function so we always pop it.
+ if (to_pop == 0 && size > 1)
to_pop = 1;
PopStackFrames(to_pop);
- trace[0] = pc;
+ trace_buffer[0] = pc;
}
-void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
- uptr max_depth) {
+void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
+ uptr max_depth) {
CHECK_GE(max_depth, 2);
if (!unwind_backtrace_signal_arch) {
SlowUnwindStack(pc, max_depth);
@@ -143,7 +143,7 @@ void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
// +2 compensate for libcorkscrew unwinder returning addresses of call
// instructions instead of raw return addresses.
for (sptr i = 0; i < res; ++i)
- trace[size++] = frames[i].absolute_pc + 2;
+ trace_buffer[size++] = frames[i].absolute_pc + 2;
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc
index 9f24510dbd0..fbccef19cb1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cc
@@ -442,7 +442,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
}
#if !SANITIZER_GO
-void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
+void BufferedStackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
CHECK_GE(max_depth, 2);
// FIXME: CaptureStackBackTrace might be too slow for us.
// FIXME: Compare with StackWalk64.
@@ -457,8 +457,8 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
PopStackFrames(pc_location);
}
-void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
- uptr max_depth) {
+void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
+ uptr max_depth) {
CONTEXT ctx = *(CONTEXT *)context;
STACKFRAME64 stack_frame;
memset(&stack_frame, 0, sizeof(stack_frame));
@@ -481,7 +481,7 @@ void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
&stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
&SymGetModuleBase64, NULL) &&
size < Min(max_depth, kStackTraceMax)) {
- trace[size++] = (uptr)stack_frame.AddrPC.Offset;
+ trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
}
}
#endif // #if !SANITIZER_GO