2 # Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
3 # Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
7 takes powerpc assembly instructions and turns them into LE/BE binary
8 data. calls powerpc64-linux-gnu-as, ld and objcopy to do so.
16 from io
import BytesIO
19 filedir
= os
.path
.dirname(os
.path
.realpath(__file__
))
20 memmap
= os
.path
.join(filedir
, "memmap")
24 def __init__(self
, instructions
, bigendian
):
25 self
.bigendian
= bigendian
27 self
.endian_fmt
= "elf64-big"
32 self
.endian_fmt
= "elf64-little"
35 if isinstance(instructions
, bytes
): # actual bytes
36 self
.binfile
= BytesIO(instructions
)
37 self
.binfile
.name
= "assembly"
38 self
.assembly
= '' # noo disassemble number fiiive
39 elif isinstance(instructions
, str): # filename
40 # read instructions into a BytesIO to avoid "too many open files"
41 with
open(instructions
, "rb") as f
:
43 self
.binfile
= BytesIO(b
)
44 self
.assembly
= '' # noo disassemble number fiiive
45 print("program", self
.binfile
)
47 if isinstance(instructions
, list):
48 instructions
= '\n'.join(instructions
)
49 self
.assembly
= instructions
+ '\n' # plus final newline
51 self
._instructions
= list(self
._get
_instructions
())
56 def __exit__(self
, type, value
, traceback
):
59 def _get_binary(self
, elffile
):
60 self
.binfile
= tempfile
.NamedTemporaryFile(suffix
=".bin")
61 args
= ["powerpc64-linux-gnu-objcopy",
63 "-I", self
.endian_fmt
,
66 subprocess
.check_output(args
)
68 def _link(self
, ofile
):
69 with tempfile
.NamedTemporaryFile(suffix
=".elf") as elffile
:
70 args
= ["powerpc64-linux-gnu-ld",
75 subprocess
.check_output(args
)
76 self
._get
_binary
(elffile
)
79 with tempfile
.NamedTemporaryFile(suffix
=".o") as outfile
:
80 args
= ["powerpc64-linux-gnu-as",
85 p
= subprocess
.Popen(args
, stdin
=subprocess
.PIPE
)
86 p
.communicate(self
.assembly
.encode('utf-8'))
88 print("Error in program:")
93 def _get_instructions(self
):
95 data
= self
.binfile
.read(4)
98 yield struct
.unpack('<I', data
)[0] # unsigned int
100 def generate_instructions(self
):
101 yield from self
._instructions
107 curpos
= self
.binfile
.tell()
108 self
.binfile
.seek(0, 2) # Seek to end of file
109 size
= self
.binfile
.tell()
110 self
.binfile
.seek(curpos
, 0)
113 def write_bin(self
, fname
):
115 data
= self
.binfile
.read()
116 with
open(fname
, "wb") as f
:
122 if __name__
== '__main__':
123 lst
= ['addi 5, 0, 4660',
128 with
Program(lst
, False) as p
:
129 p
.write_bin("/tmp/test.bin")