1 from pygdbmi
.gdbcontroller
import GdbController
4 launch_args_be
= ['qemu-system-ppc64',
5 '-machine', 'powernv9',
9 launch_args_le
= ['qemu-system-ppc64le',
10 '-machine', 'powernv9',
15 def swap_order(x
, nbytes
):
16 x
= x
.to_bytes(nbytes
, byteorder
='little')
17 x
= int.from_bytes(x
, byteorder
='big', signed
=False)
22 def __init__(self
, kernel
, bigendian
):
24 args
= launch_args_be
+ ['-kernel', kernel
]
26 args
= launch_args_le
+ ['-kernel', kernel
]
27 self
.qemu_popen
= subprocess
.Popen(args
,
28 stdout
=subprocess
.PIPE
,
29 stdin
=subprocess
.PIPE
)
30 self
.gdb
= GdbController(gdb_path
='powerpc64-linux-gnu-gdb')
31 self
.bigendian
= bigendian
36 def __exit__(self
, type, value
, traceback
):
40 return self
.gdb
.write('-target-select remote localhost:1234')
42 def set_endian(self
, bigendian
):
44 cmd
= '-gdb-set endian big'
46 cmd
= '-gdb-set endian little'
47 return self
.gdb
.write(cmd
)
49 def break_address(self
, addr
):
50 cmd
= '-break-insert *0x{:x}'.format(addr
)
51 return self
.gdb
.write(cmd
)
53 def delete_breakpoint(self
, breakpoint
=None):
56 breakstring
= f
' {breakpoint}'
57 return self
.gdb
.write('-break-delete' + breakstring
)
59 def set_byte(self
, addr
, v
):
60 print("qemu set byte", hex(addr
), hex(v
))
61 faddr
= '&{int}0x%x' % addr
62 res
= self
.gdb
.write('-data-write-memory-bytes %s "%02x"' % (faddr
, v
))
63 print("confirm", self
.get_mem(addr
, 1))
65 def get_mem(self
, addr
, nbytes
):
66 res
= self
.gdb
.write("-data-read-memory %d u 1 1 %d" %
68 #print ("get_mem", res)
70 if(x
["type"] == "result"):
71 l
= list(map(int, x
['payload']['memory'][0]['data']))
73 for j
in range(0, len(l
), 8):
75 for i
, v
in enumerate(l
[j
:j
+8]):
81 def get_registers(self
):
82 return self
.gdb
.write('-data-list-register-values x')
84 def _get_register(self
, fmt
):
85 res
= self
.gdb
.write('-data-list-register-values '+fmt
,
86 timeout_sec
=1.0) # increase this timeout if needed
88 if(x
["type"] == "result"):
89 assert 'register-values' in x
['payload']
90 res
= int(x
['payload']['register-values'][0]['value'], 0)
92 # return swap_order(res, 8)
95 # TODO: use -data-list-register-names instead of hardcoding the values
96 def get_pc(self
): return self
._get
_register
('x 64')
97 def get_msr(self
): return self
._get
_register
('x 65')
98 def get_cr(self
): return self
._get
_register
('x 66')
99 def get_lr(self
): return self
._get
_register
('x 67')
100 def get_ctr(self
): return self
._get
_register
('x 68') # probably
101 def get_xer(self
): return self
._get
_register
('x 69')
102 def get_fpscr(self
): return self
._get
_register
('x 70')
103 def get_mq(self
): return self
._get
_register
('x 71')
105 def get_register(self
, num
):
106 return self
._get
_register
('x {}'.format(num
))
109 return self
.gdb
.write('-exec-next-instruction')
111 def gdb_continue(self
):
112 return self
.gdb
.write('-exec-continue')
114 def gdb_eval(self
, expr
):
115 return self
.gdb
.write(f
'-data-evaluate-expression {expr}')
119 self
.qemu_popen
.kill()
120 outs
, errs
= self
.qemu_popen
.communicate()
121 self
.qemu_popen
.stdout
.close()
122 self
.qemu_popen
.stdin
.close()
125 def run_program(program
, initial_mem
=None, extra_break_addr
=None,
127 q
= QemuController(program
.binfile
.name
, bigendian
)
129 q
.set_endian(True) # easier to set variables this way
131 # Run to the start of the program
133 for addr
, (v
, wid
) in initial_mem
.items():
135 q
.set_byte(addr
+i
, (v
>> i
*8) & 0xff)
137 # set breakpoint at start
138 q
.break_address(0x20000000)
140 # set the MSR bit 63, to set bigendian/littleendian mode
142 print("msr", bigendian
, hex(msr
))
145 msr
= msr
& ((1 << 64)-1)
148 q
.gdb_eval('$msr=%d' % msr
)
149 print("msr set to", hex(msr
))
150 # set the CR to 0, matching the simulator
152 # delete the previous breakpoint so loops don't screw things up
153 q
.delete_breakpoint()
155 q
.break_address(0x20000000 + program
.size())
157 q
.break_address(0x700)
158 # or to alternative (absolute) address)
160 q
.break_address(extra_break_addr
)
162 q
.set_endian(bigendian
)
167 if __name__
== '__main__':
168 q
= QemuController("simulator/qemu_test/kernel.bin", bigendian
=True)
170 q
.break_address(0x20000000)
172 print(q
.get_register(1))
174 print(q
.get_register(1))