blob: ba22c3aaef0d3c5b41f16f564a78a7eef0784b48 [file] [log] [blame]
//===- Report.h - Debugging reports for bugs found by SAFECode ------------===//
//
// The SAFECode Compiler Project
//
// 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 for creating reports for the SAFECode
// run-time.
//
//===----------------------------------------------------------------------===//
#ifndef _REPORT_H_
#define _REPORT_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "safecode/Config/config.h"
#ifdef SC_DEBUGTOOL
#define ABORT_PROGRAM() abort()
#else
//#define ABORT_PROGRAM() *((volatile int*)NULL)
#define ABORT_PROGRAM() __builtin_trap()
#endif
extern FILE * ReportLog;
#ifdef SC_DEBUGTOOL
// Global Configuration Information
extern unsigned StopOnError;
static unsigned alertNum = 0;
static unsigned initialized = 0;
//
// Function: printAlertHeader()
//
// Description:
// Increment the alert number and print a header for this report message.
//
static unsigned
printAlertHeader (void) {
//
// Initialize the reporting code if necessary. This cannot be done in the
// SAFECode initialization routines because those need to run before
// constructors are executed, and the libc stdio functions may not have been
// initialized at that point.
//
if (!initialized) {
//
// Open up an additional file for error reporting.
//
ReportLog = fopen ("sclogfile", "a");
fprintf (ReportLog, "\n");
fprintf (ReportLog, "New Run of Program\n");
fprintf (ReportLog, "====================================================\n");
fflush (ReportLog);
initialized = 1;
}
fprintf (ReportLog, "=======+++++++ SAFECODE RUNTIME ALERT #%04d +++++++=======\n",
++alertNum);
return alertNum;
}
//
// Function: ReportDanglingPointer()
//
// Description:
// Create a report entry for a dangling pointer error.
//
// Inputs:
// addr - The dangling pointer value that was dereferenced.
// pc - The program counter of the instruction.
// allocpc - The program counter at which the object was last allocated.
// allocgen - The generation number of the allocation.
// freepc - The program counter at which the object was last freed.
// freegen - The generation number of the free.
//
static void
ReportDanglingPointer (void * addr,
unsigned pc,
unsigned allocpc,
unsigned allocgen,
unsigned freepc,
unsigned freegen) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Dangling pointer access to memory address 0x%p \n", id, addr);
fprintf (ReportLog, "%04d: at program counter 0x%08x\n", id, (unsigned)pc);
fprintf (ReportLog, "%04d:\tObject allocated at program counter : 0x%08x \n", id, (unsigned)allocpc);
fprintf (ReportLog, "%04d:\tObject allocation generation number : %d \n", id, allocgen);
fprintf (ReportLog, "%04d:\tObject freed at program counter : 0x%08x \n", id, freepc);
fprintf (ReportLog, "%04d:\tObject free generation number : %d \n", id, freegen);
fprintf(ReportLog, "=======+++++++ end of runtime error report +++++++=======\n");
if (StopOnError) ABORT_PROGRAM();
return;
}
//
// Function: ReportLoadStoreCheck()
//
// Description:
// Report a failure on a load or store check.
//
// Inputs:
// ptr - The pointer for the failed load/store operation.
// pc - The program counter of the failed run-time check.
//
static void
ReportLoadStoreCheck (void * ptr,
void * pc,
char * SourceFile,
unsigned lineno) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Load/Store violation to memory address %p\n", id, ptr);
fprintf (ReportLog, "%04d: at program counter %p\n", id, pc);
fprintf (ReportLog, "%04d:\tAddress : %p \n", id, ptr);
fprintf (ReportLog, "%04d:\tSource filename : %s \n", id, SourceFile);
fprintf (ReportLog, "%04d:\tSource line number : %d \n", id, lineno);
fflush (ReportLog);
if (StopOnError) ABORT_PROGRAM();
return;
}
//
// Function: ReportBoundsCheck()
//
// Description:
// Generate a report for a bounds check violation.
//
// Inputs:
// src - The source pointer for the failed indexing operation.
// dest - The result pointer for the failed indexing operation.
// allocID - The generation number of the object's allocation.
// allocPC - The program counter at which the object was last allocated.
// pc - The program counter of the failed run-time check.
// objstart - The start of the object in which the source pointer was found.
// objlen - The length of the object in which the source pointer was found.
// SourceFile - The source file in which the check failed.
// lineno - The line number at which the check failed.
// allocSF - The source file in which the object was allocated.
// allocLN - The line number at which the object was allocated.
//
// Note:
// An objstart and objlen of 0 indicate that the source pointer was not found
// within a valid object.
//
static void
ReportBoundsCheck (unsigned src,
unsigned dest,
unsigned allocID,
unsigned allocPC,
unsigned pc,
unsigned objstart,
unsigned objlen,
unsigned char * SourceFile,
unsigned lineno,
unsigned char * allocSF,
unsigned allocLN) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Bounds violation to memory address 0x%08x\n", id, dest);
fprintf (ReportLog, "%04d: at program counter 0x%08x\n", id, pc);
fprintf (ReportLog, "%04d:\tIndex source pointer : 0x%08x \n", id, src);
fprintf (ReportLog, "%04d:\tIndex result pointer : 0x%08x \n", id, dest);
fprintf (ReportLog, "%04d:\tSource filename : %s \n", id, SourceFile);
fprintf (ReportLog, "%04d:\tSource line number : %d \n", id, lineno);
if (objstart || objlen) {
fprintf (ReportLog, "%04d:\tObject lower bound : 0x%08x \n", id, objstart);
fprintf (ReportLog, "%04d:\tObject upper bound : 0x%08x \n", id, objstart+objlen);
fprintf (ReportLog, "%04d:\tObject allocated at program counter : 0x%08x \n", id, allocPC);
fprintf (ReportLog, "%04d:\tObject allocation generation number : %d \n", id, allocID);
fprintf (ReportLog, "%04d:\tObject allocated in source file : %s \n", id, allocSF);
fprintf (ReportLog, "%04d:\tObject allocated at line number : %d \n", id, allocLN);
fprintf(ReportLog, "=======+++++++ end of runtime error report +++++++=======\n");
} else {
fprintf (ReportLog, "%04d:\tNot found within object\n", id);
}
fflush (ReportLog);
if (StopOnError) ABORT_PROGRAM();
return;
}
//
// Function: ReportExactCheck()
//
// Description:
// Identical to ReportBoundsCheck() but does not use the start pointer.
//
// Inputs:
// src - The source pointer for the failed indexing operation (unused).
// dest - The result pointer for the failed indexing operation.
// pc - The program counter of the failed run-time check.
// objstart - The start of the object in which the source pointer was found.
// objlen - The length of the object in which the source pointer was found.
//
// Note:
// An objstart and objlen of 0 indicate that the source pointer was not found
// within a valid object.
//
static void
ReportExactCheck (unsigned src,
unsigned dest,
unsigned pc,
unsigned objstart,
unsigned objlen,
unsigned char * SourceFile,
unsigned lineno) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Bounds violation to memory address 0x%08x (ExactCheck)\n", id, dest);
fprintf (ReportLog, "%04d: at program counter 0x%08x\n", id, pc);
fprintf (ReportLog, "%04d:\tSource filename : %s \n", id, SourceFile);
fprintf (ReportLog, "%04d:\tSource line number : %d \n", id, lineno);
fprintf (ReportLog, "%04d:\tIndex result pointer : 0x%08x \n", id, dest);
if (objstart || objlen) {
fprintf (ReportLog, "%04d:\tObject lower bound : 0x%08x \n", id, objstart);
fprintf (ReportLog, "%04d:\tObject upper bound : 0x%08x \n", id, objstart+objlen);
fprintf(ReportLog, "=======+++++++ end of runtime error report +++++++=======\n");
} else {
fprintf (ReportLog, "%04d:\tNot found within object\n", id);
}
fflush (ReportLog);
if (StopOnError) ABORT_PROGRAM();
return;
}
//
// Function: ReportOOBPointer()
//
// Description:
// Generate a report for the use of an out of bounds (OOB) pointer.
//
// Inputs:
// pc - The program counter of the failed run-time check.
// ptr - The out of bounds pointer.
// oobp - The rewritten pointer that caused the fault.
// ObjStart - The start of the object from which the pointer came.
// Objend - The end of the object from which the pointer came.
// SourceFile - The source file in which the pointer went out of bounds.
// lineno - The line number at which the pointer went out of bounds.
//
static void
ReportOOBPointer (unsigned pc,
void * ptr,
void * oobp,
void * ObjStart,
void * ObjEnd,
char * SourceFile,
unsigned lineno) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Load/Store violation to out of bounds memory address 0x%08x\n", id, (unsigned)ptr);
fprintf (ReportLog, "%04d: at program counter 0x08%p\n", id, pc);
fprintf (ReportLog, "%04d:\tOut of Bounds rewrite pointer : 0x%p \n", id, oobp);
fprintf (ReportLog, "%04d:\tStart of Object : 0x%p \n", id, ObjStart);
fprintf (ReportLog, "%04d:\tEnd of Object : 0x%p \n", id, ObjEnd);
fprintf (ReportLog, "%04d:\tSource filename : %s \n", id, SourceFile);
fprintf (ReportLog, "%04d:\tSource line number : %d \n", id, lineno);
fflush (ReportLog);
if (StopOnError) ABORT_PROGRAM();
return;
}
//
// Function: ReportInvalidFree()
//
// Description:
// Generate a report for an invalid free.
//
// Inputs:
// pc - The program counter at which the invalid free occurred.
// ptr - The invalid pointer passed to poolfree().
// SourceFile - The source file in which the call to free() occurred.
// lineno - The line number at which the call to free() occurred.
//
static void
ReportInvalidFree (unsigned pc,
void * ptr,
char * SourceFile,
unsigned lineno) {
// Print the header and get the ID for this report
unsigned id = printAlertHeader();
fprintf (ReportLog, "%04d: Invalid free of address 0x%08x\n", id,
(unsigned)ptr);
fprintf (ReportLog, "%04d: at program counter 0x%08x\n", id, pc);
fprintf (ReportLog, "%04d:\tSource filename : %s \n", id, SourceFile);
fprintf (ReportLog, "%04d:\tSource line number : %d \n", id, lineno);
fflush (ReportLog);
if (StopOnError) ABORT_PROGRAM();
return;
}
#else
// Production code: all reporters are just simple wrappers for ABORT_PROGRAM()
static inline unsigned printAlertHeader (void) {
ABORT_PROGRAM();
return 0;
}
static inline void ReportDanglingPointer (void * addr,
unsigned pc,
unsigned allocpc,
unsigned allocgen,
unsigned freepc,
unsigned freegen) {
ABORT_PROGRAM();
}
static inline void
ReportLoadStoreCheck (void * ptr,
void * pc,
char * SourceFile,
unsigned lineno) {
ABORT_PROGRAM();
}
static inline void
ReportBoundsCheck (unsigned src,
unsigned dest,
unsigned allocID,
unsigned allocPC,
unsigned pc,
unsigned objstart,
unsigned objlen,
unsigned char * SourceFile,
unsigned lineno,
unsigned char * allocSF,
unsigned allocLN) {
ABORT_PROGRAM();
}
static inline void ReportExactCheck (unsigned src,
unsigned dest,
unsigned pc,
unsigned objstart,
unsigned objlen,
unsigned char * SourceFile,
unsigned lineno) {
ABORT_PROGRAM();
}
static inline void
ReportOOBPointer (unsigned pc, void * ptr, char * SourceFile, unsigned lineno) {
ABORT_PROGRAM();
}
#endif
#endif