aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_common.h')
-rw-r--r--lib/sanitizer_common/sanitizer_common.h214
1 files changed, 110 insertions, 104 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 1fbaee7e39a1..3b999edfbe58 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -39,11 +39,7 @@ struct StackTrace;
const uptr kWordSize = SANITIZER_WORDSIZE / 8;
const uptr kWordSizeInBits = 8 * kWordSize;
-#if defined(__powerpc__) || defined(__powerpc64__)
- const uptr kCacheLineSize = 128;
-#else
- const uptr kCacheLineSize = 64;
-#endif
+const uptr kCacheLineSize = SANITIZER_CACHE_LINE_SIZE;
const uptr kMaxPathLength = 4096;
@@ -52,7 +48,7 @@ const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
static const uptr kErrorMessageBufferSize = 1 << 16;
// Denotes fake PC values that come from JIT/JAVA/etc.
-// For such PC values __tsan_symbolize_external() will be called.
+// For such PC values __tsan_symbolize_external_ex() will be called.
const u64 kExternalPCBit = 1ULL << 60;
extern const char *SanitizerToolName; // Can be changed by the tool.
@@ -92,8 +88,8 @@ void UnmapOrDie(void *addr, uptr size);
// Behaves just like MmapOrDie, but tolerates out of memory condition, in that
// case returns nullptr.
void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
-void *MmapFixedNoReserve(uptr fixed_addr, uptr size,
- const char *name = nullptr);
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
+ WARN_UNUSED_RESULT;
void *MmapNoReserveOrDie(uptr size, const char *mem_type);
void *MmapFixedOrDie(uptr fixed_addr, uptr size);
// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
@@ -110,9 +106,11 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
bool MprotectNoAccess(uptr addr, uptr size);
bool MprotectReadOnly(uptr addr, uptr size);
+void MprotectMallocZones(void *addr, int prot);
+
// Find an available address space.
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
- uptr *largest_gap_found);
+ uptr *largest_gap_found, uptr *max_occupied_addr);
// Used to check if we can map shadow memory to a fixed location.
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
@@ -122,8 +120,8 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end);
void IncreaseTotalMmap(uptr size);
void DecreaseTotalMmap(uptr size);
uptr GetRSS();
-void NoHugePagesInRegion(uptr addr, uptr length);
-void DontDumpShadowMemory(uptr addr, uptr length);
+bool NoHugePagesInRegion(uptr addr, uptr length);
+bool DontDumpShadowMemory(uptr addr, uptr length);
// Check if the built VMA size matches the runtime one.
void CheckVMASize();
void RunMallocHooks(const void *ptr, uptr size);
@@ -153,49 +151,6 @@ typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
// |stats_size| elements.
void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);
-// InternalScopedBuffer can be used instead of large stack arrays to
-// keep frame size low.
-// FIXME: use InternalAlloc instead of MmapOrDie once
-// InternalAlloc is made libc-free.
-template <typename T>
-class InternalScopedBuffer {
- public:
- explicit InternalScopedBuffer(uptr cnt) {
- cnt_ = cnt;
- ptr_ = (T *)MmapOrDie(cnt * sizeof(T), "InternalScopedBuffer");
- }
- ~InternalScopedBuffer() { UnmapOrDie(ptr_, cnt_ * sizeof(T)); }
- T &operator[](uptr i) { return ptr_[i]; }
- T *data() { return ptr_; }
- uptr size() { return cnt_ * sizeof(T); }
-
- private:
- T *ptr_;
- uptr cnt_;
- // Disallow copies and moves.
- InternalScopedBuffer(const InternalScopedBuffer &) = delete;
- InternalScopedBuffer &operator=(const InternalScopedBuffer &) = delete;
- InternalScopedBuffer(InternalScopedBuffer &&) = delete;
- InternalScopedBuffer &operator=(InternalScopedBuffer &&) = delete;
-};
-
-class InternalScopedString : public InternalScopedBuffer<char> {
- public:
- explicit InternalScopedString(uptr max_length)
- : InternalScopedBuffer<char>(max_length), length_(0) {
- (*this)[0] = '\0';
- }
- uptr length() { return length_; }
- void clear() {
- (*this)[0] = '\0';
- length_ = 0;
- }
- void append(const char *format, ...);
-
- private:
- uptr length_;
-};
-
// Simple low-level (mmap-based) allocator for internal use. Doesn't have
// constructor, so all instances of LowLevelAllocator should be
// linker initialized.
@@ -243,15 +198,6 @@ class ScopedErrorReportLock {
extern uptr stoptheworld_tracer_pid;
extern uptr stoptheworld_tracer_ppid;
-// Opens the file 'file_name" and reads up to 'max_len' bytes.
-// The resulting buffer is mmaped and stored in '*buff'.
-// The size of the mmaped region is stored in '*buff_size'.
-// The total number of read bytes is stored in '*read_len'.
-// Returns true if file was successfully opened and read.
-bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
- uptr *read_len, uptr max_len = 1 << 26,
- error_t *errno_p = nullptr);
-
bool IsAccessibleMemoryRange(uptr beg, uptr size);
// Error report formatting.
@@ -275,6 +221,7 @@ bool SetEnv(const char *name, const char *value);
u32 GetUid();
void ReExec();
+void CheckASLR();
char **GetArgv();
void PrintCmdline();
bool StackSizeIsUnlimited();
@@ -283,7 +230,7 @@ void SetStackSizeLimitInBytes(uptr limit);
bool AddressSpaceIsUnlimited();
void SetAddressSpaceUnlimited();
void AdjustStackSize(void *attr);
-void PrepareForSandboxing(__sanitizer_sandbox_arguments *args);
+void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args);
void SetSandboxingCallback(void (*f)());
void InitializeCoverage(bool enabled, const char *coverage_dir);
@@ -297,8 +244,6 @@ void SleepForMillis(int millis);
u64 NanoTime();
u64 MonotonicNanoTime();
int Atexit(void (*function)(void));
-void SortArray(uptr *array, uptr size);
-void SortArray(u32 *array, uptr size);
bool TemplateMatch(const char *templ, const char *str);
// Exit
@@ -310,13 +255,6 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
const char *mmap_type, error_t err,
bool raw_report = false);
-// Set the name of the current thread to 'name', return true on succees.
-// The name may be truncated to a system-dependent limit.
-bool SanitizerSetThreadName(const char *name);
-// Get the name of the current thread (no more than max_len bytes),
-// return true on succees. name should have space for at least max_len+1 bytes.
-bool SanitizerGetThreadName(char *name, int max_len);
-
// Specific tools may override behavior of "Die" and "CheckFailed" functions
// to do tool-specific job.
typedef void (*DieCallbackType)(void);
@@ -382,6 +320,8 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info,
void ReportErrorSummary(const char *error_type, const StackTrace *trace,
const char *alt_tool_name = nullptr);
+void ReportMmapWriteExec(int prot);
+
// Math
#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
extern "C" {
@@ -489,13 +429,12 @@ template<typename T>
class InternalMmapVectorNoCtor {
public:
void Initialize(uptr initial_capacity) {
- capacity_ = Max(initial_capacity, (uptr)1);
+ capacity_bytes_ = 0;
size_ = 0;
- data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVectorNoCtor");
- }
- void Destroy() {
- UnmapOrDie(data_, capacity_ * sizeof(T));
+ data_ = 0;
+ reserve(initial_capacity);
}
+ void Destroy() { UnmapOrDie(data_, capacity_bytes_); }
T &operator[](uptr i) {
CHECK_LT(i, size_);
return data_[i];
@@ -505,10 +444,10 @@ class InternalMmapVectorNoCtor {
return data_[i];
}
void push_back(const T &element) {
- CHECK_LE(size_, capacity_);
- if (size_ == capacity_) {
+ CHECK_LE(size_, capacity());
+ if (size_ == capacity()) {
uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
- Resize(new_capacity);
+ Realloc(new_capacity);
}
internal_memcpy(&data_[size_++], &element, sizeof(T));
}
@@ -529,12 +468,15 @@ class InternalMmapVectorNoCtor {
T *data() {
return data_;
}
- uptr capacity() const {
- return capacity_;
+ uptr capacity() const { return capacity_bytes_ / sizeof(T); }
+ void reserve(uptr new_size) {
+ // Never downsize internal buffer.
+ if (new_size > capacity())
+ Realloc(new_size);
}
void resize(uptr new_size) {
- Resize(new_size);
if (new_size > size_) {
+ reserve(new_size);
internal_memset(&data_[size_], 0, sizeof(T) * (new_size - size_));
}
size_ = new_size;
@@ -556,39 +498,84 @@ class InternalMmapVectorNoCtor {
return data() + size();
}
+ void swap(InternalMmapVectorNoCtor &other) {
+ Swap(data_, other.data_);
+ Swap(capacity_bytes_, other.capacity_bytes_);
+ Swap(size_, other.size_);
+ }
+
private:
- void Resize(uptr new_capacity) {
+ void Realloc(uptr new_capacity) {
CHECK_GT(new_capacity, 0);
CHECK_LE(size_, new_capacity);
- T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
- "InternalMmapVector");
+ uptr new_capacity_bytes =
+ RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
+ T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector");
internal_memcpy(new_data, data_, size_ * sizeof(T));
- T *old_data = data_;
+ UnmapOrDie(data_, capacity_bytes_);
data_ = new_data;
- UnmapOrDie(old_data, capacity_ * sizeof(T));
- capacity_ = new_capacity;
+ capacity_bytes_ = new_capacity_bytes;
}
T *data_;
- uptr capacity_;
+ uptr capacity_bytes_;
uptr size_;
};
+template <typename T>
+bool operator==(const InternalMmapVectorNoCtor<T> &lhs,
+ const InternalMmapVectorNoCtor<T> &rhs) {
+ if (lhs.size() != rhs.size()) return false;
+ return internal_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
+}
+
+template <typename T>
+bool operator!=(const InternalMmapVectorNoCtor<T> &lhs,
+ const InternalMmapVectorNoCtor<T> &rhs) {
+ return !(lhs == rhs);
+}
+
template<typename T>
class InternalMmapVector : public InternalMmapVectorNoCtor<T> {
public:
- explicit InternalMmapVector(uptr initial_capacity) {
- InternalMmapVectorNoCtor<T>::Initialize(initial_capacity);
+ InternalMmapVector() { InternalMmapVectorNoCtor<T>::Initialize(1); }
+ explicit InternalMmapVector(uptr cnt) {
+ InternalMmapVectorNoCtor<T>::Initialize(cnt);
+ this->resize(cnt);
}
~InternalMmapVector() { InternalMmapVectorNoCtor<T>::Destroy(); }
- // Disallow evil constructors.
- InternalMmapVector(const InternalMmapVector&);
- void operator=(const InternalMmapVector&);
+ // Disallow copies and moves.
+ InternalMmapVector(const InternalMmapVector &) = delete;
+ InternalMmapVector &operator=(const InternalMmapVector &) = delete;
+ InternalMmapVector(InternalMmapVector &&) = delete;
+ InternalMmapVector &operator=(InternalMmapVector &&) = delete;
+};
+
+class InternalScopedString : public InternalMmapVector<char> {
+ public:
+ explicit InternalScopedString(uptr max_length)
+ : InternalMmapVector<char>(max_length), length_(0) {
+ (*this)[0] = '\0';
+ }
+ uptr length() { return length_; }
+ void clear() {
+ (*this)[0] = '\0';
+ length_ = 0;
+ }
+ void append(const char *format, ...);
+
+ private:
+ uptr length_;
+};
+
+template <class T>
+struct CompareLess {
+ bool operator()(const T &a, const T &b) const { return a < b; }
};
// HeapSort for arrays and InternalMmapVector.
-template<class Container, class Compare>
-void InternalSort(Container *v, uptr size, Compare comp) {
+template <class T, class Compare = CompareLess<T>>
+void Sort(T *v, uptr size, Compare comp = {}) {
if (size < 2)
return;
// Stage 1: insert elements to the heap.
@@ -596,8 +583,8 @@ void InternalSort(Container *v, uptr size, Compare comp) {
uptr j, p;
for (j = i; j > 0; j = p) {
p = (j - 1) / 2;
- if (comp((*v)[p], (*v)[j]))
- Swap((*v)[j], (*v)[p]);
+ if (comp(v[p], v[j]))
+ Swap(v[j], v[p]);
else
break;
}
@@ -605,18 +592,18 @@ void InternalSort(Container *v, uptr size, Compare comp) {
// Stage 2: swap largest element with the last one,
// and sink the new top.
for (uptr i = size - 1; i > 0; i--) {
- Swap((*v)[0], (*v)[i]);
+ Swap(v[0], v[i]);
uptr j, max_ind;
for (j = 0; j < i; j = max_ind) {
uptr left = 2 * j + 1;
uptr right = 2 * j + 2;
max_ind = j;
- if (left < i && comp((*v)[max_ind], (*v)[left]))
+ if (left < i && comp(v[max_ind], v[left]))
max_ind = left;
- if (right < i && comp((*v)[max_ind], (*v)[right]))
+ if (right < i && comp(v[max_ind], v[right]))
max_ind = right;
if (max_ind != j)
- Swap((*v)[j], (*v)[max_ind]);
+ Swap(v[j], v[max_ind]);
else
break;
}
@@ -650,6 +637,25 @@ enum ModuleArch {
kModuleArchARM64
};
+// Opens the file 'file_name" and reads up to 'max_len' bytes.
+// The resulting buffer is mmaped and stored in '*buff'.
+// Returns true if file was successfully opened and read.
+bool ReadFileToVector(const char *file_name,
+ InternalMmapVectorNoCtor<char> *buff,
+ uptr max_len = 1 << 26, error_t *errno_p = nullptr);
+
+// Opens the file 'file_name" and reads up to 'max_len' bytes.
+// This function is less I/O efficient than ReadFileToVector as it may reread
+// file multiple times to avoid mmap during read attempts. It's used to read
+// procmap, so short reads with mmap in between can produce inconsistent result.
+// The resulting buffer is mmaped and stored in '*buff'.
+// The size of the mmaped region is stored in '*buff_size'.
+// The total number of read bytes is stored in '*read_len'.
+// Returns true if file was successfully opened and read.
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+ uptr *read_len, uptr max_len = 1 << 26,
+ error_t *errno_p = nullptr);
+
// 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) {