mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-15 12:09:51 +00:00
Introduce __asan_set_error_report_callback() to allow the client program post-process the error reports.
If the callback is set, Report() and Printf() print the reports into a buffer (together with stderr), which is then passed to the client. llvm-svn: 151528
This commit is contained in:
parent
169f436870
commit
7e07f56811
@ -222,6 +222,13 @@ int internal_strcmp(const char *s1, const char *s2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *internal_strncpy(char *dst, const char *src, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n && src[i]; i++)
|
||||
dst[i] = src[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
// ---------------------- Wrappers ---------------- {{{1
|
||||
|
@ -40,6 +40,7 @@ int internal_memcmp(const void* s1, const void* s2, size_t n);
|
||||
char *internal_strstr(const char *haystack, const char *needle);
|
||||
char *internal_strncat(char *dst, const char *src, size_t n);
|
||||
int internal_strcmp(const char *s1, const char *s2);
|
||||
char *internal_strncpy(char *dst, const char *src, size_t n);
|
||||
// Works only for base=10 and doesn't set errno.
|
||||
int64_t internal_simple_strtoll(const char *nptr, char **endptr, int base);
|
||||
|
||||
|
@ -121,6 +121,9 @@ extern "C" {
|
||||
void __asan_set_death_callback(void (*callback)(void))
|
||||
ASAN_INTERFACE_FUNCTION_ATTRIBUTE;
|
||||
|
||||
void __asan_set_error_report_callback(void (*callback)(const char*))
|
||||
ASAN_INTERFACE_FUNCTION_ATTRIBUTE;
|
||||
|
||||
// Returns the estimated number of bytes that will be reserved by allocator
|
||||
// for request of "size" bytes. If ASan allocator can't allocate that much
|
||||
// memory, returns the maximal possible allocation size, otherwise returns
|
||||
|
@ -22,6 +22,9 @@
|
||||
|
||||
namespace __asan {
|
||||
|
||||
extern char *error_message_buffer;
|
||||
extern size_t error_message_buffer_pos, error_message_buffer_size;
|
||||
|
||||
void RawWrite(const char *buffer) {
|
||||
static const char *kRawWriteError = "RawWrite can't output requested buffer!";
|
||||
size_t length = (size_t)internal_strlen(buffer);
|
||||
@ -29,6 +32,14 @@ void RawWrite(const char *buffer) {
|
||||
AsanWrite(2, kRawWriteError, internal_strlen(kRawWriteError));
|
||||
AsanDie();
|
||||
}
|
||||
if (error_message_buffer) {
|
||||
int remaining = error_message_buffer_size - error_message_buffer_pos;
|
||||
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
||||
buffer, remaining);
|
||||
error_message_buffer[error_message_buffer_size - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += remaining > length ? length : remaining;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int AppendChar(char **buff, const char *buff_end, char c) {
|
||||
|
@ -52,6 +52,10 @@ int FLAG_sleep_before_dying;
|
||||
int asan_inited;
|
||||
bool asan_init_is_running;
|
||||
static void (*death_callback)(void);
|
||||
static void (*error_report_callback)(const char*);
|
||||
char *error_message_buffer = NULL;
|
||||
size_t error_message_buffer_pos = 0;
|
||||
size_t error_message_buffer_size = 0;
|
||||
|
||||
// -------------------------- Misc ---------------- {{{1
|
||||
void ShowStatsAndAbort() {
|
||||
@ -237,7 +241,7 @@ ASAN_REPORT_ERROR(store, true, 16)
|
||||
// dynamic libraries access the symbol even if it is not used by the executable
|
||||
// itself. This should help if the build system is removing dead code at link
|
||||
// time.
|
||||
static void force_interface_symbols() {
|
||||
static NOINLINE void force_interface_symbols() {
|
||||
volatile int fake_condition = 0; // prevent dead condition elimination.
|
||||
if (fake_condition) {
|
||||
__asan_report_load1(NULL);
|
||||
@ -253,6 +257,7 @@ static void force_interface_symbols() {
|
||||
__asan_register_global(0, 0, NULL);
|
||||
__asan_register_globals(NULL, 0);
|
||||
__asan_unregister_globals(NULL, 0);
|
||||
__asan_set_error_report_callback(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,6 +305,16 @@ void __asan_set_death_callback(void (*callback)(void)) {
|
||||
death_callback = callback;
|
||||
}
|
||||
|
||||
void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
|
||||
error_report_callback = callback;
|
||||
if (callback) {
|
||||
error_message_buffer_size = 1 << 14;
|
||||
error_message_buffer =
|
||||
(char*)AsanMmapSomewhereOrDie(error_message_buffer_size, __FUNCTION__);
|
||||
error_message_buffer_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp,
|
||||
uintptr_t addr, bool is_write, size_t access_size) {
|
||||
// Do not print more than one report, otherwise they will mix up.
|
||||
@ -389,6 +404,9 @@ void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp,
|
||||
PrintBytes(" ", (uintptr_t*)(aligned_shadow+2*kWordSize));
|
||||
PrintBytes(" ", (uintptr_t*)(aligned_shadow+3*kWordSize));
|
||||
PrintBytes(" ", (uintptr_t*)(aligned_shadow+4*kWordSize));
|
||||
if (error_report_callback) {
|
||||
error_report_callback(error_message_buffer);
|
||||
}
|
||||
AsanDie();
|
||||
}
|
||||
|
||||
|
@ -342,3 +342,21 @@ TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
|
||||
kInvalidPoisonMessage);
|
||||
free(array);
|
||||
}
|
||||
|
||||
static void ErrorReportCallbackOneToZ(const char *report) {
|
||||
int len = strlen(report);
|
||||
char *dup = (char*)malloc(len);
|
||||
strcpy(dup, report);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (dup[i] == '1') dup[i] = 'Z';
|
||||
}
|
||||
write(2, dup, len);
|
||||
free(dup);
|
||||
}
|
||||
|
||||
TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
|
||||
__asan_set_error_report_callback(ErrorReportCallbackOneToZ);
|
||||
char *array = Ident((char*)malloc(120));
|
||||
EXPECT_DEATH(ACCESS(array, 120), "size Z");
|
||||
__asan_set_error_report_callback(NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user