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 _update_data(self): """Update the note data based on our changes.""" if not (self.note_name is None or self.note_type is None or \ self._desc_data is None): # Round the data up to a multiple of word size. desc_data = self._desc_data if (len(desc_data) % self.bytes_per_word) != 0: desc_data += ByteArray('\0' * (len(desc_data) % self.bytes_per_word)) data = ByteArray( struct.pack(self.endianess + self._format_chr * 3, len(self.note_name) + 1, len(desc_data), self.note_type)) data += ByteArray( struct.pack( self.endianess + str(align_up(len(self.note_name) + 1, self.bytes_per_word)) + 's', self.note_name + '\0')) data += desc_data self._data = data
def test_get_data(self): data = ByteArray("pants") sect = UnpreparedElfSection("test", data=data) self.assertEquals(sect.get_data(), data) sect = UnpreparedElfSection("test", section_type=SHT_NOBITS) sect.set_size(10) self.assertEquals(sect.get_data(), ByteArray('\0' * 10))
def todata(self, wordsize, endianess): """Initialise the data from object.""" if wordsize == 32: format_str = "III" else: format_str = "QQQ" num_mappings = len(self._mappings) if num_mappings > self.RS_MAX_MAPS: raise MergeError, "Error: %d rootserver mappings " \ "are being added to the kernel config but the maximum is %d." % \ (num_mappings, self.RS_MAX_MAPS) data = ByteArray( struct.pack(endianess + format_str, self._entry, self._stack, num_mappings)) for i in range(num_mappings): data += self._mappings[i].todata(wordsize, endianess) # Pad unused fields with zeros. data += ByteArray('\0' * (Mapping.get_struct_size(wordsize) * \ (self.RS_MAX_MAPS - num_mappings))) return ByteArray(data)
def test_data_append(self): data = ByteArray("pants") sect = UnpreparedElfSection(None, "test", data = data) self.assertEquals(sect.get_data(), data) sect.append_data(ByteArray("foo")) self.assertEquals(sect.get_data(), ByteArray("pantsfoo")) sect = sect.prepare(0, 0, 0) self.assertEqual(hasattr(sect, "data_append"), False)
def _encode(self, offset, val): """ Encode the provided value at the offset in this section's data. """ if val >= 0: self._data[offset:offset+4] = \ ByteArray(struct.pack(self.format_word, val)) else: self._data[offset:offset+4] = \ ByteArray(struct.pack(self.format_signed_word, val))
def get_thread_data(self, base_addr, live_threads, num_spare_threads): # Sort the threads into reverse priority order. live_threads.sort(lambda x, y: cmp(y[1], x[1])) # Setup empty scheduling queue data structures. priority_bitfield = 0L plist = [0 for i in range(self.MAX_PRIORITY + 1)] threads_at_priority = [[] for i in range(self.MAX_PRIORITY + 1)] # Iterate through and create scheduler priority list and bitmap. for i, thread in enumerate(live_threads): priority = thread[1] threads_at_priority[priority].append((i, priority)) if plist[priority] == 0L: priority_bitfield |= (1 << priority) plist[priority] = self.thread_num_to_tcb_addr(base_addr, i) # For each thread, determine who is next on the scheduler queue. tcb_prev_next = {} for plevel in threads_at_priority: i = 0 for entry in plevel: prev = plevel[(i - 1) % len(plevel)][0] next = plevel[(i + 1) % len(plevel)][0] tcb_prev_next[entry[0]] = (prev, next) i += 1 # Iterate through and create the TCBs. thread_data = ByteArray() num_threads = 0 for i, thread in enumerate(live_threads): prev, next = tcb_prev_next[i] thread_data += self.init_thread(i, thread, base_addr, prev, next) num_threads += 1 # Pack scheduling data priority_table = ByteArray() for pdata in plist: priority_table += ByteArray(struct.pack(self.format_str, pdata)) # Create the spare threads. first_spare_thread_num = num_threads for id in range(num_spare_threads): prev = first_spare_thread_num + ((id - 1) % num_spare_threads) next = first_spare_thread_num + ((id + 1) % num_spare_threads) thread_data += self.init_empty_thread(num_threads, base_addr, prev, next) num_threads += 1 first_spare_thread_addr = self.thread_num_to_tcb_addr( base_addr, first_spare_thread_num) return thread_data, priority_table, priority_bitfield, first_spare_thread_addr
def test_get_file_data(self): ef = SectionedElfSegment(sections=[]) self.assertRaises(InvalidArgument, ef.get_file_data) data = ByteArray("pants") ef = DataElfSegment(data=data) self.assertEqual(ef.get_file_data(), data)
def get_file_data(self): """Return the data that should be copied into the file. The data is returned as a byte array.""" if self.type == SHT_NOBITS: return ByteArray() else: return self._data
def test_remove_nobits(self): for file_name in ["data/null_elf", "data/arm_exec", "data/arm_stripped_exec", "data/arm_exec_nosect", "data/arm_object", "data/mips64_exec", "data/mips32_exec", "data/ia32_exec", "data/amd64_exec", "data/ia64_exec", ]: ef = PreparedElfFile(filename=file_name) if ef.segments: seg_sizes = [] for segment in ef.segments: seg_sizes.append((segment.get_memsz(), segment.get_filesz())) ef.remove_nobits() for segment, seg_size in zip(ef.segments, seg_sizes): self.assertEqual(segment.get_memsz(), segment.get_filesz()) self.assertEqual(segment.get_memsz(), seg_size[0]) ef = UnpreparedElfFile() sec = UnpreparedElfSection(None, section_type=SHT_NOBITS, data=10) self.assertEqual(sec.get_size(), 10) ef.add_section(sec) ef.remove_nobits() sec = ef.sections[1] self.assertEqual(sec.type, SHT_PROGBITS) self.assertEqual(sec.get_size(), 10) self.assertEqual(sec.get_file_data(), ByteArray('\0' * 10))
def remove_nobits(self): """If this section is nobits, change it to PROGBITS.""" if self.type == SHT_NOBITS: # Note: Order is important here. self.get_size() # is implemented differently depending on NOBITS vs PROGBITS self._data = ByteArray('\0' * self.get_size()) self.type = SHT_PROGBITS
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 get_data(self): """Return the data the will exist in memory. This may differ from what is copied into the file itself.""" if self.type == SHT_NOBITS: return ByteArray('\0' * self.get_size()) else: return self._data
def generate_dynamic_segments(self, cell, image, machine, pools): """ Create a memsection for the environment based on the size of the contents. """ attrs = image.new_attrs( cell.namespace.add_namespace("cell_environment")) attrs.attach = PF_R | PF_W attrs.pager = None attrs.data = ByteArray('\0') cell.space.register_mapping(attrs) self._add_entry( "SEGMENTS", CellEnvSegments(self.machine, self.image, self.mappings, self.min_page_size)) for mapping in self.mappings: self._add_entry( mapping[1], CellEnvSegmentEntry(self.machine, self.image, mapping)) self.snap(cell) out = self.generate_data(machine, image) attrs.size = len(out.getvalue()) self.memsect = image.add_memsection(attrs, machine, pools, section_prefix=cell.name)
def todata(self): """Convert the ELF header to an array of bytes""" packed = struct.pack(self.endianess + self.layout, self.st_name, self.st_info, self.st_other, self.st_shndx, self.st_value, self.st_size) data = ByteArray(packed) return data
def __init__(self, attrs, elf, _, pools, kernel_seg): ImageKernelHeap.__init__(self, attrs, pools) self.segment = None self.kernel_segment = kernel_seg data = self.attrs.data = ByteArray([]) if attrs.size is not None and len(data) < self.attrs.size: data.extend([0] * (self.attrs.size - len(data))) self.attrs.size = data.buffer_info()[1] * data.itemsize section_name = "kernel.heap" sect = UnpreparedElfSection(elf, section_name, SHT_PROGBITS, self.attrs.virt_addr, data=data, flags=SHF_WRITE | SHF_ALLOC) elf.add_section(sect) self.segment = SectionedElfSegment(elf, PT_LOAD, self.attrs.virt_addr, self.attrs.phys_addr, PF_R | PF_W, self.attrs.align, sections=[sect]) elf.add_segment(self.segment)
def _get_segments(self): elf_file = UnpreparedElfFile() sections = [UnpreparedElfSection(elf_file, "test1", data=ByteArray("test1 data")), UnpreparedElfSection(elf_file, "test2", data=ByteArray("test2 data"))] empty_sec_seg = SectionedElfSegment(None) full_sec_seg = SectionedElfSegment(elf_file, sections=sections) head_seg = HeaderElfSegment(None) prep_head_seg = HeaderElfSegment(None) prep_head_seg.prepare(37, PROG_HEADER_SIZE) data = ByteArray("pants") full_data_seg = DataElfSegment(None, vaddr=DATA_BASE, paddr=PHYS_BASE, data=data) nobits_data_seg = DataElfSegment(None, vaddr=DATA_BASE, paddr=PHYS_BASE, data=data, memsz=10) return empty_sec_seg, full_sec_seg, head_seg, prep_head_seg, full_data_seg, nobits_data_seg
def todata(self): """Convert the ELF header to an array of bytes""" packed = struct.pack(self.endianess + self.layout, self.p_type, self.p_flags, self.p_offset, self.p_vaddr, self.p_paddr, self.p_filesz, self.p_memsz, self.p_align) data = ByteArray(packed) return data
def todata(self): """Convert the ELF header to an array of bytes""" packed = struct.pack(self.endianess + self.layout, self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, self.sh_offset, self.sh_size, self.sh_link, self.sh_info, self.sh_addralign, self.sh_entsize) data = ByteArray(packed) return data
def generate_init_script(self, kernel, elf, image, machine): f = self.create_ops(kernel, image, machine) dlen = len(f.getvalue()) assert (dlen <= self.init_ms.get_attrs().size) self.init_ms.segment.sections[0]._data[:dlen] = ByteArray(f.getvalue()) f.close()
def test_setdata(self): ef = DataElfSegment() data = ByteArray("foo") ef.set_data(data) self.assertEqual(ef.get_file_data(), data) ef = SectionedElfSegment(sections=[]) self.assertRaises(InvalidArgument, ef.set_data, data)
def generate_init(self, machine, _, pools, image): """Create the environment section.""" out = self.generate_data(machine, image) dlen = len(out.getvalue()) assert (self.memsect.attrs.size == dlen) self.memsect.segment.sections[0]._data[:dlen] = \ ByteArray(out.getvalue())
def test_init(self): ElfSegment() ElfSegment(PT_LOAD) ElfSegment(program_header_type=PT_LOAD) sections = [UnpreparedElfSection("foo")] self.assertRaises(TypeError, ElfSegment, data=ByteArray("pants"), sections=sections)
def _update_data(self): """Update the note data based on our changes.""" if not (self.note_name is None or self.note_type is None or \ self._desc_data is None): data = ByteArray( struct.pack(self._endianess + self._format_chr * 3, len(self.note_name) + 1, len(self._desc_data), self.note_type)) data += ByteArray( struct.pack( self._endianess + str(align_up(len(self.note_name) + 1, self.bytes_per_word)) + 's', self.note_name)) data += self._desc_data self._data = data
def todata(self, wordsize, endianess): """Generate raw data from the object.""" if wordsize == 32: format_str = "IIIII" else: format_str = "QQQQQ" return ByteArray( struct.pack(endianess + format_str, self._low, self._high, self._sub_type, self._memdesc_type, self._virtual))
def test_get_size(self): sect = UnpreparedElfSection("test") self.assertEqual(sect.get_size(), 0) sect = UnpreparedElfSection("test", data=ByteArray("pants")) self.assertEqual(sect.get_size(), 5) sect = UnpreparedElfSection("test", SHT_NOBITS) sect.set_size(40) self.assertEqual(sect.get_size(), 40)
def todata(self): """Convert the ELF header to an array of bytes""" data = self.ident.todata() packed = struct.pack(self.ident.endianess + self.layout, self.e_type, self.e_machine, self.e_version, self.e_entry, self.e_phoff, self.e_shoff, self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum, self.e_shentsize, self.e_shnum, self.e_shstrndx) data.extend(ByteArray(packed)) return data
def todata(self, wordsize, endianess): """Initialise the object from data.""" if wordsize == 32: format_str = "III" else: format_str = "QQQ" return ByteArray( struct.pack(endianess + format_str, self._phys, self._virt, self._size))
def get_data(self, base, size): """ Get some size bytes of data starting at base. base must be > 0. """ assert 'b' in self.mode self.seek(base) data = ByteArray() data.fromfile(self, size) return data
def _todata(self, as_bytearray, args): """ A helper method which subclass.todata() should call to pack the data and return it in the correct wrapping object. """ packed = pack(self.endianess + self.layout, *args) if as_bytearray: return ByteArray(packed) else: return packed