2014-07-23 14:44:44 +00:00
|
|
|
"""
|
|
|
|
Tests that test voltron in the lldb cli driver
|
|
|
|
|
|
|
|
Tests:
|
2014-07-24 14:34:42 +00:00
|
|
|
Client -> Server -> LLDBAdaptor
|
2014-07-23 14:44:44 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
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)
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def teardown():
|
2014-07-24 14:34:42 +00:00
|
|
|
read_data()
|
|
|
|
p.terminate(True)
|
2014-09-28 04:06:29 +00:00
|
|
|
time.sleep(2)
|
2014-07-23 14:44:44 +00:00
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def start_debugger(do_break=True):
|
|
|
|
global p, client
|
|
|
|
p = pexpect.spawn('lldb')
|
2014-07-27 18:41:06 +00:00
|
|
|
p.sendline("settings set target.x86-disassembly-flavor intel")
|
2014-07-23 14:44:44 +00:00
|
|
|
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()
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def stop_debugger():
|
2014-07-24 14:34:42 +00:00
|
|
|
p.terminate(True)
|
2014-07-23 14:44:44 +00:00
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def read_data():
|
|
|
|
try:
|
|
|
|
while True:
|
|
|
|
p.read_nonblocking(size=64, timeout=1)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def restart_debugger(do_break=True):
|
|
|
|
stop_debugger()
|
|
|
|
start_debugger(do_break)
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def test_bad_request():
|
|
|
|
req = client.create_request('version')
|
|
|
|
req.request = 'xxx'
|
|
|
|
res = client.send_request(req)
|
|
|
|
assert res.is_error
|
2014-07-25 09:50:37 +00:00
|
|
|
assert res.code == 0x1002
|
2014-07-23 14:44:44 +00:00
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def test_version():
|
|
|
|
req = client.create_request('version')
|
|
|
|
res = client.send_request(req)
|
2015-12-26 05:11:23 +00:00
|
|
|
assert res.api_version == 1.1
|
2014-07-23 14:44:44 +00:00
|
|
|
assert 'lldb' in res.host_version
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-17 13:15:46 +00:00
|
|
|
def test_registers():
|
2014-07-23 14:44:44 +00:00
|
|
|
global registers
|
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
|
|
|
read_data()
|
2014-10-17 13:15:46 +00:00
|
|
|
res = client.perform_request('registers')
|
2014-07-23 14:44:44 +00:00
|
|
|
registers = res.registers
|
|
|
|
assert res.status == 'success'
|
|
|
|
assert len(registers) > 0
|
|
|
|
assert registers['rip'] != 0
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-17 13:15:46 +00:00
|
|
|
def test_memory():
|
2014-07-23 14:44:44 +00:00
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
2014-10-17 13:15:46 +00:00
|
|
|
res = client.perform_request('memory', address=registers['rip'], length=0x40)
|
2014-07-23 14:44:44 +00:00
|
|
|
assert res.status == 'success'
|
|
|
|
assert len(res.memory) > 0
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def test_state_stopped():
|
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
|
|
|
res = client.perform_request('state')
|
|
|
|
assert res.is_success
|
|
|
|
assert res.state == "stopped"
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-17 13:15:46 +00:00
|
|
|
def test_targets():
|
2014-07-23 14:44:44 +00:00
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
2014-10-17 13:15:46 +00:00
|
|
|
res = client.perform_request('targets')
|
2014-07-23 14:44:44 +00:00
|
|
|
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')
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-17 13:15:46 +00:00
|
|
|
def test_stack():
|
2014-07-23 14:44:44 +00:00
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
2014-10-17 13:15:46 +00:00
|
|
|
res = client.perform_request('stack', length=0x40)
|
2014-07-23 14:44:44 +00:00
|
|
|
assert res.status == 'success'
|
|
|
|
assert len(res.memory) > 0
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-17 13:15:46 +00:00
|
|
|
def test_command():
|
2014-07-23 14:44:44 +00:00
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
2014-10-17 13:15:46 +00:00
|
|
|
res = client.perform_request('command', command="reg read")
|
2014-07-23 14:44:44 +00:00
|
|
|
assert res.status == 'success'
|
|
|
|
assert len(res.output) > 0
|
|
|
|
assert 'rax' in res.output
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-07-23 14:44:44 +00:00
|
|
|
def test_disassemble():
|
|
|
|
restart_debugger()
|
|
|
|
time.sleep(1)
|
|
|
|
res = client.perform_request('disassemble', count=0x20)
|
|
|
|
assert res.status == 'success'
|
|
|
|
assert len(res.disassembly) > 0
|
2014-07-27 18:41:06 +00:00
|
|
|
assert 'push' in res.disassembly
|
2014-07-23 14:44:44 +00:00
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2014-10-27 17:14:54 +00:00
|
|
|
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'
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2015-02-01 15:15:12 +00:00
|
|
|
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"
|
2015-12-06 05:19:35 +00:00
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2015-12-06 05:19:35 +00:00
|
|
|
def test_multi():
|
|
|
|
global r1, r2
|
|
|
|
restart_debugger(True)
|
|
|
|
time.sleep(1)
|
|
|
|
r1, r2 = None, None
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2015-12-06 05:19:35 +00:00
|
|
|
def send_req():
|
|
|
|
global r1, r2
|
|
|
|
r1, r2 = client.send_requests(api_request('targets', block=True), api_request('registers', block=True))
|
|
|
|
print "sent requests"
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2015-12-06 05:19:35 +00:00
|
|
|
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
|
|
|
|
|
2015-12-26 10:42:01 +00:00
|
|
|
|
2015-12-06 05:19:35 +00:00
|
|
|
def test_capabilities():
|
|
|
|
restart_debugger(True)
|
|
|
|
res = client.perform_request('version')
|
|
|
|
assert res.capabilities == ['async']
|