A Portable Virtual Machine for Program Debugging and Directing Camil Demetrescu University of Rome...

Preview:

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

Recommended