Beispiel #1
0
 def ResetForPack(self):
     """Reset offset/size fields so that packing can be done again"""
     self.Detail('ResetForPack: offset %s->%s, size %s->%s' %
                 (to_hex(self.offset), to_hex(self.orig_offset),
                  to_hex(self.size), to_hex(self.orig_size)))
     self.pre_reset_size = self.size
     self.offset = self.orig_offset
     self.size = self.orig_size
Beispiel #2
0
    def Pack(self, offset):
        """Figure out how to pack the entry into the section

        Most of the time the entries are not fully specified. There may be
        an alignment but no size. In that case we take the size from the
        contents of the entry.

        If an entry has no hard-coded offset, it will be placed at @offset.

        Once this function is complete, both the offset and size of the
        entry will be know.

        Args:
            Current section offset pointer

        Returns:
            New section offset pointer (after this entry)
        """
        self.Detail(
            'Packing: offset=%s, size=%s, content_size=%x' %
            (to_hex(self.offset), to_hex(self.size), self.contents_size))
        if self.offset is None:
            if self.offset_unset:
                self.Raise('No offset set with offset-unset: should another '
                           'entry provide this correct offset?')
            self.offset = tools.align(offset, self.align)
        needed = self.pad_before + self.contents_size + self.pad_after
        needed = tools.align(needed, self.align_size)
        size = self.size
        if not size:
            size = needed
        new_offset = self.offset + size
        aligned_offset = tools.align(new_offset, self.align_end)
        if aligned_offset != new_offset:
            size = aligned_offset - self.offset
            new_offset = aligned_offset

        if not self.size:
            self.size = size

        if self.size < needed:
            self.Raise("Entry contents size is %#x (%d) but entry size is "
                       "%#x (%d)" % (needed, needed, self.size, self.size))
        # Check that the alignment is correct. It could be wrong if the
        # and offset or size values were provided (i.e. not calculated), but
        # conflict with the provided alignment values
        if self.size != tools.align(self.size, self.align_size):
            self.Raise(
                "Size %#x (%d) does not match align-size %#x (%d)" %
                (self.size, self.size, self.align_size, self.align_size))
        if self.offset != tools.align(self.offset, self.align):
            self.Raise("Offset %#x (%d) does not match align %#x (%d)" %
                       (self.offset, self.offset, self.align, self.align))
        self.Detail(
            '   - packed: offset=%#x, size=%#x, content_size=%#x, next_offset=%x'
            % (self.offset, self.size, self.contents_size, new_offset))

        return new_offset
Beispiel #3
0
    def ProcessContentsUpdate(self, data):
        """Update the contents of an entry, after the size is fixed

        This checks that the new data is the same size as the old. If the size
        has changed, this triggers a re-run of the packing algorithm.

        Args:
            data: Data to set to the contents (bytes)

        Raises:
            ValueError if the new data size is not the same as the old
        """
        size_ok = True
        new_size = len(data)
        if state.AllowEntryExpansion() and new_size > self.contents_size:
            # self.data will indicate the new size needed
            size_ok = False
        elif state.AllowEntryContraction() and new_size < self.contents_size:
            size_ok = False

        # If not allowed to change, try to deal with it or give up
        if size_ok:
            if new_size > self.contents_size:
                self.Raise('Cannot update entry size from %d to %d' %
                           (self.contents_size, new_size))

            # Don't let the data shrink. Pad it if necessary
            if size_ok and new_size < self.contents_size:
                data += tools.get_bytes(0, self.contents_size - new_size)

        if not size_ok:
            tout.debug("Entry '%s' size change from %s to %s" %
                       (self._node.path, to_hex(
                           self.contents_size), to_hex(new_size)))
        self.SetContents(data)
        return size_ok