blob: 9fc2e91ed772eab37309ce30311f32d473260528 [file] [log] [blame]
//===- RewritePtr.cpp --------------------------------------------------- -===//
//
// The SAFECode Compiler
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements functions to rewrite out of bounds pointers.
//
//===----------------------------------------------------------------------===//
#include "PoolAllocator.h"
#include "DebugReport.h"
#include "RewritePtr.h"
#include "safecode/Runtime/BBRuntime.h"
#include "llvm/ADT/DenseMap.h"
#include <cstdio>
#include <map>
extern FILE * ReportLog;
NAMESPACE_SC_BEGIN
DebugPoolTy OOBPool;
// Map between rewrite pointer and source file information
llvm::DenseMap<void *, const char*> RewriteSourcefile;
llvm::DenseMap<void *, unsigned> RewriteLineno;
std::map<const void *, const void *> RewrittenPointers;
// Record from which object an OOB pointer originates
llvm::DenseMap<void *, std::pair<void *, void * > > RewrittenObjs;
//
// Function: rewrite_ptr()
//
// Description:
// Take the given pointer and rewrite it to an Out Of Bounds (OOB) pointer.
//
// Inputs:
// Pool - The pool in which the pointer should be located (but isn't).
// This value can be NULL if the caller doesn't know the pool.
// p - The pointer that needs to be rewritten.
// ObjStart - The address of the first valid byte of the object.
// ObjEnd - The address of the last valid byte of the object.
// SourceFile - The name of the source file in which the check requesting the
// rewrite is located.
// lineno - The line number within the source file in which the check
// requesting the rewrite is located.
//
void *
rewrite_ptr (DebugPoolTy * Pool,
const void * p,
void * ObjStart,
void * ObjEnd,
const char * SourceFile,
unsigned lineno) {
static unsigned char * invalidptr = 0;
//
// If this pointer has already been rewritten, do not rewrite it again.
//
if (RewrittenPointers.find (p) != RewrittenPointers.end()) {
return const_cast<void*>(RewrittenPointers[p]);
}
//
// Calculate a new rewrite pointer.
//
if (invalidptr == 0) invalidptr = (unsigned char*)InvalidLower;
++invalidptr;
//
// Ensure that we haven't run out of rewrite pointers.
//
void* P = invalidptr;
if ((uintptr_t) P == InvalidUpper) {
fprintf (stderr, "rewrite: out of rewrite ptrs: %p %p, pc=%p\n",
(void *) InvalidLower, (void *) InvalidUpper, invalidptr);
fflush (stderr);
return const_cast<void*>(p);
}
//
// If no pool was specified (as is the case for an ExactCheck), use a
// special Out of Bounds Pointer pool.
//
if (!Pool) Pool = &OOBPool;
//
// Determine if this pointer value has already been rewritten. If so, just
// return the previously rewritten value. Otherwise, insert a mapping from
// rewrite pointer to original pointer into the pool.
//
Pool->OOB.insert (invalidptr, ((unsigned char *)(invalidptr)), const_cast<void*>(p));
//
// If debugging tool support is enabled, then insert it into the global
// OOB pool as well; this will ensure that we can find the pointer on a
// memory protection violation (on faults, we don't have Pool handle
// information).
//
if (logregs) {
fprintf (ReportLog, "rewrite: %p: %p -> %p\n", (void*) Pool, p, invalidptr);
fflush (ReportLog);
}
OOBPool.OOB.insert (invalidptr, ((unsigned char *)(invalidptr)), const_cast<void*>(p));
RewriteSourcefile[invalidptr] = SourceFile;
RewriteLineno[invalidptr] = lineno;
RewrittenPointers[p] = invalidptr;
RewrittenObjs[invalidptr] = std::make_pair(ObjStart, ObjEnd);
return invalidptr;
}
NAMESPACE_SC_END
using namespace safecode;
//
// Function: getActualValue()
//
// Description:
// If src is an out of object pointer, get the original value.
//
void *
pchk_getActualValue (DebugPoolTy * Pool, void * p) {
//
// If the pointer is not within the rewrite pointer range, then it is not a
// rewritten pointer. Simply return its current value.
//
if (((uintptr_t)p <= InvalidLower) || ((uintptr_t)p >= InvalidUpper)) {
return p;
}
void * src = 0;
void* tag = 0;
void * end = 0;
//
// Look for the pointer in the pool's OOB pointer list. If we find it,
// return its actual value.
//
if (Pool && (Pool->OOB.find(p, src, end, tag))) {
if (logregs) {
fprintf (ReportLog, "getActualValue(1): %p: %p -> %p\n", (void*)Pool, p, tag);
fflush (ReportLog);
}
return tag;
}
//
// If we can't find the pointer in the pool's OOB list, perhaps it's in the
// global OOB Pool (this can happen when it's rewritten by an exact check).
//
if (OOBPool.OOB.find (p, src, end, tag)) {
if (logregs) {
fprintf (ReportLog, "getActualValue(2): %p: %p -> %p\n", (void*)&OOBPool, p, tag);
fflush (ReportLog);
}
return tag;
}
//
// If we can't find the pointer, no worries. If the program tries to use the
// pointer, another SAFECode checks should flag a failure. In this case,
// just return the pointer.
//
if (logregs) {
fprintf (ReportLog, "getActualValue(3): %p: %p -> %p\n", (void*)Pool, p, p);
fflush (ReportLog);
}
return p;
}