@@ -20,20 +20,50 @@ static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
2020// that "too many errors" has already been reported.
2121static __sanitizer::atomic_uint32_t caller_pcs_sz;
2222
23- __attribute__ ((noinline)) static bool report_this_error(uintptr_t caller) {
23+ static char *append_str (const char *s, char *buf, const char *end) {
24+ for (const char *p = s; (buf < end) && (*p != ' \0 ' ); ++p, ++buf)
25+ *buf = *p;
26+ return buf;
27+ }
28+
29+ static char *append_hex (uintptr_t d, char *buf, const char *end) {
30+ // Print the address by nibbles.
31+ for (unsigned shift = sizeof (uintptr_t ) * 8 ; shift && buf < end;) {
32+ shift -= 4 ;
33+ unsigned nibble = (d >> shift) & 0xf ;
34+ *(buf++) = nibble < 10 ? nibble + ' 0' : nibble - 10 + ' a' ;
35+ }
36+ return buf;
37+ }
38+
39+ static void format_msg (const char *kind, uintptr_t caller, char *buf,
40+ const char *end) {
41+ buf = append_str (" ubsan: " , buf, end);
42+ buf = append_str (kind, buf, end);
43+ buf = append_str (" by 0x" , buf, end);
44+ buf = append_hex (caller, buf, end);
45+ buf = append_str (" \n " , buf, end);
46+ if (buf == end)
47+ --buf; // Make sure we don't cause a buffer overflow.
48+ *buf = ' \0 ' ;
49+ }
50+
51+ static void report_error (const char *kind, uintptr_t caller) {
2452 if (caller == 0 )
25- return false ;
53+ return ;
2654 while (true ) {
2755 unsigned sz = __sanitizer::atomic_load_relaxed (&caller_pcs_sz);
28- if (sz > kMaxCallerPcs ) return false ; // early exit
56+ if (sz > kMaxCallerPcs )
57+ return ; // early exit
2958 // when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg
3059 // succeeds in order to not print it multiple times.
3160 if (sz > 0 && sz < kMaxCallerPcs ) {
3261 uintptr_t p;
3362 for (unsigned i = 0 ; i < sz; ++i) {
3463 p = __sanitizer::atomic_load_relaxed (&caller_pcs[i]);
3564 if (p == 0 ) break ; // Concurrent update.
36- if (p == caller) return false ;
65+ if (p == caller)
66+ return ;
3767 }
3868 if (p == 0 ) continue ; // FIXME: yield?
3969 }
@@ -44,34 +74,27 @@ __attribute__((noinline)) static bool report_this_error(uintptr_t caller) {
4474
4575 if (sz == kMaxCallerPcs ) {
4676 message (" ubsan: too many errors\n " );
47- return false ;
77+ return ;
4878 }
4979 __sanitizer::atomic_store_relaxed (&caller_pcs[sz], caller);
50- return true ;
51- }
52- }
5380
54- __attribute__ ((noinline)) static void decorate_msg(char *buf,
55- uintptr_t caller) {
56- // print the address by nibbles
57- for (unsigned shift = sizeof (uintptr_t ) * 8 ; shift;) {
58- shift -= 4 ;
59- unsigned nibble = (caller >> shift) & 0xf ;
60- *(buf++) = nibble < 10 ? nibble + ' 0' : nibble - 10 + ' a' ;
81+ char msg_buf[128 ];
82+ format_msg (kind, caller, msg_buf, msg_buf + sizeof (msg_buf));
83+ message (msg_buf);
6184 }
62- // finish the message
63- buf[0 ] = ' \n ' ;
64- buf[1 ] = ' \0 ' ;
6585}
6686
6787#if defined(__ANDROID__)
6888extern " C" __attribute__((weak)) void android_set_abort_message (const char *);
69- static void abort_with_message (const char *msg) {
70- if (&android_set_abort_message) android_set_abort_message (msg);
89+ static void abort_with_message (const char *kind, uintptr_t caller) {
90+ char msg_buf[128 ];
91+ format_msg (kind, caller, msg_buf, msg_buf + sizeof (msg_buf));
92+ if (&android_set_abort_message)
93+ android_set_abort_message (msg_buf);
7194 abort ();
7295}
7396#else
74- static void abort_with_message (const char *) { abort (); }
97+ static void abort_with_message (const char *kind, uintptr_t caller ) { abort (); }
7598#endif
7699
77100#if SANITIZER_DEBUG
@@ -89,33 +112,21 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
89112
90113#define INTERFACE extern " C" __attribute__((visibility(" default" )))
91114
92- // How many chars we need to reserve to print an address.
93- constexpr unsigned kAddrBuf = SANITIZER_WORDSIZE / 4 ;
94- #define MSG_TMPL (msg ) " ubsan: " msg " by 0x"
95- #define MSG_TMPL_END (buf, msg ) (buf + sizeof (MSG_TMPL(msg)) - 1 )
96- // Reserve an additional byte for '\n'.
97- #define MSG_BUF_LEN (msg ) (sizeof (MSG_TMPL(msg)) + kAddrBuf + 1 )
98-
99- #define HANDLER_RECOVER (name, msg ) \
100- INTERFACE void __ubsan_handle_##name##_minimal() { \
101- uintptr_t caller = GET_CALLER_PC (); \
102- if (!report_this_error (caller)) return ; \
103- char msg_buf[MSG_BUF_LEN (msg)] = MSG_TMPL (msg); \
104- decorate_msg (MSG_TMPL_END (msg_buf, msg), caller); \
105- message (msg_buf); \
115+ #define HANDLER_RECOVER (name, kind ) \
116+ INTERFACE void __ubsan_handle_##name##_minimal() { \
117+ report_error (kind, GET_CALLER_PC ()); \
106118 }
107119
108- #define HANDLER_NORECOVER (name, msg ) \
109- INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
110- char msg_buf[MSG_BUF_LEN (msg)] = MSG_TMPL (msg); \
111- decorate_msg (MSG_TMPL_END (msg_buf, msg), GET_CALLER_PC ()); \
112- message (msg_buf); \
113- abort_with_message (msg_buf); \
120+ #define HANDLER_NORECOVER (name, kind ) \
121+ INTERFACE void __ubsan_handle_##name##_minimal_abort() { \
122+ uintptr_t caller = GET_CALLER_PC (); \
123+ report_error (kind, caller); \
124+ abort_with_message (kind, caller); \
114125 }
115126
116- #define HANDLER (name, msg ) \
117- HANDLER_RECOVER (name, msg) \
118- HANDLER_NORECOVER(name, msg )
127+ #define HANDLER (name, kind ) \
128+ HANDLER_RECOVER (name, kind) \
129+ HANDLER_NORECOVER(name, kind )
119130
120131HANDLER(type_mismatch, " type-mismatch" )
121132HANDLER(alignment_assumption, " alignment-assumption" )
0 commit comments