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 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 _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 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 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 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 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 test_getmemsz(self): seg = DataElfSegment() self.assertRaises(InvalidArgument, seg.get_memsz) data = ByteArray() data.memsz = 10 seg.set_data(data) self.assertEquals(seg.get_memsz(), 10) seg = HeaderElfSegment() self.assertRaises(Unprepared, seg.get_memsz)
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 test_get_program_header(self): data = ByteArray() data.memsz = 0 seg = DataElfSegment(None, data = data) self.assertRaises(Unprepared, seg.get_program_header, '<', 32) seg.prepare(0) self.assertRaises(InvalidArgument, seg.get_program_header, '<', 33) self.assertRaises(InvalidArgument, seg.get_program_header, 'ads', 32) ph = seg.get_program_header('<', 32) self.assertEquals(ph.todata(), Elf32ProgramHeader('<').todata())
def test_get_program_header(self): data = ByteArray() data.memsz = 0 seg = DataElfSegment(data=data) self.assertRaises(Unprepared, seg.get_program_header, "<", 32) seg.prepare(0) self.assertRaises(InvalidArgument, seg.get_program_header, "<", 33) self.assertRaises(InvalidArgument, seg.get_program_header, "ads", 32) ph = seg.get_program_header("<", 32) self.assertEquals(ph.todata(), Elf32ProgramHeader("<").todata())
def test_getfilesz(self): seg = DataElfSegment() self.assertRaises(InvalidArgument, seg.get_filesz) data = ByteArray("1234567890") data.memsz = 10 seg.set_data(data) self.assertEquals(seg.get_filesz(), 10) seg = HeaderElfSegment() self.assertRaises(Unprepared, seg.get_filesz) seg = SectionedElfSegment() self.assertEqual(seg.get_filesz(), 0)
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 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 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 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 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 __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 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 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 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 __init__(self, elffile, name=None, section_type=SHT_NULL, address=0, data=None, flags=0, addralign=0, info=None, link=None, entsize=None): self.elffile = elffile self.address = address self.type = section_type self._name = name self.flags = flags self.addralign = addralign self.entsize = entsize self.info = info self.link = link self._backlinks = [] # keeps track of sections which link to us. self._in_segment_offset = None self.in_segment = False if self.address is None: self.address = 0 # If the section is a 'NOBITS' section, then it just has size, and # no real data. So _data, may be an integer or a ByteArray depending # on the different circumstance if data is None: if section_type == SHT_NOBITS: self._data = 0 else: self._data = ByteArray() else: self._data = data if section_type == SHT_NOBITS: assert is_integer(self._data) else: assert self._data.__class__ == ByteArray
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 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 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 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 _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 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 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 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, 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
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 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 s in self.strings: data.extend(ByteArray(s)) return data
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
class BaseElfSection(object): """ ElfSection instances represent sections in an ELF file. Note that this differs from ElfSectionheader, which just describes the header, not the data itself. ElfSection objects can exist in two states: prepared and unprepared. The subclasses UnpreparedElfSection and PreparedElfSection represent these two states. In the prepared state the section is ready to be written out to a file, but can not be modified (unless the changes maintain certain invariants). In the unprepared state the section can be modified, but must be prepared for writing before it can actually be written out. A section can be intialised from into either the prepared or unprepared state. Once in the prepared state, it is not possible to revert to the unprepared state. An unprepared section has a method .prepare which will return a prepared version of the section. Two important properties of the section, the wordsize and endianess, are only available in the prepared state. This class is written with the expectation that it will be sub-classed. To create a subclass (e.g. to implement a particular type of section) you need to create subclasses following the inheritance pattern below (this pattern is a little complicated, but would look much saner in 3D). BaseElfSection | |-------------------------------------------| | | | UnpreparedElfSection PreparedElfSection BaseSubClass | | | | | |-----------------| | | | | | PreparedSubClass | | | |-------------------------------------------| | UnpreparedSubClass class BaseSubClass(BaseElfSection): pass class UnpreparedSubClass(UnpreparedElfSection, BaseSubClass): pass class PreparedSubClass(PreparedElfSection, BaseSubClass): pass In this example, BaseSubClass would provide any class specific methods and also override any methods of BaseElfSection. When overriding methods of BaseElfSection, it is important to pass these overrides to subclasses. For example, if BaseSubClass defines get_size() (overriding BaseElfSection.get_size), then each of its subclasses would require a line get_size = BaseSubClass.get_size This is because python resolves multiple inheritance depth first, left to right, so BaseElfSection.get_size would be the first method resolved unless the explicit override is given. """ def __init__(self, elffile, name=None, section_type=SHT_NULL, address=0, data=None, flags=0, addralign=0, info=None, link=None, entsize=None): self.elffile = elffile self.address = address self.type = section_type self._name = name self.flags = flags self.addralign = addralign self.entsize = entsize self.info = info self.link = link self._backlinks = [] # keeps track of sections which link to us. self._in_segment_offset = None self.in_segment = False if self.address is None: self.address = 0 # If the section is a 'NOBITS' section, then it just has size, and # no real data. So _data, may be an integer or a ByteArray depending # on the different circumstance if data is None: if section_type == SHT_NOBITS: self._data = 0 else: self._data = ByteArray() else: self._data = data if section_type == SHT_NOBITS: assert is_integer(self._data) else: assert self._data.__class__ == ByteArray def __repr__(self): return "<%s %s %s>" % (self.__class__.__name__, self.type, self.name) def get_size(self): """Return the size of the section in bytes.""" if self.type == SHT_NOBITS: return self._data else: return len(self._data) def _get_name(self): """Return the name of this segment.""" return self._name name = property(_get_name) def _set_link(self, link): """Set a related section.""" if link is not None: if not issubclass(link.__class__, BaseElfSection): raise InvalidArgument, "Link must be an ElfSection. %s" % \ str(link.__class__) link._backlinks.append(self) self._link = link def _get_link(self): """Return the related ElfSection.""" return self._link link = property(_get_link, _set_link) 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 get_file_data(self, clean=False): """ 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: if clean: return self._data.copy() else: return self._data 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_num_entries(self): """Return number of entries in the section.""" if self.entsize is None: raise InvalidArgument, "This section does not use entries" return self.get_size() / self.entsize def get_entry(self, index): """Return the data for a given entry""" if self.entsize is None: raise InvalidArgument, "This section does not use entries" size = self.entsize return self._data[index*size:(index+1)*size] def get_entries(self): """Return a generator of all entries.""" if self.entsize is None: raise InvalidArgument, "This section does not use entries" for i in range(self.get_num_entries()): yield self.get_entry(i) def set_in_segment_offset(self, offset): self._in_segment_offset = offset def calc_in_segment_offset(self, segment): """ Return the offset into the given segment. """ offset = self._in_segment_offset if not segment.is_scatter_load() or offset is None or \ self.name.startswith('kernel_') or self.name.startswith('ER_'): return self.address - segment.vaddr else: return offset def data_trim(self, frm, to): """Trim the data so it is just [frm:to]""" self._data = self._data[frm:to] def info_is_section(self): """ Do we expect the .link for this section to be a section itself? """ return self.type in (SHT_REL, SHT_RELA) def _get_wordsize(self): """ Wordsize is proxied to the elf file. """ return self.elffile.wordsize wordsize = property(_get_wordsize) def _get_endianess(self): """ Endianess is proxied to the elf file. """ return self.elffile.endianess endianess = property(_get_endianess)