def signed( value, nbits ): mask = 0x1 << (nbits - 1) value = trim( value, nbits ) if value & mask: twos_complement = ~value + 1 return -intmask( trim( twos_complement, nbits ) ) return intmask( value )
def signed(value, nbits): mask = 0x1 << (nbits - 1) value = trim(value, nbits) if value & mask: twos_complement = ~value + 1 return -intmask(trim(twos_complement, nbits)) return intmask(value)
def load_program( fp, mem, alignment=0, is_64bit=False ): mem_image = elf.elf_reader( fp, is_64bit=is_64bit ) sections = mem_image.get_sections() entrypoint = -1 for section in sections: start_addr = section.addr for i, data in enumerate( section.data ): mem.write( start_addr+i, 1, ord( data ) ) # TODO: HACK should really have elf_reader return the entry point # address in the elf header! if section.name == '.text': entrypoint = intmask( section.addr ) if section.name == '.data': mem.data_section = section.addr assert entrypoint >= 0 last_sec = sections[-1] breakpoint = last_sec.addr + len( last_sec.data ) if alignment > 0: def round_up( val, alignment ): return (val + alignment - 1) & ~(alignment - 1) breakpoint = round_up( breakpoint, alignment ) return entrypoint, breakpoint
def do_syscall(s): syscall_number = s.rf[v4] arg0 = intmask(s.rf[a1]) arg1 = intmask(s.rf[a2]) arg2 = intmask(s.rf[a3]) if syscall_number not in syscall_funcs: print "WARNING: syscall not implemented: %d" % syscall_number # TODO: return an error? else: syscall_handler = syscall_funcs[syscall_number] # call the syscall handler and get the return and error values retval, errno = syscall_handler(s, arg0, arg1, arg2) if s.debug.enabled("syscalls"): print " retval=%x errno=%x" % (retval, errno) s.rf[a1] = trim_32(retval)
def do_syscall( s ): syscall_number = s.rf[ v4 ] arg0 = intmask( s.rf[ a1 ] ) arg1 = intmask( s.rf[ a2 ] ) arg2 = intmask( s.rf[ a3 ] ) if syscall_number not in syscall_funcs: print "WARNING: syscall not implemented: %d" % syscall_number # TODO: return an error? else: syscall_handler = syscall_funcs[ syscall_number ] # call the syscall handler and get the return and error values retval, errno = syscall_handler( s, arg0, arg1, arg2 ) if s.debug.enabled( "syscalls" ): print " retval=%x errno=%x" % ( retval, errno ) s.rf[ a1 ] = trim_32( retval )
def syscall_brk( s, arg0, arg1, arg2 ): new_brk = arg0 if s.debug.enabled( "syscalls" ): print "syscall_brk( addr=%x )" % new_brk, if new_brk != 0: s.breakpoint = r_uint( new_brk ) return intmask( s.breakpoint ), 0
def execute_cmp(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = intmask(a - b) s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not_borrow_from(result) s.V = overflow_from_sub(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def do_syscall( s ): syscall_number = s.rf[17] arg0 = intmask( s.rf[10] ) arg1 = intmask( s.rf[11] ) arg2 = intmask( s.rf[12] ) # TODO: riscv supports 6 syscall args, disabling higher args for the time # being #arg3 = s.rf[13] #arg4 = s.rf[14] #arg5 = s.rf[15] if syscall_number not in syscall_funcs: print "WARNING: syscall not implemented: %d" % syscall_number else: syscall_handler = syscall_funcs[ syscall_number ] retval, errno = syscall_handler( s, arg0, arg1, arg2 ) if s.debug.enabled( "syscalls" ): print " retval=%x errno=%x" % ( retval, errno ) s.rf[ 10 ] = retval
def do_syscall(s): syscall_number = s.rf[17] arg0 = intmask(s.rf[10]) arg1 = intmask(s.rf[11]) arg2 = intmask(s.rf[12]) # TODO: riscv supports 6 syscall args, disabling higher args for the time # being #arg3 = s.rf[13] #arg4 = s.rf[14] #arg5 = s.rf[15] if syscall_number not in syscall_funcs: print "WARNING: syscall not implemented: %d" % syscall_number else: syscall_handler = syscall_funcs[syscall_number] retval, errno = syscall_handler(s, arg0, arg1, arg2) if s.debug.enabled("syscalls"): print " retval=%x errno=%x" % (retval, errno) s.rf[10] = retval
def execute_cmp( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = intmask( a - b ) s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = not_borrow_from( result ) s.V = overflow_from_sub( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_sbc(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = intmask(a - b - (not s.C)) s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not_borrow_from(result) s.V = overflow_from_sub(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_sbc( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = intmask( a - b - (not s.C) ) s.rf[ inst.rd ] = trim_32( result ) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = not_borrow_from( result ) s.V = overflow_from_sub( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def load_program(elf, mem, coreids, alignment=0, ext_base=0x8e000000, ext_size=32): """Copy the contents of an ELF file into individual cores. The 'elf' argument should be the result of a call to pydgin.elf.elf_reader(). """ sections = elf.get_sections() code_blocks = [] for coreid in coreids: coreid_mask = coreid << 20 for section in sections: if is_local_address(section.addr): start_addr = coreid_mask | section.addr else: start_addr = section.addr for index, data in enumerate(section.data): mem.write(start_addr + index, 1, ord(data), quiet=True) if section.name == '.text' or section.name == 'NEW_LIB_RO': entry_point = intmask(start_addr) end_point = entry_point + len(section.data) code_blocks.append((entry_point, end_point)) if section.name == '.data': mem.data_section = section.addr return code_blocks
def elf_reader(file_obj, is_64bit=False): # Read the data for the ELF header ehdr_data = file_obj.read( ElfHeader.NBYTES64 if is_64bit else ElfHeader.NBYTES) # Construct an ELF header object ehdr = ElfHeader(ehdr_data, is_64bit=is_64bit) # Verify if its a known format and realy an ELF file if ehdr.ident[0:4] != '\x7fELF': raise ValueError("Not a valid ELF file") # We need to find the section string table so we can figure out the # name of each section. We know that the section header for the section # string table is entry shstrndx, so we first get the data for this # section header. file_obj.seek(intmask(ehdr.shoff) + ehdr.shstrndx * ehdr.shentsize) shdr_data = file_obj.read(ehdr.shentsize) # Construct a section header object for the section string table shdr = ElfSectionHeader(shdr_data, is_64bit=is_64bit) # Read the data for the section header table file_obj.seek(intmask(shdr.offset)) shstrtab_data = file_obj.read(intmask(shdr.size)) # Load sections symtab_data = None strtab_data = None mem_image = SparseMemoryImage() for section_idx in range(ehdr.shnum): # Read the data for the section header file_obj.seek(intmask(ehdr.shoff) + section_idx * ehdr.shentsize) shdr_data = file_obj.read(ehdr.shentsize) # Pad the returned string in case the section header is not long # enough (otherwise the unpack function would not work) #shdr_data = shdr_data.ljust( ElfSectionHeader.NBYTES, '\0' ) shdr_nbytes = ElfSectionHeader.NBYTES64 if is_64bit else \ ElfSectionHeader.NBYTES fill = '\0' * (shdr_nbytes - len(shdr_data)) shdr_data = shdr_data + fill # Construct a section header object shdr = ElfSectionHeader(shdr_data, is_64bit=is_64bit) # Find the section name #start = shstrtab_data[shdr.name:] idx = shdr.name assert idx >= 0 start = shstrtab_data[idx:] #section_name = start.partition('\0')[0] section_name = start.split('\0', 1)[0] # only sections marked as lloc should be written to memory if not (shdr.flags & ElfSectionHeader.FLAGS_ALLOC): continue # Read the section data if it exists if section_name not in ['.sbss', '.bss']: file_obj.seek(intmask(shdr.offset)) data = file_obj.read(intmask(shdr.size)) # NOTE: the .bss and .sbss sections don't actually contain any # data in the ELF. These sections should be initialized to zero. # For more information see: # # - http://stackoverflow.com/questions/610682/bss-section-in-elf-file else: data = '\0' * shdr.size # Save the data holding the symbol string table if shdr.type == ElfSectionHeader.TYPE_STRTAB: strtab_data = data # Save the data holding the symbol table elif shdr.type == ElfSectionHeader.TYPE_SYMTAB: symtab_data = data # Otherwise create section and append it to our list of sections else: section = SparseMemoryImage.Section(section_name, shdr.addr, data) mem_image.add_section(section) # Load symbols. We skip the first symbol since it both "designates the # first entry in the table and serves as the undefined symbol index". # For now, I have commented this out, since we are not really using it. # num_symbols = len(symtab_data) / ElfSymTabEntry.NBYTES # for sym_idx in xrange(1,num_symbols): # # # Read the data for a symbol table entry # # start = sym_idx * ElfSymTabEntry.NBYTES # sym_data = symtab_data[start:start+ElfSymTabEntry.NBYTES] # # # Construct a symbol table entry # # sym = ElfSymTabEntry( sym_data ) # # # Get the symbol type # # sym_type = sym.info & 0xf # # # Check to see if symbol is one of the three types we want to load # # valid_sym_types = \ # [ # ElfSymTabEntry.TYPE_NOTYPE, # ElfSymTabEntry.TYPE_OBJECT, # ElfSymTabEntry.TYPE_FUNC, # ] # # # Check to see if symbol is one of the three types we want to load # # if sym_type not in valid_sym_types: # continue # # # Get the symbol name from the string table # # start = strtab_data[sym.name:] # name = start.partition('\0')[0] # # # Add symbol to the sparse memory image # # mem_image.add_symbol( name, sym.value ) return mem_image
def elf_reader( file_obj, is_64bit=False ): # Read the data for the ELF header ehdr_data = file_obj.read( ElfHeader.NBYTES64 if is_64bit else ElfHeader.NBYTES ) # Construct an ELF header object ehdr = ElfHeader( ehdr_data, is_64bit=is_64bit ) # Verify if its a known format and realy an ELF file if ehdr.ident[0:4] != '\x7fELF': raise ValueError( "Not a valid ELF file" ) # We need to find the section string table so we can figure out the # name of each section. We know that the section header for the section # string table is entry shstrndx, so we first get the data for this # section header. file_obj.seek( intmask( ehdr.shoff ) + ehdr.shstrndx * ehdr.shentsize ) shdr_data = file_obj.read(ehdr.shentsize) # Construct a section header object for the section string table shdr = ElfSectionHeader( shdr_data, is_64bit=is_64bit ) # Read the data for the section header table file_obj.seek( intmask( shdr.offset ) ) shstrtab_data = file_obj.read( intmask( shdr.size ) ) # Load sections symtab_data = None strtab_data = None mem_image = SparseMemoryImage() for section_idx in range(ehdr.shnum): # Read the data for the section header file_obj.seek( intmask( ehdr.shoff ) + section_idx * ehdr.shentsize ) shdr_data = file_obj.read(ehdr.shentsize) # Pad the returned string in case the section header is not long # enough (otherwise the unpack function would not work) #shdr_data = shdr_data.ljust( ElfSectionHeader.NBYTES, '\0' ) shdr_nbytes = ElfSectionHeader.NBYTES64 if is_64bit else \ ElfSectionHeader.NBYTES fill = '\0'*( shdr_nbytes - len(shdr_data) ) shdr_data = shdr_data + fill # Construct a section header object shdr = ElfSectionHeader( shdr_data, is_64bit=is_64bit ) # Find the section name #start = shstrtab_data[shdr.name:] idx = shdr.name assert idx >= 0 start = shstrtab_data[idx:] #section_name = start.partition('\0')[0] section_name = start.split('\0', 1)[0] # only sections marked as lloc should be written to memory if not (shdr.flags & ElfSectionHeader.FLAGS_ALLOC): continue # Read the section data if it exists if section_name not in ['.sbss', '.bss']: file_obj.seek( intmask( shdr.offset ) ) data = file_obj.read( intmask( shdr.size ) ) # NOTE: the .bss and .sbss sections don't actually contain any # data in the ELF. These sections should be initialized to zero. # For more information see: # # - http://stackoverflow.com/questions/610682/bss-section-in-elf-file else: data = '\0' * shdr.size # Save the data holding the symbol string table if shdr.type == ElfSectionHeader.TYPE_STRTAB: strtab_data = data # Save the data holding the symbol table elif shdr.type == ElfSectionHeader.TYPE_SYMTAB: symtab_data = data # Otherwise create section and append it to our list of sections else: section = SparseMemoryImage.Section( section_name, shdr.addr, data ) mem_image.add_section( section ) # Load symbols. We skip the first symbol since it both "designates the # first entry in the table and serves as the undefined symbol index". # For now, I have commented this out, since we are not really using it. # num_symbols = len(symtab_data) / ElfSymTabEntry.NBYTES # for sym_idx in xrange(1,num_symbols): # # # Read the data for a symbol table entry # # start = sym_idx * ElfSymTabEntry.NBYTES # sym_data = symtab_data[start:start+ElfSymTabEntry.NBYTES] # # # Construct a symbol table entry # # sym = ElfSymTabEntry( sym_data ) # # # Get the symbol type # # sym_type = sym.info & 0xf # # # Check to see if symbol is one of the three types we want to load # # valid_sym_types = \ # [ # ElfSymTabEntry.TYPE_NOTYPE, # ElfSymTabEntry.TYPE_OBJECT, # ElfSymTabEntry.TYPE_FUNC, # ] # # # Check to see if symbol is one of the three types we want to load # # if sym_type not in valid_sym_types: # continue # # # Get the symbol name from the string table # # start = strtab_data[sym.name:] # name = start.partition('\0')[0] # # # Add symbol to the sparse memory image # # mem_image.add_symbol( name, sym.value ) return mem_image