def test_linking(self): """ Test pull in of undefined symbols from libraries. """ arch = get_arch('msp430') obj1 = ObjectFile(arch) obj1.create_section('foo') obj1.add_symbol(0, 'printf', 'global', None, None, 'func', 0) # undefined obj2 = ObjectFile(arch) obj3 = ObjectFile(arch) obj3.create_section('foo') obj3.add_symbol(0, 'syscall', 'global', 0, 'foo', 'func', 0) # defined lib1 = archive([obj2, obj3]) obj4 = ObjectFile(arch) obj4.create_section('foo') obj4.add_symbol(0, 'putc', 'global', 0, 'foo', 'func', 0) # defined obj4.add_symbol(1, 'syscall', 'global', None, None, 'func', 0) # undefined obj5 = ObjectFile(arch) obj5.create_section('foo') obj5.add_symbol(0, 'printf', 'global', 0, 'foo', 'func', 0) # defined obj5.add_symbol(1, 'putc', 'global', None, None, 'func', 0) # undefined lib2 = archive([obj4, obj5]) obj = link([obj1], libraries=[lib1, lib2])
def run_it(): arch = get_arch("example") bsp = io.StringIO( """ module bsp; public function void sleep(int ms); public function void putc(byte c); public function bool get_key(int* key); """ ) ircode = c3_to_ir( ["../src/snake/game.c3", "../src/snake/main.c3", "../../librt/io.c3"], [bsp], arch, ) with open("python_snake2.py", "w") as f: print("import time", file=f) print("import sys", file=f) print("import threading", file=f) ir_to_python([ircode], f) print("", file=f) print("def bsp_putc(c):", file=f) print(' print(chr(c), end="")', file=f) print("def bsp_get_key(x):", file=f) print(" return 0", file=f) print("def bsp_sleep(x):", file=f) print(" time.sleep(x*0.001)", file=f) print("main_main()", file=f) print("Now run python_snake2.py !")
def compile_nos_for_riscv(): """ Compile nOS for riscv architecture. """ logging.basicConfig(level=logging.INFO) murax_folder = os.path.join(this_dir, "..", "examples", "riscvmurax") arch = api.get_arch("riscv") # Gather sources: path = os.path.join(murax_folder, "csrc", "nos") folders, srcs = get_sources(path, "*.c") folders += [os.path.join(murax_folder, "csrc")] print(srcs) coptions = COptions() for folder in folders: coptions.add_include_path(folder) # Build code: o1 = api.asm(os.path.join(murax_folder, "start.s"), arch) o2 = api.asm(os.path.join(murax_folder, "nOSPortasm.s"), arch) objs = [o1, o2] for src in srcs: with open(src) as f: objs.append(api.cc(f, "riscv", coptions=coptions, debug=True)) # Link code: api.link( objs, os.path.join(murax_folder, "firmware.mmap"), use_runtime=True, debug=True, )
def test_bug2(self): """ Check that if blocks are in function in strange order, the dag builder works """ module = ir.Module('dut') function = ir.Procedure('tst', ir.Binding.GLOBAL) module.add_function(function) block1 = ir.Block('b1') block2 = ir.Block('b2') function.add_block(block1) function.add_block(block2) function.entry = block2 con = ir.Const(2, 'con', ir.i32) block2.add_instruction(con) block2.add_instruction(ir.Jump(block1)) block1.add_instruction(ir.Cast(con, 'con_cast', ir.i8)) block1.add_instruction(ir.Exit()) # Target generation target = get_arch('arm') frame = target.new_frame('a', function) function_info = FunctionInfo(frame) debug_db = DebugDb() prepare_function_info(target, function_info, function) dag_builder = SelectionGraphBuilder(target) sgraph = dag_builder.build(function, function_info, debug_db) dag_splitter = DagSplitter(target)
def build_sample_to_ir(src, lang, bsp_c3, march, reporter): """ Compile the given sample into ir-modules """ if lang == "c3": ir_modules = [ api.c3_to_ir( [bsp_c3, relpath("..", "librt", "io.c3"), io.StringIO(src)], [], march, reporter=reporter, ) ] elif lang == "bf": ir_modules = [api.bf_to_ir(src, march)] elif lang == "c": coptions = COptions() include_path1 = relpath("..", "librt", "libc") lib = relpath("..", "librt", "libc", "lib.c") coptions.add_include_path(include_path1) with open(lib, "r") as f: mod1 = api.c_to_ir(f, march, coptions=coptions, reporter=reporter) mod2 = api.c_to_ir( io.StringIO(src), march, coptions=coptions, reporter=reporter ) ir_modules = [mod1, mod2] elif lang == "pas": pascal_ir_modules = api.pascal_to_ir( [io.StringIO(src)], api.get_arch(march) ) ir_modules = pascal_ir_modules else: # pragma: no cover raise NotImplementedError("Language {} not implemented".format(lang)) return ir_modules
def test_save_load(self): arch = get_arch('arm') ef1 = ElfFile() f = io.BytesIO() ef1.save(f, ObjectFile(arch)) f2 = io.BytesIO(f.getvalue()) ElfFile.load(f2)
def test_normal_use(self): arch = get_arch('example') obj = ObjectFile(arch) o = BinaryOutputStream(obj) o.select_section('.text') o.emit(Label('a')) self.assertSequenceEqual(bytes(), obj.get_section('.text').data)
def test_save(self): """ Test the generation of a windows exe file """ arch = get_arch('x86_64') obj = ObjectFile(arch) obj.get_section('code', create=True) obj.get_section('data', create=True) f = io.BytesIO() # TODO: ExeWriter().write(obj, f)
def test_undefined_reference(self): arch = get_arch('arm') object1 = ObjectFile(arch) object1.get_section('.text', create=True) object1.add_symbol(0, 'undef', 'global', None, None, 'object', 0) object1.gen_relocation('rel8', 0, '.text', 0) object2 = ObjectFile(arch) with self.assertRaises(CompilerError): link([object1, object2])
def test_duplicate_symbol(self): arch = get_arch('arm') object1 = ObjectFile(arch) object1.get_section('.text', create=True) object1.add_symbol(0, 'a', 'global', 0, '.text', 'object', 0) object2 = ObjectFile(arch) object2.get_section('.text', create=True) object2.add_symbol(0, 'a', 'global', 0, '.text', 'object', 0) with self.assertRaises(CompilerError): link([object1, object2])
def test_overlapping_sections(self): """ Check that overlapping sections are detected """ obj = ObjectFile(get_arch('msp430')) obj.get_section('s1', create=True).add_data(bytes(range(100))) obj.get_section('s2', create=True).add_data(bytes(range(100))) obj.add_image(Image('x', 0)) obj.get_image('x').add_section(obj.get_section('s1')) obj.get_image('x').add_section(obj.get_section('s2')) with self.assertRaisesRegex(ValueError, 'overlap'): obj.get_image('x').data
def test_parse_failure(self): """ Check the error reporting of the assembler """ arch = get_arch('example') obj = ObjectFile(arch) ostream = BinaryOutputStream(obj) ostream.select_section('code') diag = DiagnosticsManager() assembler = BaseAssembler() with self.assertRaises(CompilerError): assembler.assemble('abc def', ostream, diag)
def test_rel8_relocation(self): arch = get_arch('arm') object1 = ObjectFile(arch) object1.get_section('.text', create=True).add_data(bytes([0] * 100)) object1.add_symbol(10, 'a', 'global', None, None, 'object', 0) object1.gen_relocation('rel8', 10, '.text', 0) object2 = ObjectFile(arch) object2.get_section('.text', create=True).add_data(bytes([0] * 100)) object2.add_symbol(0, 'a', 'global', 24, '.text', 'object', 0) link([object1, object2])
def setUp(self): self.source = io.StringIO() self.as_args = [] arch = get_arch(self.march) self.obj = ObjectFile(arch) self.ostream = BinaryOutputStream(self.obj) self.ostream.select_section('code') self.diag = DiagnosticsManager() # Prep assembler! self.assembler = arch.assembler self.assembler.prepare()
def test_is_used(self): arch = get_arch('x86_64') frame = Frame('tst') vreg = XmmRegisterSingle('vreg99') vreg.set_color(6) vreg2 = XmmRegisterDouble('vreg100') vreg2.set_color(6) frame.used_regs.add(vreg.get_real()) assert vreg is not xmm6 assert vreg.get_real() is not xmm6 assert vreg2 is not xmm6 assert vreg2.get_real() is xmm6 assert frame.is_used(vreg, arch.info.alias) assert frame.is_used(xmm6, arch.info.alias)
def test_readregs(self, mock_stdout): """ Test read registers """ arch = get_arch('arm') r1, r2 = arch.gdb_registers[1:3] reg_values = { r1: 1, r2: 1000, } self.debugger_mock.get_registers = MagicMock(return_value=[r1, r2]) self.debugger_mock.get_register_values = MagicMock( return_value=reg_values) self.cmd('readregs') lines = [' R1 : 0x00000001', ' R2 : 0x000003E8', ''] self.assertEqual('\n'.join(lines), mock_stdout.getvalue())
def test_offset_adjustment(self): """ Test if offsets are correctly modified when linking debug info """ arch = get_arch('arm') obj1 = ObjectFile(arch) obj1.get_section('code', create=True).add_data(bytes(59)) obj2 = ObjectFile(arch) obj2.get_section('code', create=True).add_data(bytes(59)) obj2.add_symbol(1, 'x', 'local', 5, 'code') obj2.debug_info = debuginfo.DebugInfo() loc = SourceLocation('a.txt', 1, 1, 22) obj2.debug_info.add( debuginfo.DebugLocation(loc, address=debuginfo.DebugAddress(1))) obj = link([obj1, obj2], debug=True) # Take into account alignment! So 60 + 5 = 65. self.assertEqual(0, obj.debug_info.locations[0].address.symbol_id) self.assertEqual(65, obj.get_symbol_id_value(0))
def test_inline_asm(self): """ Test the compilation of inline assembly code. """ src = """ int foo(int a, int b, char c) { asm ( "mov rsi, %0\n" "xor rsi, %1\n" "and rsi, %1\n" : : "r" (a), "r" (c) : "rsi" ); return b; } """ march = get_arch('x86_64') cc(io.StringIO(src), march)
def test_single_sample(self): src = io.StringIO(""" int add(int a, int b) { int g = a+b+55+1-2; return g + a+8*b; } """) mod = api.c_to_ir(src, 'x86_64') # For now optimize to the allocation of a variable on heap: api.optimize(mod, level='2') wasm_module = ir_to_wasm(mod) # W00t! Convert back to ir again! (because it is possible) mod2 = wasm_to_ir( wasm_module, api.get_arch('x86_64').info.get_type_info('ptr')) # TODO: find a way to execute this wasm code. ir_to_wasm(mod2)
def test_command(self, mock_stdout, mock_stderr): obj_file = new_temp_file('.obj') bin_file = new_temp_file('.bin') arch = api.get_arch('arm') obj = ObjectFile(arch) data = bytes(range(100)) section = Section('.text') section.add_data(data) image = Image('code2', 0) image.sections.append(section) obj.add_section(section) obj.add_image(image) with open(obj_file, 'w') as f: obj.save(f) objcopy(['-O', 'bin', '-S', 'code2', obj_file, bin_file]) with open(bin_file, 'rb') as f: exported_data = f.read() self.assertEqual(data, exported_data)
def compile(self, source): """ Compile the given source with current settings. """ srcfile = io.StringIO(source) outfile = io.StringIO() if self.stage == "ast": src_ast = create_ast(srcfile, api.get_arch(self.arch).info) print_ast(src_ast, file=outfile) else: ir_module = api.c_to_ir(srcfile, self.arch) if self.optimize: api.optimize(ir_module, level=2) if self.stage == "ir": print_module(ir_module, file=outfile) else: text_stream = TextOutputStream(f=outfile, add_binary=True) api.ir_to_stream(ir_module, self.arch, text_stream) return outfile.getvalue()
def compile_8cc(): """ Compile the 8cc compiler. 8cc homepage: https://github.com/rui314/8cc """ home = os.environ['HOME'] _8cc_folder = os.path.join(home, 'GIT', '8cc') libc_includes = os.path.join(this_dir, '..', 'librt', 'libc', 'include') linux_include_dir = '/usr/include' arch = api.get_arch('x86_64') coptions = COptions() include_paths = [ libc_includes, _8cc_folder, linux_include_dir, ] coptions.add_include_paths(include_paths) coptions.add_define('BUILD_DIR', '"{}"'.format(_8cc_folder)) sources = [ 'cpp.c', 'debug.c', 'dict.c', 'gen.c', 'lex.c', 'vector.c', 'parse.c', 'buffer.c', 'map.c', 'error.c', 'path.c', 'file.c', 'set.c', 'encoding.c', ] objs = [] for filename in sources: source_path = os.path.join(_8cc_folder, filename) with open(source_path, 'r') as f: objs.append(api.cc(f, arch, coptions=coptions))
def make_twins(self): """ Make two object files that have equal contents """ arch = get_arch('arm') object1 = ObjectFile(arch) object2 = ObjectFile(arch) object2.get_section('code', create=True).add_data(bytes(range(55))) object1.get_section('code', create=True).add_data(bytes(range(55))) object1.add_symbol(10, 'A', 'global', None, None, 'object', 0) object2.add_symbol(10, 'A', 'global', None, None, 'object', 0) object1.gen_relocation('rel8', 10, 'code', 0x2) object2.gen_relocation('rel8', 10, 'code', 0x2) object1.add_symbol(0, 'A2', 'global', 0x90, 'code', 'object', 0) object2.add_symbol(0, 'A2', 'global', 0x90, 'code', 'object', 0) object1.add_symbol(1, 'A3', 'global', 0x90, 'code', 'object', 0) object2.add_symbol(1, 'A3', 'global', 0x90, 'code', 'object', 0) object1.add_image(Image('a', 0x0)) object1.get_image('a').add_section(object1.get_section('code')) object2.add_image(Image('a', 0x0)) object2.get_image('a').add_section(object2.get_section('code')) return object1, object2
def test_gen_call(self): arch = get_arch('avr') frame = Frame('foo') pushed = [] popped = [] vcall = VCall('bar') vcall.live_in = {r17, r19r18} vcall.live_out = {r17, r19r18} regs = [r17, r19r18, r20, r25, r26] for instruction in arch.gen_save_registers(frame, regs): if isinstance(instruction, Push): pushed.append(instruction.rd) for instruction in arch.gen_restore_registers(frame, regs): if isinstance(instruction, Pop): popped.append(instruction.rd) self.assertTrue(pushed) self.assertTrue(popped) popped.reverse() self.assertSequenceEqual(pushed, popped) self.assertSequenceEqual([r18, r19, r20, r25, r26], pushed)
def test_symbol_values(self): """ Check if values are correctly resolved """ arch = get_arch('arm') object1 = ObjectFile(arch) object1.get_section('.text', create=True).add_data(bytes([0] * 108)) object1.add_symbol(0, 'b', 'global', 24, '.text', 'object', 0) object2 = ObjectFile(arch) object2.get_section('.text', create=True).add_data(bytes([0] * 100)) object2.add_symbol(0, 'a', 'global', 2, '.text', 'object', 0) layout1 = layout.Layout() flash_mem = layout.Memory('flash') flash_mem.location = 0x0 flash_mem.size = 0x1000 flash_mem.add_input(layout.SymbolDefinition('code_start')) flash_mem.add_input(layout.Section('.text')) flash_mem.add_input(layout.SymbolDefinition('code_end')) layout1.add_memory(flash_mem) object3 = link([object1, object2], layout1) self.assertEqual(110, object3.get_symbol_value('a')) self.assertEqual(24, object3.get_symbol_value('b')) self.assertEqual(208, object3.get_section('.text').size) self.assertEqual(0, object3.get_symbol_value('code_start')) self.assertEqual(208, object3.get_symbol_value('code_end'))
def to_ir(self, includes=None, march=None, reporter=None): """ Compile C3 to PPCI IR for the given architecture. """ # todo: why would we have to specify an arch here? # circular ref, maybe move get_arch to utils? from ppci.api import get_arch from ppci.api import get_current_arch includes = [] if includes is None else includes march = get_current_arch() if march is None else get_arch(march) logger = logging.getLogger('c3c') if not reporter: # pragma: no cover reporter = DummyReportGenerator() logger.debug('C3 compilation started') reporter.heading(2, 'c3 compilation') sources = [io.StringIO(i) for i in self.items] includes = [get_file(fn) for fn in includes] diag = DiagnosticsManager() c3b = C3Builder(diag, march.info) try: _, ir_modules = c3b.build(sources, includes) for ircode in ir_modules: Verifier().verify(ircode) except CompilerError as ex: diag.error(ex.msg, ex.loc) diag.print_errors() raise TaskError('Compile errors') reporter.message('C3 compilation listings for {}'.format(sources)) for ir_module in ir_modules: reporter.message('{} {}'.format(ir_module, ir_module.stats())) reporter.dump_ir(ir_module) return self._new('ir', ir_modules)
""" Create a simple microblaze program which spits out an 'A' character to the UART. """ import io from ppci.api import asm, get_arch, objcopy, link from ppci.binutils.layout import get_layout from ppci.arch.microblaze import instructions, registers arch = get_arch('microblaze') # See also: # https://github.com/edgarigl/tbm/blob/master/arch-microblaze/head.S # According to qemu, we have an xilinx xps uart-lite device. # This device has the following registers: # BASE_ADDR + 0x0 : Rx fifo # BASE_ADDR + 0x4 : Tx fifo # The uart base addr is: 0x8400_0000 src = """ section code reset_vector: bri _bare_start _bare_start: ; Setup stack: ; Print 'A' to console:
from ppci.lang.c import COptions from ppci.utils.reporting import html_reporter def get_sources(folder, extension): resfiles = [] resdirs = [] for x in os.walk(folder): for y in glob(os.path.join(x[0], extension)): resfiles.append(y) resdirs.append(x[0]) return ((resdirs, resfiles)) with html_reporter('report.html') as reporter: arch = get_arch('riscv') o1 = asm("start.s", arch) o2 = asm("nOSPortasm.s", arch) path = os.path.join('.', 'csrc', argv[1]) dirs, srcs = get_sources(path, '*.c') #srcs += [os.path.join('.','csrc','bsp.c')] + [os.path.join('.','csrc','lib.c')] dirs += [os.path.join('.', 'csrc')] obj = [] coptions = COptions() for dir in dirs: coptions.add_include_path(dir) for src in srcs: with open(src) as f: obj.append( cc(f, "riscv",
def test_function(self): march = get_arch('arm') with open(filename, 'r') as f: fortrancompile([f.read()], march)
def setUp(self): arch = get_arch('example') self.register_allocator = GraphColoringRegisterAllocator( arch, None, None)