summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asan/asan_report.cc2
-rw-r--r--lib/asan/asan_rtl.cc1
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc4
-rw-r--r--lib/sanitizer_common/sanitizer_common.h30
-rw-r--r--lib/sanitizer_common/sanitizer_flags.inc3
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_mac.cc30
-rw-r--r--lib/sanitizer_common/sanitizer_printf.cc28
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc2
-rw-r--r--lib/tsan/rtl/tsan_report.cc2
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc2
-rw-r--r--test/asan/TestCases/Darwin/uuid.cc28
12 files changed, 123 insertions, 11 deletions
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index 937ba4077..3ad48fa88 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -179,6 +179,8 @@ class ScopedInErrorReport {
if (common_flags()->print_cmdline)
PrintCmdline();
+ if (common_flags()->print_module_map == 2) PrintModuleMap();
+
// Copy the message buffer so that we could start logging without holding a
// lock that gets aquired during printing.
InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index fee7b8a2d..d9d7d7e4f 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -46,6 +46,7 @@ static void AsanDie() {
// Don't die twice - run a busy loop.
while (1) { }
}
+ if (common_flags()->print_module_map >= 1) PrintModuleMap();
if (flags()->sleep_before_dying) {
Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
SleepForSeconds(flags()->sleep_before_dying);
diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 89c5c4511..9824a5198 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/lib/sanitizer_common/sanitizer_common.cc
@@ -270,6 +270,8 @@ void LoadedModule::set(const char *module_name, uptr base_address,
void LoadedModule::clear() {
InternalFree(full_name_);
+ base_address_ = 0;
+ max_executable_address_ = 0;
full_name_ = nullptr;
arch_ = kModuleArchUnknown;
internal_memset(uuid_, 0, kModuleUUIDSize);
@@ -285,6 +287,8 @@ void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable) {
void *mem = InternalAlloc(sizeof(AddressRange));
AddressRange *r = new(mem) AddressRange(beg, end, executable);
ranges_.push_back(r);
+ if (executable && end > max_executable_address_)
+ max_executable_address_ = end;
}
bool LoadedModule::containsAddress(uptr address) const {
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index fee642f3e..fc44ecd5b 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -283,6 +283,7 @@ void UpdateProcessName();
void CacheBinaryName();
void DisableCoreDumperIfNecessary();
void DumpProcessMap();
+void PrintModuleMap();
bool FileExists(const char *filename);
const char *GetEnv(const char *name);
bool SetEnv(const char *name, const char *value);
@@ -665,6 +666,32 @@ enum ModuleArch {
kModuleArchARM64
};
+// When adding a new architecture, don't forget to also update
+// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cc.
+inline const char *ModuleArchToString(ModuleArch arch) {
+ switch (arch) {
+ case kModuleArchUnknown:
+ return "";
+ case kModuleArchI386:
+ return "i386";
+ case kModuleArchX86_64:
+ return "x86_64";
+ case kModuleArchX86_64H:
+ return "x86_64h";
+ case kModuleArchARMV6:
+ return "armv6";
+ case kModuleArchARMV7:
+ return "armv7";
+ case kModuleArchARMV7S:
+ return "armv7s";
+ case kModuleArchARMV7K:
+ return "armv7k";
+ case kModuleArchARM64:
+ return "arm64";
+ }
+ CHECK(0 && "Invalid module arch");
+}
+
const uptr kModuleUUIDSize = 16;
// Represents a binary loaded into virtual memory (e.g. this can be an
@@ -674,6 +701,7 @@ class LoadedModule {
LoadedModule()
: full_name_(nullptr),
base_address_(0),
+ max_executable_address_(0),
arch_(kModuleArchUnknown),
instrumented_(false) {
internal_memset(uuid_, 0, kModuleUUIDSize);
@@ -688,6 +716,7 @@ class LoadedModule {
const char *full_name() const { return full_name_; }
uptr base_address() const { return base_address_; }
+ uptr max_executable_address() const { return max_executable_address_; }
ModuleArch arch() const { return arch_; }
const u8 *uuid() const { return uuid_; }
bool instrumented() const { return instrumented_; }
@@ -707,6 +736,7 @@ class LoadedModule {
private:
char *full_name_; // Owned.
uptr base_address_;
+ uptr max_executable_address_;
ModuleArch arch_;
u8 uuid_[kModuleUUIDSize];
bool instrumented_;
diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc
index 43900f87b..d7fa34a58 100644
--- a/lib/sanitizer_common/sanitizer_flags.inc
+++ b/lib/sanitizer_common/sanitizer_flags.inc
@@ -74,6 +74,9 @@ COMMON_FLAG(bool, allocator_may_return_null, false,
COMMON_FLAG(bool, print_summary, true,
"If false, disable printing error summaries in addition to error "
"reports.")
+COMMON_FLAG(int, print_module_map, 0,
+ "OS X only. 0 = don't print, 1 = print only once before process "
+ "exits, 2 = print after each report.")
COMMON_FLAG(bool, check_printf, true, "Check printf arguments.")
COMMON_FLAG(bool, handle_segv, true,
"If set, registers the tool's custom SIGSEGV/SIGBUS handler.")
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 76cdc72a0..7328a5c0a 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -1393,6 +1393,8 @@ void MaybeReexec() {
// No need to re-exec on Linux.
}
+void PrintModuleMap() { }
+
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
UNREACHABLE("FindAvailableMemoryRange is not available");
return 0;
diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc
index 73e018c85..b4f8ab5e3 100644
--- a/lib/sanitizer_common/sanitizer_mac.cc
+++ b/lib/sanitizer_common/sanitizer_mac.cc
@@ -854,6 +854,36 @@ void SignalContext::DumpAllRegisters(void *context) {
# undef DUMPREG
}
+static inline bool CompareBaseAddress(const LoadedModule &a,
+ const LoadedModule &b) {
+ return a.base_address() < b.base_address();
+}
+
+void FormatUUID(char *out, uptr size, const u8 *uuid) {
+ internal_snprintf(out, size,
+ "<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
+ "%02X%02X%02X%02X%02X%02X>",
+ uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
+ uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+}
+
+void PrintModuleMap() {
+ Printf("Process module map:\n");
+ MemoryMappingLayout memory_mapping(false);
+ InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128);
+ memory_mapping.DumpListOfModules(&modules);
+ InternalSort(&modules, modules.size(), CompareBaseAddress);
+ for (uptr i = 0; i < modules.size(); ++i) {
+ char uuid_str[128];
+ FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
+ Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
+ modules[i].max_executable_address(), modules[i].full_name(),
+ ModuleArchToString(modules[i].arch()), uuid_str);
+ }
+ Printf("End of module map.\n");
+}
+
} // namespace __sanitizer
#endif // SANITIZER_MAC
diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc
index f394e75b0..c8317be60 100644
--- a/lib/sanitizer_common/sanitizer_printf.cc
+++ b/lib/sanitizer_common/sanitizer_printf.cc
@@ -43,7 +43,7 @@ static int AppendChar(char **buff, const char *buff_end, char c) {
// on the value of |pad_with_zero|.
static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
u8 base, u8 minimal_num_length, bool pad_with_zero,
- bool negative) {
+ bool negative, bool uppercase) {
uptr const kMaxLen = 30;
RAW_CHECK(base == 10 || base == 16);
RAW_CHECK(base == 10 || !negative);
@@ -76,23 +76,25 @@ static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
for (; pos >= 0; pos--) {
char digit = static_cast<char>(num_buffer[pos]);
- result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
- : 'a' + digit - 10);
+ digit = (digit < 10) ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10;
+ result += AppendChar(buff, buff_end, digit);
}
return result;
}
static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
- u8 minimal_num_length, bool pad_with_zero) {
+ u8 minimal_num_length, bool pad_with_zero,
+ bool uppercase) {
return AppendNumber(buff, buff_end, num, base, minimal_num_length,
- pad_with_zero, false /* negative */);
+ pad_with_zero, false /* negative */, uppercase);
}
static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
u8 minimal_num_length, bool pad_with_zero) {
bool negative = (num < 0);
return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
- minimal_num_length, pad_with_zero, negative);
+ minimal_num_length, pad_with_zero, negative,
+ false /* uppercase */);
}
static int AppendString(char **buff, const char *buff_end, int precision,
@@ -112,14 +114,16 @@ 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_POINTER_FORMAT_LENGTH, true);
+ SANITIZER_POINTER_FORMAT_LENGTH,
+ true /* pad_with_zero */, false /* uppercase */);
return result;
}
int VSNPrintf(char *buff, int buff_length,
const char *format, va_list args) {
static const char *kPrintfFormatsHelp =
- "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %(\\.\\*)?s; %c\n";
+ "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; %(\\.\\*)?s; "
+ "%c\n";
RAW_CHECK(format);
RAW_CHECK(buff_length > 0);
const char *buff_end = &buff[buff_length - 1];
@@ -164,12 +168,14 @@ int VSNPrintf(char *buff, int buff_length,
break;
}
case 'u':
- case 'x': {
+ case 'x':
+ case 'X': {
uval = have_ll ? va_arg(args, u64)
: have_z ? va_arg(args, uptr)
: va_arg(args, unsigned);
- result += AppendUnsigned(&buff, buff_end, uval,
- (*cur == 'u') ? 10 : 16, width, pad_with_zero);
+ bool uppercase = (*cur == 'X');
+ result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
+ width, pad_with_zero, uppercase);
break;
}
case 'p': {
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index 6efd33021..9682d2921 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -388,6 +388,8 @@ void DumpProcessMap() {
}
#endif
+void PrintModuleMap() { }
+
void DisableCoreDumperIfNecessary() {
// Do nothing.
}
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 156876e5c..07fd41208 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -358,6 +358,8 @@ void PrintReport(const ReportDesc *rep) {
ReportErrorSummary(rep_typ_str, frame->info);
}
+ if (common_flags()->print_module_map == 2) PrintModuleMap();
+
Printf("==================\n");
}
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 804f3cf64..bfb835889 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -404,6 +404,8 @@ void Initialize(ThreadState *thr) {
int Finalize(ThreadState *thr) {
bool failed = false;
+ if (common_flags()->print_module_map == 1) PrintModuleMap();
+
if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
SleepForMillis(flags()->atexit_sleep_ms);
diff --git a/test/asan/TestCases/Darwin/uuid.cc b/test/asan/TestCases/Darwin/uuid.cc
new file mode 100644
index 000000000..eaa022036
--- /dev/null
+++ b/test/asan/TestCases/Darwin/uuid.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_asan %s -o %t
+// RUN: %env_asan_opts=print_module_map=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=print_module_map=2 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan %s -o %t -fsanitize-recover=address
+// RUN: %env_asan_opts=print_module_map=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char *argv[]) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "otool -l %s", argv[0]);
+ system(buf);
+ // CHECK: cmd LC_UUID
+ // CHECK-NEXT: cmdsize 24
+ // CHECK-NEXT: uuid [[UUID:[0-9A-F-]{36}]]
+
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ char mybuf[10];
+ memcpy(mybuf, x, 10);
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: Process module map:
+ // CHECK: uuid.cc.tmp {{.*}} <[[UUID]]>
+
+ fprintf(stderr, "Done.\n");
+}