voltron/tests/lldb_cli_tests.py

224 lines
5.0 KiB
Python

"""
Tests that test voltron in the lldb cli driver
Tests:
Client -> Server -> LLDBAdaptor
Inside an LLDB CLI driver instance
"""
import tempfile
import sys
import json
import time
import logging
import pexpect
import os
from mock import Mock
from nose.tools import *
import voltron
from voltron.core import *
from voltron.api import *
from voltron.plugin import PluginManager, DebuggerAdaptorPlugin
from common import *
log = logging.getLogger('tests')
p = None
client = None
def setup():
global p, client, pm
log.info("setting up LLDB CLI tests")
voltron.setup_env()
# compile test inferior
pexpect.run("cc -o tests/inferior tests/inferior.c")
# start debugger
start_debugger()
time.sleep(1)
def teardown():
read_data()
p.terminate(True)
time.sleep(2)
def start_debugger(do_break=True):
global p, client
p = pexpect.spawn('lldb')
p.sendline("settings set target.x86-disassembly-flavor intel")
p.sendline("command script import dbgentry.py")
p.sendline("file tests/inferior")
p.sendline("voltron init")
p.sendline("process kill")
p.sendline("break delete 1")
if do_break:
p.sendline("b main")
p.sendline("run loop")
read_data()
client = Client()
def stop_debugger():
p.terminate(True)
def read_data():
try:
while True:
p.read_nonblocking(size=64, timeout=1)
except:
pass
def restart_debugger(do_break=True):
stop_debugger()
start_debugger(do_break)
def test_bad_request():
req = client.create_request('version')
req.request = 'xxx'
res = client.send_request(req)
assert res.is_error
assert res.code == 0x1002
def test_version():
req = client.create_request('version')
res = client.send_request(req)
assert res.api_version == 1.1
assert 'lldb' in res.host_version
def test_registers():
global registers
restart_debugger()
time.sleep(1)
read_data()
res = client.perform_request('registers')
registers = res.registers
assert res.status == 'success'
assert len(registers) > 0
assert registers['rip'] != 0
def test_memory():
restart_debugger()
time.sleep(1)
res = client.perform_request('memory', address=registers['rip'], length=0x40)
assert res.status == 'success'
assert len(res.memory) > 0
def test_state_stopped():
restart_debugger()
time.sleep(1)
res = client.perform_request('state')
assert res.is_success
assert res.state == "stopped"
def test_targets():
restart_debugger()
time.sleep(1)
res = client.perform_request('targets')
assert res.is_success
assert res.targets[0]['state'] == "stopped"
assert res.targets[0]['arch'] == "x86_64"
assert res.targets[0]['id'] == 0
assert res.targets[0]['file'].endswith('tests/inferior')
def test_stack():
restart_debugger()
time.sleep(1)
res = client.perform_request('stack', length=0x40)
assert res.status == 'success'
assert len(res.memory) > 0
def test_command():
restart_debugger()
time.sleep(1)
res = client.perform_request('command', command="reg read")
assert res.status == 'success'
assert len(res.output) > 0
assert 'rax' in res.output
def test_disassemble():
restart_debugger()
time.sleep(1)
res = client.perform_request('disassemble', count=0x20)
assert res.status == 'success'
assert len(res.disassembly) > 0
assert 'push' in res.disassembly
def test_dereference():
restart_debugger()
time.sleep(1)
res = client.perform_request('registers')
res = client.perform_request('dereference', pointer=res.registers['rsp'])
assert res.status == 'success'
assert res.output[0][0] == 'pointer'
assert res.output[-1][1] == 'start + 0x1'
def test_breakpoints():
restart_debugger()
time.sleep(1)
res = client.perform_request('breakpoints')
assert res.status == 'success'
assert len(res.breakpoints) == 1
assert res.breakpoints[0]['one_shot'] == False
assert res.breakpoints[0]['enabled']
assert res.breakpoints[0]['id'] == 1
assert res.breakpoints[0]['hit_count'] > 0
assert res.breakpoints[0]['locations'][0]['name'] == "inferior`main"
def test_multi():
global r1, r2
restart_debugger(True)
time.sleep(1)
r1, r2 = None, None
def send_req():
global r1, r2
r1, r2 = client.send_requests(api_request('targets', block=True), api_request('registers', block=True))
print "sent requests"
t = threading.Thread(target=send_req)
t.start()
time.sleep(5)
p.sendline("stepi")
time.sleep(5)
t.join()
print r1
print r2
assert r1.is_success
assert r1.targets[0]['state'] == "stopped"
assert r1.targets[0]['arch'] == "x86_64"
assert r1.targets[0]['id'] == 0
assert r1.targets[0]['file'].endswith('tests/inferior')
assert r2.status == 'success'
assert len(r2.registers) > 0
assert r2.registers['rip'] != 0
def test_capabilities():
restart_debugger(True)
res = client.perform_request('version')
assert res.capabilities == ['async']