Upload
clifford-may
View
213
Download
1
Embed Size (px)
Citation preview
A Portable Virtual Machine A Portable Virtual Machine for Program Debugging for Program Debugging
and Directingand Directing
Camil DemetrescuUniversity of Rome “La Sapienza”
Irene FinocchiUniversity of Rome “Tor Vergata”
MotivationMotivation
Devising powerful methodologies and
tools for assuring software reliability
Directorsreactive systems that monitor the run-time environment reacting to events generated
by the processes
What kind of events? Variable referencing, program interruption, memory allocation/ deallocation, function calls, memory accesses...
Difficulties of implementationDifficulties of implementation
• Instrumenting source code
programming efforts, flexibility
• Low-level OS primitives
• Instrumenting assembly code
portability
• Interpreted execution (high level languages)
efficiency
Directing through virtual Directing through virtual machinesmachines
Interpreting intermediate level languages (e.g., Java bytecodes)
• Capabilities of introspection
• Targeting multiple languages
• Targeting “difficult” languages (C, C++
need instructions to manipulate addresses)
• Running in reversible mode
(very useful for error localization)
Our contributionOur contribution
The Leonardo Virtual MachineThe Leonardo Virtual Machine
Provides advanced facilities for implementing
directors with low effort:
Fine grained monitoring of memory accesses
Reversible computing capabilities
Continuous monitoring (not just on demand)
by means of a flexible event handling
mechanism
Architectural layersArchitectural layers
Hardware / operating system
Leonardo Library (LL-Win32, LL-Qt)
Leonardo Virtual Machine Native applications
(editors, compilers)
Interpreted applications (directors, visualizers,
analysis tools)
Virtual CPU Kernel
Virtual CPUVirtual CPU
• Stack-based Only 5 registers About 100 elementary instructions About 180 lines of C code
• Handlers installed by external clients are
executed at critical instructions (e.g.,
ld / st / jsr / rts)
2 bits per word
Memory protectionMemory protection
• Typically, processes prevented from getting outside their logical address space
• … but how to avoid damages inside it?
Memory mask for detecting illegal accesses to each memory word
Stack protectionStack protection
• 101 out of 107 VCPU instructions access the top of the stack
• Combine compile-time & run-time checking
• Static analysis to compute max stack usage in a subroutine
• Run-time checks necessary only on function calls (jsr)
• Run-time checks for overflow / underflow would be very inefficient
ReversibilityReversibility
• State = registers + memory image• Incremental log of state changes
• Only special points are checkpointable
Log record = addresses + values of memory words changed in the transaction
Forward execution: at each checkpoint a new log record is pushed onto a history stack
Backward execution: the log record on the top of the history stack is used to restore the state
OptimizationsOptimizations
Stack optimization: data over the top of the execution stack are not part of the state
Buffering techniques to reduce I/Os
Multiple changes of the same word are not saved
saved in the log record
transaction
Stack-preserving transactionsStack-preserving transactions
• A stack-preserving transaction pushes temporary
data on the top of the stack and pop them
leaving the final height unchanged
• LVM executables satisfy this property:
transactions between consecutive
checkpoints within the same subroutine are stack-preserving
• We support reversibility at different granularities
Event handling: an exampleEvent handling: an example
void _MemAccessH(ui4 inBase, ui4 inSize){ ui4 theB1 = inBase/LINE; ui4 theB2 = (inBase+inSize-1)/LINE; if (sB != theB1) { sB = theB1; ++sMiss; } if (sB != theB2) { sB = theB2; ++sMiss; } ++sMems;}
#include <lvm.h>
#define LINE 4096
static ui4 sMems; /* # of mem accesses */static ui4 sMiss; /* # of cache misses */static ui4 sB; /* current line address */
Event handling: an exampleEvent handling: an example
/* install mem access handlers */ KNewAsyncEvtH(thePID, KMEM_READ_EVENT, 0, (KEvtHT)_MemAccessH); KNewAsyncEvtH(thePID, KMEM_WRITE_EVENT, 0, (KEvtHT)_MemAccessH);
void main(){
}
/* create new process */ ui4 thePID = KNewProc(“bubblesort.leo”, 0, 0);
/* output results */ KPuts("# Mem accesses = "); KPrintlnUI4(sMems); KPuts("# Cache misses = "); KPrintlnUI4(sMiss);
/* start process, wait for termination */ KStartProc(thePID); KWaitSyncEvtH(thePID, KHALT_EVENT,0, NULL);
Experiments: running timesExperiments: running times
0
20
40
60
80
100
120
bubble hanoi matmul perm qsort queen sieveStanford programs
no history logging
granularity = 4
granularity = 1
Experiments: history logExperiments: history log
0
20
40
60
80
100
120
bubble hanoi matmul perm qsort queen sieveStanford programs
granularity = 4
granularity = 1
Future workFuture work
http://www.leonardo-vm.org/
Further information and source code at:
Feedback is welcome!
Trading time for space: a (partial) re-execution
based approach to reversibility
Implementation of directors: memory monitor tools for software visualization
Just in time compilation