forked from OSchip/llvm-project
[asan] implement our own /proc/self/maps reader and use it on linux instead of sysinfo.h
llvm-svn: 147581
This commit is contained in:
parent
aca1885695
commit
cd271f5440
|
@ -264,7 +264,6 @@ $(BIN)/%_test$(SUFF).o: tests/%_test.mm $(RTL_HDR) $(MAKEFILE)
|
|||
$(BIN)/%$(SUFF).o: %.cc $(RTL_HDR) $(MAKEFILE)
|
||||
$(CXX) $(PIE) $(CFLAGS) -fPIC -c -O2 -fno-exceptions -funwind-tables \
|
||||
-o $@ -g $< -Ithird_party \
|
||||
-DASAN_USE_SYSINFO=1 \
|
||||
-DASAN_NEEDS_SEGV=$(ASAN_NEEDS_SEGV) \
|
||||
-DASAN_HAS_EXCEPTIONS=$(ASAN_HAS_EXCEPTIONS) \
|
||||
-DASAN_FLEXIBLE_MAPPING_AND_OFFSET=$(ASAN_FLEXIBLE_MAPPING_AND_OFFSET) \
|
||||
|
@ -272,7 +271,6 @@ $(BIN)/%$(SUFF).o: %.cc $(RTL_HDR) $(MAKEFILE)
|
|||
|
||||
$(BIN)/%$(SUFF).o: %.c $(RTL_HDR) $(MAKEFILE)
|
||||
$(CC) $(PIE) $(CFLAGS) -fPIC -c -O2 -o $@ -g $< -Ithird_party \
|
||||
-DASAN_USE_SYSINFO=1 \
|
||||
$(ASAN_FLAGS)
|
||||
|
||||
ifeq ($(OS),darwin)
|
||||
|
|
|
@ -45,8 +45,12 @@
|
|||
|
||||
// If set, sysinfo/sysinfo.h will be used to iterate over /proc/maps.
|
||||
#ifndef ASAN_USE_SYSINFO
|
||||
#ifdef __linux__
|
||||
# define ASAN_USE_SYSINFO 0
|
||||
#else
|
||||
# define ASAN_USE_SYSINFO 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If set, asan will install its own SEGV signal handler.
|
||||
#ifndef ASAN_NEEDS_SEGV
|
||||
|
@ -99,10 +103,18 @@ ssize_t AsanRead(int fd, void *buf, size_t count);
|
|||
ssize_t AsanWrite(int fd, const void *buf, size_t count);
|
||||
int AsanClose(int fd);
|
||||
|
||||
// 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',
|
||||
// Returns the number of read bytes or -1 if file can not be opened.
|
||||
ssize_t ReadFileToBuffer(const char *file_name, char **buff,
|
||||
size_t *buff_size, size_t max_len);
|
||||
|
||||
// asan_printf.cc
|
||||
void RawWrite(const char *buffer);
|
||||
int SNPrint(char *buffer, size_t length, const char *format, ...);
|
||||
void Printf(const char *format, ...);
|
||||
int SScanf(const char *str, const char *format, ...);
|
||||
void Report(const char *format, ...);
|
||||
|
||||
// Don't use std::min and std::max, to minimize dependency on libstdc++.
|
||||
|
|
|
@ -13,12 +13,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
#ifdef __linux__
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_procmaps.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern char _DYNAMIC[];
|
||||
|
@ -96,6 +99,57 @@ int AsanClose(int fd) {
|
|||
return close(fd);
|
||||
}
|
||||
|
||||
AsanProcMaps::AsanProcMaps() {
|
||||
proc_self_maps_buff_len_ =
|
||||
ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_,
|
||||
&proc_self_maps_buff_mmaped_size_, 1 << 20);
|
||||
CHECK(proc_self_maps_buff_len_ > 0);
|
||||
// AsanWrite(2, proc_self_maps_buff_, proc_self_maps_buff_len_);
|
||||
Reset();
|
||||
}
|
||||
|
||||
AsanProcMaps::~AsanProcMaps() {
|
||||
AsanUnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_);
|
||||
}
|
||||
|
||||
void AsanProcMaps::Reset() {
|
||||
current_ = proc_self_maps_buff_;
|
||||
}
|
||||
|
||||
bool AsanProcMaps::Next(uint64_t *start, uint64_t *end,
|
||||
uint64_t *offset, char filename[],
|
||||
size_t filename_size) {
|
||||
char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_;
|
||||
if (current_ >= last) return false;
|
||||
int consumed = 0;
|
||||
char flags[10];
|
||||
int major, minor;
|
||||
uint64_t inode;
|
||||
char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
|
||||
if (next_line == NULL)
|
||||
next_line = last;
|
||||
if (SScanf(current_,
|
||||
"%llx-%llx %4s %llx %x:%x %lld %n",
|
||||
start, end, flags, offset, &major, &minor,
|
||||
&inode, &consumed) != 7)
|
||||
return false;
|
||||
current_ += consumed;
|
||||
// Skip spaces.
|
||||
while (current_ < next_line && *current_ == ' ')
|
||||
current_++;
|
||||
// Fill in the filename.
|
||||
size_t i = 0;
|
||||
while (current_ < next_line) {
|
||||
if (filename && i < filename_size - 1)
|
||||
filename[i++] = *current_;
|
||||
current_++;
|
||||
}
|
||||
if (filename && i < filename_size)
|
||||
filename[i] = 0;
|
||||
current_ = next_line + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // __linux__
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "asan_interceptors.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -178,4 +179,12 @@ void Report(const char *format, ...) {
|
|||
RawWrite(buffer);
|
||||
}
|
||||
|
||||
int SScanf(const char *str, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int res = vsscanf(str, format, args);
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "asan_lock.h"
|
||||
#include "asan_mac.h"
|
||||
#include "asan_mapping.h"
|
||||
#include "asan_procmaps.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_stats.h"
|
||||
#include "asan_thread.h"
|
||||
|
@ -119,22 +120,19 @@ static void PrintBytes(const char *before, uintptr_t *a) {
|
|||
Printf("\n");
|
||||
}
|
||||
|
||||
// Opens the file 'file_name" and reads up to 'max_len' bytes.
|
||||
// The resulting buffer is mmaped and stored in '*buff'.
|
||||
// Returns the number of read bytes or -1 if file can not be opened.
|
||||
static ssize_t ReadFileToBuffer(const char *file_name, char **buff,
|
||||
size_t max_len) {
|
||||
ssize_t ReadFileToBuffer(const char *file_name, char **buff,
|
||||
size_t *buff_size, size_t max_len) {
|
||||
const size_t kMinFileLen = kPageSize;
|
||||
ssize_t read_len = -1;
|
||||
*buff = 0;
|
||||
size_t maped_size = 0;
|
||||
*buff_size = 0;
|
||||
// The files we usually open are not seekable, so try different buffer sizes.
|
||||
for (size_t size = kMinFileLen; size <= max_len; size *= 2) {
|
||||
int fd = AsanOpenReadonly(file_name);
|
||||
if (fd < 0) return -1;
|
||||
AsanUnmapOrDie(*buff, maped_size);
|
||||
maped_size = size;
|
||||
AsanUnmapOrDie(*buff, *buff_size);
|
||||
*buff = (char*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
|
||||
*buff_size = size;
|
||||
read_len = AsanRead(fd, *buff, size);
|
||||
AsanClose(fd);
|
||||
if (read_len < size) // We've read the whole file.
|
||||
|
@ -151,7 +149,9 @@ static const char* GetEnvFromProcSelfEnviron(const char* name) {
|
|||
static bool inited;
|
||||
if (!inited) {
|
||||
inited = true;
|
||||
len = ReadFileToBuffer("/proc/self/environ", &environ, 1 << 20);
|
||||
size_t environ_size;
|
||||
len = ReadFileToBuffer("/proc/self/environ",
|
||||
&environ, &environ_size, 1 << 20);
|
||||
}
|
||||
if (!environ || len <= 0) return NULL;
|
||||
size_t namelen = internal_strlen(name);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_lock.h"
|
||||
#include "asan_procmaps.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
#include "asan_thread_registry.h"
|
||||
|
@ -128,9 +129,27 @@ void AsanStackTrace::PrintStack(uintptr_t *addr, size_t size) {
|
|||
|
||||
#else // ASAN_USE_SYSINFO
|
||||
void AsanStackTrace::PrintStack(uintptr_t *addr, size_t size) {
|
||||
AsanProcMaps proc_maps;
|
||||
for (size_t i = 0; i < size && addr[i]; i++) {
|
||||
proc_maps.Reset();
|
||||
uintptr_t pc = addr[i];
|
||||
Printf(" #%ld 0x%lx\n", i, pc);
|
||||
uint64_t start, end, offset;
|
||||
char filename[4096];
|
||||
bool found = 0;
|
||||
int map_idx = 0;
|
||||
while (proc_maps.Next(&start, &end, &offset,
|
||||
filename, sizeof(filename))) {
|
||||
if (pc >= start && pc <= end) {
|
||||
found = true;
|
||||
uintptr_t relative_pc = (map_idx == 0) ? pc : (pc - start);
|
||||
Printf(" #%ld 0x%lx (%s+0x%lx)\n", i, pc, filename, relative_pc);
|
||||
break;
|
||||
}
|
||||
map_idx++;
|
||||
}
|
||||
if (!found) {
|
||||
Printf(" #%ld 0x%lx\n", i, pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ASAN_USE_SYSINFO
|
||||
|
|
|
@ -13,14 +13,11 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
#include "asan_allocator.h"
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_procmaps.h"
|
||||
#include "asan_thread.h"
|
||||
#include "asan_thread_registry.h"
|
||||
#include "asan_mapping.h"
|
||||
|
||||
#if ASAN_USE_SYSINFO == 1
|
||||
#include "sysinfo/sysinfo.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <pthread.h>
|
||||
|
@ -126,17 +123,16 @@ void AsanThread::SetThreadStackTopAndBottom() {
|
|||
int local;
|
||||
CHECK(AddrIsInStack((uintptr_t)&local));
|
||||
#else
|
||||
#if ASAN_USE_SYSINFO == 1
|
||||
if (tid() == 0) {
|
||||
// This is the main thread. Libpthread may not be initialized yet.
|
||||
struct rlimit rl;
|
||||
CHECK(getrlimit(RLIMIT_STACK, &rl) == 0);
|
||||
|
||||
// Find the mapping that contains a stack variable.
|
||||
ProcMapsIterator it(0);
|
||||
uint64_t start, end;
|
||||
AsanProcMaps proc_maps;
|
||||
uint64_t start, end, offset;
|
||||
uint64_t prev_end = 0;
|
||||
while (it.Next(&start, &end, NULL, NULL, NULL, NULL)) {
|
||||
while (proc_maps.Next(&start, &end, &offset, NULL, 0)) {
|
||||
if ((uintptr_t)&rl < end)
|
||||
break;
|
||||
prev_end = end;
|
||||
|
@ -155,7 +151,6 @@ void AsanThread::SetThreadStackTopAndBottom() {
|
|||
CHECK(AddrIsInStack((uintptr_t)&rl));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
pthread_attr_t attr;
|
||||
CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
|
||||
size_t stacksize = 0;
|
||||
|
|
Loading…
Reference in New Issue