sanitizer_common.cc revision 591616d323d73b7ea7cd8fea4eec46cedccda27e
1//===-- sanitizer_common.cc -----------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common.h"
15#include "sanitizer_libc.h"
16
17namespace __sanitizer {
18
19static void (*DieCallback)(void);
20void SetDieCallback(void (*callback)(void)) {
21  DieCallback = callback;
22}
23
24void NORETURN Die() {
25  if (DieCallback) {
26    DieCallback();
27  }
28  Exit(1);
29}
30
31static CheckFailedCallbackType CheckFailedCallback;
32void SetCheckFailedCallback(CheckFailedCallbackType callback) {
33  CheckFailedCallback = callback;
34}
35
36void NORETURN CheckFailed(const char *file, int line, const char *cond,
37                          u64 v1, u64 v2) {
38  if (CheckFailedCallback) {
39    CheckFailedCallback(file, line, cond, v1, v2);
40  }
41  Report("Sanitizer CHECK failed: %s:%d %s (%zd, %zd)\n", file, line, cond,
42                                                          v1, v2);
43  Die();
44}
45
46void RawWrite(const char *buffer) {
47  static const char *kRawWriteError = "RawWrite can't output requested buffer!";
48  uptr length = (uptr)internal_strlen(buffer);
49  if (length != internal_write(2, buffer, length)) {
50    internal_write(2, kRawWriteError, internal_strlen(kRawWriteError));
51    Die();
52  }
53}
54
55uptr ReadFileToBuffer(const char *file_name, char **buff,
56                      uptr *buff_size, uptr max_len) {
57  const uptr kMinFileLen = kPageSize;
58  uptr read_len = 0;
59  *buff = 0;
60  *buff_size = 0;
61  // The files we usually open are not seekable, so try different buffer sizes.
62  for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
63    fd_t fd = internal_open(file_name, /*write*/ false);
64    if (fd == kInvalidFd) return 0;
65    UnmapOrDie(*buff, *buff_size);
66    *buff = (char*)MmapOrDie(size, __FUNCTION__);
67    *buff_size = size;
68    // Read up to one page at a time.
69    read_len = 0;
70    bool reached_eof = false;
71    while (read_len + kPageSize <= size) {
72      uptr just_read = internal_read(fd, *buff + read_len, kPageSize);
73      if (just_read == 0) {
74        reached_eof = true;
75        break;
76      }
77      read_len += just_read;
78    }
79    internal_close(fd);
80    if (reached_eof)  // We've read the whole file.
81      break;
82  }
83  return read_len;
84}
85
86// We don't want to use std::sort to avoid including <algorithm>, as
87// we may end up with two implementation of std::sort - one in instrumented
88// code, and the other in runtime.
89// qsort() from stdlib won't work as it calls malloc(), which results
90// in deadlock in ASan allocator.
91// We re-implement in-place sorting w/o recursion as straightforward heapsort.
92void SortArray(uptr *array, uptr size) {
93  if (size < 2)
94    return;
95  // Stage 1: insert elements to the heap.
96  for (uptr i = 1; i < size; i++) {
97    uptr j, p;
98    for (j = i; j > 0; j = p) {
99      p = (j - 1) / 2;
100      if (array[j] > array[p])
101        Swap(array[j], array[p]);
102      else
103        break;
104    }
105  }
106  // Stage 2: swap largest element with the last one,
107  // and sink the new top.
108  for (uptr i = size - 1; i > 0; i--) {
109    Swap(array[0], array[i]);
110    uptr j, max_ind;
111    for (j = 0; j < i; j = max_ind) {
112      uptr left = 2 * j + 1;
113      uptr right = 2 * j + 2;
114      max_ind = j;
115      if (left < i && array[left] > array[max_ind])
116        max_ind = left;
117      if (right < i && array[right] > array[max_ind])
118        max_ind = right;
119      if (max_ind != j)
120        Swap(array[j], array[max_ind]);
121      else
122        break;
123    }
124  }
125}
126
127}  // namespace __sanitizer
128