forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			147 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- asan_debugging.cc -------------------------------------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file is a part of AddressSanitizer, an address sanity checker.
 | 
						|
//
 | 
						|
// This file contains various functions that are generally useful to call when
 | 
						|
// using a debugger (LLDB, GDB).
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "asan_allocator.h"
 | 
						|
#include "asan_descriptions.h"
 | 
						|
#include "asan_flags.h"
 | 
						|
#include "asan_internal.h"
 | 
						|
#include "asan_mapping.h"
 | 
						|
#include "asan_report.h"
 | 
						|
#include "asan_thread.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
using namespace __asan;
 | 
						|
 | 
						|
static void FindInfoForStackVar(uptr addr, const char *frame_descr, uptr offset,
 | 
						|
                                char *name, uptr name_size,
 | 
						|
                                uptr ®ion_address, uptr ®ion_size) {
 | 
						|
  InternalMmapVector<StackVarDescr> vars(16);
 | 
						|
  if (!ParseFrameDescription(frame_descr, &vars)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (uptr i = 0; i < vars.size(); i++) {
 | 
						|
    if (offset <= vars[i].beg + vars[i].size) {
 | 
						|
      // We use name_len + 1 because strlcpy will guarantee a \0 at the end, so
 | 
						|
      // if we're limiting the copy due to name_len, we add 1 to ensure we copy
 | 
						|
      // the whole name and then terminate with '\0'.
 | 
						|
      internal_strlcpy(name, vars[i].name_pos,
 | 
						|
                       Min(name_size, vars[i].name_len + 1));
 | 
						|
      region_address = addr - (offset - vars[i].beg);
 | 
						|
      region_size = vars[i].size;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
uptr AsanGetStack(uptr addr, uptr *trace, u32 size, u32 *thread_id,
 | 
						|
                         bool alloc_stack) {
 | 
						|
  AsanChunkView chunk = FindHeapChunkByAddress(addr);
 | 
						|
  if (!chunk.IsValid()) return 0;
 | 
						|
 | 
						|
  StackTrace stack(nullptr, 0);
 | 
						|
  if (alloc_stack) {
 | 
						|
    if (chunk.AllocTid() == kInvalidTid) return 0;
 | 
						|
    stack = chunk.GetAllocStack();
 | 
						|
    if (thread_id) *thread_id = chunk.AllocTid();
 | 
						|
  } else {
 | 
						|
    if (chunk.FreeTid() == kInvalidTid) return 0;
 | 
						|
    stack = chunk.GetFreeStack();
 | 
						|
    if (thread_id) *thread_id = chunk.FreeTid();
 | 
						|
  }
 | 
						|
 | 
						|
  if (trace && size) {
 | 
						|
    size = Min(size, Min(stack.size, kStackTraceMax));
 | 
						|
    for (uptr i = 0; i < size; i++)
 | 
						|
      trace[i] = StackTrace::GetPreviousInstructionPc(stack.trace[i]);
 | 
						|
 | 
						|
    return size;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 | 
						|
 | 
						|
SANITIZER_INTERFACE_ATTRIBUTE
 | 
						|
const char *__asan_locate_address(uptr addr, char *name, uptr name_size,
 | 
						|
                                  uptr *region_address_ptr,
 | 
						|
                                  uptr *region_size_ptr) {
 | 
						|
  AddressDescription descr(addr);
 | 
						|
  uptr region_address = 0;
 | 
						|
  uptr region_size = 0;
 | 
						|
  const char *region_kind = nullptr;
 | 
						|
  if (name && name_size > 0) name[0] = 0;
 | 
						|
 | 
						|
  if (auto shadow = descr.AsShadow()) {
 | 
						|
    // region_{address,size} are already 0
 | 
						|
    switch (shadow->kind) {
 | 
						|
      case kShadowKindLow:
 | 
						|
        region_kind = "low shadow";
 | 
						|
        break;
 | 
						|
      case kShadowKindGap:
 | 
						|
        region_kind = "shadow gap";
 | 
						|
        break;
 | 
						|
      case kShadowKindHigh:
 | 
						|
        region_kind = "high shadow";
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  } else if (auto heap = descr.AsHeap()) {
 | 
						|
    region_kind = "heap";
 | 
						|
    region_address = heap->chunk_access.chunk_begin;
 | 
						|
    region_size = heap->chunk_access.chunk_size;
 | 
						|
  } else if (auto stack = descr.AsStack()) {
 | 
						|
    region_kind = "stack";
 | 
						|
    if (!stack->frame_descr) {
 | 
						|
      // region_{address,size} are already 0
 | 
						|
    } else {
 | 
						|
      FindInfoForStackVar(addr, stack->frame_descr, stack->offset, name,
 | 
						|
                          name_size, region_address, region_size);
 | 
						|
    }
 | 
						|
  } else if (auto global = descr.AsGlobal()) {
 | 
						|
    region_kind = "global";
 | 
						|
    auto &g = global->globals[0];
 | 
						|
    internal_strlcpy(name, g.name, name_size);
 | 
						|
    region_address = g.beg;
 | 
						|
    region_size = g.size;
 | 
						|
  } else {
 | 
						|
    // region_{address,size} are already 0
 | 
						|
    region_kind = "heap-invalid";
 | 
						|
  }
 | 
						|
 | 
						|
  CHECK(region_kind);
 | 
						|
  if (region_address_ptr) *region_address_ptr = region_address;
 | 
						|
  if (region_size_ptr) *region_size_ptr = region_size;
 | 
						|
  return region_kind;
 | 
						|
}
 | 
						|
 | 
						|
SANITIZER_INTERFACE_ATTRIBUTE
 | 
						|
uptr __asan_get_alloc_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
 | 
						|
  return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ true);
 | 
						|
}
 | 
						|
 | 
						|
SANITIZER_INTERFACE_ATTRIBUTE
 | 
						|
uptr __asan_get_free_stack(uptr addr, uptr *trace, uptr size, u32 *thread_id) {
 | 
						|
  return AsanGetStack(addr, trace, size, thread_id, /* alloc_stack */ false);
 | 
						|
}
 | 
						|
 | 
						|
SANITIZER_INTERFACE_ATTRIBUTE
 | 
						|
void __asan_get_shadow_mapping(uptr *shadow_scale, uptr *shadow_offset) {
 | 
						|
  if (shadow_scale)
 | 
						|
    *shadow_scale = SHADOW_SCALE;
 | 
						|
  if (shadow_offset)
 | 
						|
    *shadow_offset = SHADOW_OFFSET;
 | 
						|
}
 |