Powerpoint, 274 KB

Download Report

Transcript Powerpoint, 274 KB

Title Page
Debugging
via
Run-Time
Type Checking
Alexey Loginov, Suan Yong,
Susan Horwitz, Thomas Reps
University of Wisconsin - Madison
Overview 1 - C
Run-Time Type Checking
• C: weak static typing permits bugs
– unions (write one field, read another)
– casting (pointer with non-pointer
value, pointer points to object with
wrong type)
– pointer arithmetic (array out-ofbounds)
Overview 2 - goal
Run-Time Type Checking
• Goal: help programmers find these
bugs via run-time type checking
– flag errors
– track down their cause
(fault localization)
Overview - Approach
Approach: Track Types Dynamically
• Tag each memory location with its
dynamic type
– in ‘mirror’ of memory
• On use, verify that current dynamic
type is appropriate
• On assignment, verify that assigned
type is consistent with static type
Tracking run-time types: Use
Tracking Run-Time Types
• Use of a location: dynamic type verified
– wrong type: generate error message
• Example uses:
– int *p;
– *p + 5; => error if p not a pointer
=> error if *p not an integer
Tracking run-time types: Assignment
Tracking Run-Time Types
• Assignment: dynamic type propagated.
– different type: generate warning message
• helpful in tracking down root cause
• Example assignment:
– int x, *q;
– x = *q; => tag of x set to tag of *q
=> warn if *q not an integer
Purify, Safe C ...
Where we fit in
• Purify [Hastings+]
– array out-of-bounds, bad pointer dereferences,
use of uninitialized data
– memory leaks
• Safe C [Austin+]
– stale pointer uses, unions
• Our Approach
– run-time type violations
– some ability to track down logical errors
(not just flag symptoms)
Talk Overview
•
•
•
•
•
•
Introduction
Examples
Implementation
Results from Initial Tests
Future Work
Conclusion
Ex1: Unions 1
Example 1: Unions
union U { int u1; int *u2; } u;
(memory) (tags)
int *p;
u.u1 = 8;
p = u.u2;
*p = 0;
(0x08)
(u)
(p)
:
FE232F10
:
unalloc
:
:
:
:
00000000
00000008
00000000
int
uninit
uninit
:
:
:
:
Ex1: Unions 2
Example 1: Unions
union U { int u1; int *u2; } u;
(memory) (tags)
int *p;
u.u1 = 8;
p = u.u2;
*p = 0;
(0x08)
(u)
(p)
:
FE232F10
unalloc
:
:
:
:
00000008
int
uninit
int
uninit
00000000
00000008
:
:
:
:
warning :
Ex1: Unions 3
Example 1: Unions
union U { int u1; int *u2; } u;
(memory) (tags)
int *p;
u.u1 = 8;
p = u.u2;
*p = 0;
(0x08)
(u)
(p)
:
FE232F10
:
unalloc
:
:
:
:
00000008
00000008
int
uninit
int
uninit
:
:
:
error! :
Ex1: Unions 4
Example 1: Unions
union U { int u1; int *u2; } u;
(memory) (tags)
int *p;
u.u1 = 8;
p = u.u2;
*p = 0;
(0x08)
:
FE232F10
:
:
(u)
(p)
:
unalloc
:
error! :
00000008
int
uninit
int
uninit
:
:
:
:
00000008
Ex 2: Array (heap) 1
Example 2: Bad Pointer Access
int *intArray = (int *)
malloc(15 * sizeof(int));
int **ptrArray = (int **)
malloc(15 * sizeof(int *));
intArray
ptrArray
memory
Ex 2: Array (heap) 2
Example 2: Bad Pointer Access
int *i, sumEven = 0;
for(i = intArray; ...; i += 2)
sumEven += *i;
PURIFY
DTC
i
intArray
ptrArray
i
intArray
memory
ptrArray
padding
Ex 3: Array (stack) 1
Example 3: Bad Pointer Access (stack)
int intArray[10];
int *ptrArray[10];
for(i = intArray; ...; i += 2)
...
PURIFY
DTC
i
intArray
i
intArray
ptrArray
stack
ptrArray
stack
Ex 4: Sim Inherit 1
Example 4: Simulated Inheritance
struct Sup {
int a1;
int a2;
} sup;
sup
a1 int
a2 int
struct Sub {
int b1;
int b2;
char b3;
} sub;
sub
b1 int
b2 int
b3 char
Ex 4: Sim Inherit 2
Example 4: Simulated Inheritance
s
void f(struct Sup *s)
{
printInt(s->a1);
printInt(s->a2);
}
sup
sub
s
b1 int
a1 int
b2 int
a2 int
b3 char
f(&sup);
f(&sub);
Ex 4: Sim Inherit 3
Example 4: Simulated Inheritance
struct Sup {
int a1;
int a2;
} sup;
a1 int
a2 int
struct Sub {
int b1;
float f1;
int b2;
char b3;
} sub;
b1 int
f1 float
b2 int
b3 char
Ex 4: Sim Inherit 4
Example 4: Simulated Inheritance
s
void f(struct Sup *s)
{
printInt(s->a1);
printInt(s->a2);
}
s
b1 int
a1 int
error!
f1 float
a2 int
b2 int
f(&sup);
b3 char
f(&sub);
Talk Overview
•
•
•
•
•
•
Introduction
Examples
Implementation
Results from Initial Tests
Future Work
Conclusion
Overview of Tool
Overview of Tool
• Instrumentation
– preprocessed source file  instrumented C file
• Compilation
• Execution
– tracks types in “mirror” of memory
– writes error/warning messages, sends signal
• signal can be intercepted by GDB for further
debugging
Mirror and Tags
MIRROR
USER
MEM
Impl: Mirror and Tags
continuation bits
(currently unused bits)
0 0 1 0 1 0 1 0 1 0 0 0 1 0 0 0 0
type bits:
{unalloc, uninit,
integral, real, pointer}
size bits (log2)
Impl: Tags (examples)
Mirror and Tags
char
0 integral 0
short
0 integral 1 size=2 0
float
0
real
1 size=4 1 0 0 0 1 0 0 0 0
char [3] (third element uninitialized)
0 integral 0 integral 0 uninit 0 unalloc 0
Source Level X-lation: C to C
Source Level Translation
• C source  C source
– Using Lucent’s Ckit front end
– syntax-directed transformations
– instruments statements and expressions to set,
verify, and propagate tags
– preserves expression values, types, side-effects
• makes extensive use of “comma” operator
• introduces many temporary variables
– separate (partial) instrumentation
Instr Example: x = *p (1)
*(tmp2 = &x)
int x;
int *p;
x = *p
* (verifyTag(&p, ptr_type), p)
*(tmp3 = (verifyTag(&p, ptr_type), p),
verifyPtr(tmp3, sizeof(int)),
tmp3)
Instr Example: x = *p (2)
*(tmp2 = &x)
x = *p
*(tmp2 = &x) =
*(tmp3 = (verifyTag(&p, ptr_type), p),
verifyPtr(tmp3, sizeof(int)),
tmp3)
*(tmp3 = (verifyTag(&p, ptr_type), p),
verifyPtr(tmp3, sizeof(int)),
tmp3)
Instr Example: x = *p (3)
x = *p
(tmp1 =
*(tmp2 = &x) =
*(tmp3 = (verifyTag(&p, ptr_type), p),
verifyPtr(tmp3, sizeof(int)),
tmp3)
copyTag(tmp2, tmp3, int_type),
tmp1)
Talk Overview
•
•
•
•
•
•
Introduction
Examples
Implementation
Results from Initial Tests
Future Work
Conclusion
Effectiveness of Tool
Effectiveness of Tool
• Bugs identified in:
– Solaris utilities (nroff, plot, ul, ...)
– Olden benchmarks (health, voronoi)
• Output usually succinct
– Error messages pinpoint bug symptoms
– Warning messages help track down
logical error
Sample bug descriptions
Sample Bugs and Errors Reported
• stray pointer corrupts return address on
stack
– error: pointer dereference incorrectly typed
• stray pointer corrupts _iob array (stdin,
stdout, stderr)
– error: referencing unallocated memory
• treats malloc’ed memory as zero-
initialized
– error: use of uninitialized memory
Alterations in Behavior
Alterations in Behavior
• Hard to preserve behavior of nonportable programs
• Purify affects go, nroff, others
– modified memory layout
• Our tool affects ul, units, col
– local variable addition
–register variable demotion
• Behavior sometimes altered but cause
of error is the same
Performance – by slowdown (table)
Performance
Mean =
43.8
Median =
23.9
Solaris utils
Olden
SPECint95
lines of
program C code
ul
468
plot
326
tsp
567
units
457
bisort
570
col
502
perimeter
389
mst
493
compress 1,491
go
26,917
li
6,272
nroff
11,018
bh
1,049
gcc
151,531
vortex
52,624
run-time (sec)
uninstr- instruumente mented slowdown
0.33
1.87
5.6
1.02
5.90
5.8
12.78
83.64
6.5
0.39
3.19
8.2
7.60
70.86
9.3
1.47
29.39
20.0
2.22
49.13
22.1
3.25
83.10
25.6
19.87 695.83
35.0
12.04 654.86
54.4
5.47 320.99
58.7
0.82
53.01
64.6
8.97 910.02
101.4
11.08 1288.64
116.3
12.37 1596.02
129.1
Areas for Improvement: overhead, spurious errors
Areas for Improvement
• Overhead
– current slowdown: 6x - 130x
• can improve instrumentation and macro
definitions
• no attempt yet made to identify and remove
unnecessary checks
• Spurious errors and warnings
– abundant in a few benchmarks
• due to memset, calloc, etc.
• incomplete extern types (__ctype[])
Optimization: no intervening write
Planned Optimizations
• Remove redundant checks
– when there are no intervening writes
(of a different type) to a given location
int x, y, z;
if (x < 0){
x += 10;
y = (x > 5) ? x : 0;
}
Optimization: static analysis
Planned Optimizations
• Remove redundant instrumentation
– use static analysis
• to find variables that need no
instrumentation
• i.e. variables that can be statically
determined to be type-safe
– has potential to drastically reduce
overhead
Conclusion
Conclusion
• Run-time type checking works
– identified pointer and array access errors
– warnings help find root cause of error
• Potential for finding subtler type-bugs
– no “real” examples found in preliminary
testing
• Slowdown is relatively high
– potential for significant speedup untapped