Index: compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp =================================================================== --- compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp +++ compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp @@ -20,9 +20,10 @@ // that "too many errors" has already been reported. static __sanitizer::atomic_uint32_t caller_pcs_sz; -__attribute__((noinline)) static bool report_this_error(void *caller_p) { - uintptr_t caller = reinterpret_cast(caller_p); - if (caller == 0) return false; +__attribute__((noinline)) static bool +report_this_error(__sanitizer::uptr caller) { + if (caller == 0) + return false; while (true) { unsigned sz = __sanitizer::atomic_load_relaxed(&caller_pcs_sz); if (sz > kMaxCallerPcs) return false; // early exit @@ -51,6 +52,29 @@ } } +__attribute__((noinline)) static void decorate_msg(char *buf, + __sanitizer::uptr caller) { + unsigned int shift = sizeof(__sanitizer::uptr) * 8 - 4; + __sanitizer::uptr mask = __sanitizer::uptr(0xf) << shift; + // skip leading zeroes + while (shift > 0 && !(caller & mask)) { + mask >>= 4; + shift -= 4; + } + // print remaining nibbles + for (;;) { + unsigned int nibble = (caller & mask) >> shift; + *(buf++) = nibble < 10 ? nibble + '0' : nibble - 10 + 'a'; + if (!shift) + break; + mask >>= 4; + shift -= 4; + } + // finish the message + buf[0] = '\n'; + buf[1] = '\0'; +} + #if defined(__ANDROID__) extern "C" __attribute__((weak)) void android_set_abort_message(const char *); static void abort_with_message(const char *msg) { @@ -76,18 +100,28 @@ #define INTERFACE extern "C" __attribute__((visibility("default"))) -// FIXME: add caller pc to the error message (possibly as "ubsan: error-type -// @1234ABCD"). +// How many chars we need to reserve to print any address. +static const unsigned int kMaxAddrBuf = SANITIZER_WORDSIZE / 4; +#define MSG_TMPL(msg) "ubsan: " msg " @" +#define MSG_TMPL_END(buf, msg) (buf + sizeof(MSG_TMPL(msg)) - 1) +// Reserve an additional byte for '\n'. +#define MSG_BUF_LEN(msg) (sizeof(MSG_TMPL(msg)) + kMaxAddrBuf + 1) + #define HANDLER_RECOVER(name, msg) \ INTERFACE void __ubsan_handle_##name##_minimal() { \ - if (!report_this_error(__builtin_return_address(0))) return; \ - message("ubsan: " msg "\n"); \ + __sanitizer::uptr caller = GET_CALLER_PC(); \ + if (!report_this_error(caller)) return; \ + char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \ + decorate_msg(MSG_TMPL_END(msg_buf, msg), caller); \ + message(msg_buf); \ } #define HANDLER_NORECOVER(name, msg) \ INTERFACE void __ubsan_handle_##name##_minimal_abort() { \ - message("ubsan: " msg "\n"); \ - abort_with_message("ubsan: " msg); \ + char msg_buf[MSG_BUF_LEN(msg)] = MSG_TMPL(msg); \ + decorate_msg(MSG_TMPL_END(msg_buf, msg), GET_CALLER_PC()); \ + message(msg_buf); \ + abort_with_message(msg_buf); \ } #define HANDLER(name, msg) \