def todata(self): """Return a list of (array, offset) tuples""" data = [(0, self.get_elf_header().todata())] # Create any section headers if self.sections[1:]: sect_data = ByteArray() for header in self.get_section_headers(): sect_data.extend(header.todata()) data.append( (self._sh_offset, sect_data) ) # Create any section headers if self.segments: ph_data = ByteArray() for segment in self.segments: ph_data.extend( segment.get_program_header(self.endianess, self.wordsize).todata()) data.append( (self._ph_offset, ph_data) ) if self.sections[1:]: data += [(sec.offset, sec.get_file_data()) for sec in self.sections] elif self.segments: data += [(seg.offset, seg.get_file_data()) for seg in self.segments] return data
def todata(self): """Return a list of (array, offset) tuples""" data = [(0, self.get_elf_header().todata())] # Create any section headers if self.sections and self.has_section_headers: sect_data = ByteArray() for sh in self.get_section_headers(): sect_data.extend(sh.todata()) data.append((self._sh_offset, sect_data)) # Create any segment headers if self.segments: ph_data = ByteArray() for segment in self.segments: ph_data.extend( segment.get_program_header(self.endianess, self.wordsize).todata()) data.append((self._ph_offset, ph_data)) if self.sections: data += [(sec.offset, sec.get_file_data()) for sec in self.sections] elif self.segments: data += [(seg.offset, seg.get_file_data()) for seg in self.segments] return data
def get_file_data(self, clean=False): """Return an array of bytes representing the data.""" #return ByteArray(chain(*(reloc.todata() for reloc in self.int_relocs))) data = ByteArray() for reloc in self.int_relocs: data.extend(reloc.todata()) return data
def add_memsection(self, attrs, machine, pools): """ Create a memsection for inclusion in the image. If the data or file attributes of 'attr' are non-None, then a ELF segment will be created, otherwise the memsection will will be included in the address layout process, but will be created at runtime by Iguana server. """ new_segment = None in_image = False if attrs.file is not None or attrs.data is not None: if attrs.file is not None: the_file = open(attrs.file, 'r') data = ByteArray(the_file.read()) the_file.close() else: data = attrs.data if attrs.size is not None and len(data) < attrs.size: data.extend([0] * (attrs.size - len(data))) attrs.size = data.buffer_info()[1] * data.itemsize sect = UnpreparedElfSection(attrs.name, SHT_PROGBITS, attrs.virt_addr, data = data, flags = SHF_WRITE | SHF_ALLOC) self.elf.add_section(sect) new_segment = SectionedElfSegment(PT_LOAD, attrs.virt_addr, attrs.phys_addr, PF_R | PF_W, machine.min_page_size(), sections=[sect]) self.elf.add_segment(new_segment) in_image = True obj = ImageMemsection(new_segment, attrs, pools) # If the memsection has data that goes into the image, then # put it at the front of the list so that it will be near the # code segments. if in_image: self.memsections = [obj] + self.memsections else: self.memsections.append(obj) return obj
def to_data(self, phys_addr): # Map a 1M section def set_section(array, index, pfn, rwx, cache): entry = (pfn << 20) | (rwx << 10) | (cache << 2) | 0x12 #print "set 1M entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(index*4, 4, '<') == 0 array.set_data(index*4, entry, 4, '<') # Map a 4K page def set_page(array, offset, index, pfn, rwx, cache): entry = (pfn << 12) | (rwx << 10) | (rwx << 8) | (rwx << 6) | \ (rwx << 4) | (cache << 2) | 0x2 #print "set 4K entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(offset+index*4, 4, '<') == 0 array.set_data(offset+index*4, entry, 4, '<') # Map a 64K page def set_large_page(array, offset, index, pfn, rwx, cache): entry = (pfn << 12) | (rwx << 10) | (rwx << 8) | (rwx << 6) | \ (rwx << 4) | (cache << 2) | 0x1 for i in range(index, index+16): #print "set 64K entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(offset+i*4, 4, '<') == 0 array.set_data(offset+i*4, entry, 4, '<') # Create a subtree to support 4k pages # will extend pagetable array as neccesary, returns an offset into pagetable array # which is start of 2nd level pagetable # will return old subtree if one already exists here def create_subtree(array, index, phys_addr): existing = array.get_data(index*4, 4, '<') # if we have already created a subtree here if existing & 0x3 == 1: return (existing & 0xfffffc00) - phys_addr assert (existing & 0x3 == 0) start = len(pagetable) array.extend(1024*[0]) entry = ((phys_addr + start) & ~0x3ff) | 0x11 #print "create subtree %x = %x (%x)" % (index, entry, phys_addr + start) array.set_data(index*4, entry, 4, '<') return start pagetable = ByteArray(16*1024*"\0") # Sort by virtual self._mappings.sort(key=lambda x: x[0]) for virt, phys, pgsize, npages, rwx, cache in self._mappings: if virt == 0: #print "Warning mapping at 0 - reserving 1K of space which may not be needed" pagetable.extend(1024*[0]) continue #print "map %x -> %x (%x bytes)" % (virt, phys, pgsize*npages) section_index = virt / 1024 / 1024 num_sections = ((npages*pgsize - 1) / 1024 / 1024) + 1 for section in range(section_index, section_index+num_sections): if pgsize == 0x00100000: # 1MB set_section(pagetable, section, phys / 1024 / 1024 + section-section_index, rwx, cache) elif pgsize == 0x00010000: # 64KB subtree = create_subtree(pagetable, section, phys_addr) page_index = (virt - (section * 1024 * 1024)) / 4096 for page in range(page_index, page_index + npages): set_large_page(pagetable, subtree, page, phys / 4096 + page - page_index, rwx, cache) else: # 4KB subtree = create_subtree(pagetable, section, phys_addr) page_index = (virt - (section * 1024 * 1024)) / 4096 for page in range(page_index, page_index + npages): set_page(pagetable, subtree, page, phys / 4096 + page - page_index, rwx, cache) return pagetable
def get_file_data(self): """Return an array of bytes representing the data.""" data = ByteArray() for sym in self.int_syms: data.extend(sym.todata()) return data
def get_file_data(self): """Return an array of bytes representing the data.""" data = ByteArray() for s in self.strings: data.extend(ByteArray(s)) return data
def add_memsection(self, attrs, machine, pools, section_prefix=None): """ Create a memsection for inclusion in the image. If the data or file attributes of 'attr' are non-None, then a ELF segment will be created, otherwise the memsection will will be included in the address layout process, but will be created at runtime by Iguana server. """ new_segment = None in_image = False if attrs.file is not None or attrs.data is not None: if attrs.file is not None: the_file = open(attrs.file, 'r') data = ByteArray(the_file.read()) the_file.close() else: data = attrs.data if attrs.size is not None and len(data) < attrs.size: data.extend([0] * (attrs.size - len(data))) attrs.size = data.buffer_info()[1] * data.itemsize if section_prefix: section_name = "%s.%s" % (section_prefix, attrs.ns_node.name) else: section_name = attrs.ns_node.name sect = UnpreparedElfSection(self.elf, section_name, SHT_PROGBITS, attrs.virt_addr, data=data, flags=SHF_WRITE | SHF_ALLOC) self.elf.add_section(sect) new_segment = SectionedElfSegment(self.elf, PT_LOAD, attrs.virt_addr, attrs.phys_addr, PF_R | PF_W, machine.min_page_size(), sections=[sect]) self.elf.add_segment(new_segment) in_image = True # This check should be added, but currently fails with iguana. # elif attrs.size is None: # raise MergeError, \ # 'No size attribute given for memsection \"%s\".' % attrs.abs_name() obj = ImageMemsection(new_segment, attrs, pools) # If the memsection has data that goes into the image, then # put it at the front of the list so that it will be near the # code segments. if in_image: self.memsections = [obj] + self.memsections else: self.memsections.append(obj) return obj
def to_data(self, phys_addr): # Map a 1M section def set_section(array, index, pfn, rwx, cache): entry = (pfn << 20) | (rwx << 10) | (cache << 2) | 0x12 #print "set 1M entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(index * 4, 4, '<') == 0 array.set_data(index * 4, entry, 4, '<') # Map a 4K page def set_page(array, offset, index, pfn, rwx, cache): entry = (pfn << 12) | (rwx << 10) | (rwx << 8) | (rwx << 6) | \ (rwx << 4) | (cache << 2) | 0x2 #print "set 4K entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(offset + index * 4, 4, '<') == 0 array.set_data(offset + index * 4, entry, 4, '<') # Map a 64K page def set_large_page(array, offset, index, pfn, rwx, cache): entry = (pfn << 12) | (rwx << 10) | (rwx << 8) | (rwx << 6) | \ (rwx << 4) | (cache << 2) | 0x1 for i in range(index, index + 16): #print "set 64K entry %x = %x (%x, %x, %x)" % (index, entry, pfn, rwx, cache) assert array.get_data(offset + i * 4, 4, '<') == 0 array.set_data(offset + i * 4, entry, 4, '<') # Create a subtree to support 4k pages # will extend pagetable array as neccesary, returns an offset into pagetable array # which is start of 2nd level pagetable # will return old subtree if one already exists here def create_subtree(array, index, phys_addr): existing = array.get_data(index * 4, 4, '<') # if we have already created a subtree here if existing & 0x3 == 1: return (existing & 0xfffffc00) - phys_addr assert (existing & 0x3 == 0) start = len(pagetable) array.extend(1024 * [0]) entry = ((phys_addr + start) & ~0x3ff) | 0x11 #print "create subtree %x = %x (%x)" % (index, entry, phys_addr + start) array.set_data(index * 4, entry, 4, '<') return start pagetable = ByteArray(16 * 1024 * "\0") # Sort by virtual self._mappings.sort(key=lambda x: x[0]) for virt, phys, pgsize, npages, rwx, cache in self._mappings: if virt == 0: #print "Warning mapping at 0 - reserving 1K of space which may not be needed" pagetable.extend(1024 * [0]) continue #print "map %x -> %x (%x bytes)" % (virt, phys, pgsize*npages) section_index = virt / 1024 / 1024 num_sections = ((npages * pgsize - 1) / 1024 / 1024) + 1 for section in range(section_index, section_index + num_sections): if pgsize == 0x00100000: # 1MB set_section(pagetable, section, phys / 1024 / 1024 + section - section_index, rwx, cache) elif pgsize == 0x00010000: # 64KB subtree = create_subtree(pagetable, section, phys_addr) page_index = (virt - (section * 1024 * 1024)) / 4096 for page in range(page_index, page_index + npages): set_large_page(pagetable, subtree, page, phys / 4096 + page - page_index, rwx, cache) else: # 4KB subtree = create_subtree(pagetable, section, phys_addr) page_index = (virt - (section * 1024 * 1024)) / 4096 for page in range(page_index, page_index + npages): set_page(pagetable, subtree, page, phys / 4096 + page - page_index, rwx, cache) return pagetable