Exemplo n.º 1
0
    def _initialise_segments(self, hdr, file_, prepare):
        """Initialise instance from program headers."""
        # Now load all the program headers
        #
        # "The time has come," the developer said, "to talk of many
        # things: Of section to segment mapping and scatter load, of
        # cabbages and kings, and why the RVCT linker is on drugs and
        # whether pigs have wings."
        #
        # There are two ways of determining which sections belong in a
        # segment:
        #
        # 1) In most cases a section is in a segment if its virtual
        #    address range falls in the virtual address range of the
        #    segment.  These segments tend to contain multiple
        #    PROGBITS sections and may end with a NOBITS section.
        #
        # 2) In the case of segments build with RVCT's scatter load
        #    support the virtual address of the included sections can
        #    be anywhere in memory.  In this case a section is in the
        #    segment if its data file offset falls in the offset range
        #    of the segment.  These segments can contain multiple
        #    PROGBITS and NOBITS sections in any order.  The file size
        #    of the segment is the filesize of all of the PROGBITS
        #    sections.  The memory size of the segment is the sum of
        #    the size of all of the sections, not the difference
        #    between the lowest and highest virtual addresses.
        #
        # Some other things about ELF files that you need to know:
        #
        # a) Segments can overlap, and sections can appear in multiple
        #    segments.
        #
        # b) Some sections do not appear in any segments.  These tend
        #    to be the symbol table and other debugging data.
        #
        # c) The offsets of NOBITS sections tend to be the same as the
        #    offset for the next PROGBITS section, even if it is in
        #    the next segment.  However, sometimes NOBITS sections
        #    appear at the beginning of a segment.
        #
        # d) The address offset from the start of a segment and the
        #    file offset from the start of the segment are not
        #    necessarily the same.
        #
        # Therefore, to map sections to segments involves two passes:
        #
        # 1) Find all of the sections that fall in the segment virtual
        #    address range.
        #
        # 2) Find all of the remaining sections that fall in the file
        #    offset range.  If any are found then mark the segment as
        #    a scatter-load segment.
        #
        # The file size and memory size of a segment depends on
        # whether or not it is a scatter load segment.  For scatter
        # load files, the section that has the latest offset from the
        # beginning of the section is used, while for non-scatter-load
        # segments, the section with the largest virtual address is
        # used.
        #
        # File offsets cannot be used for both types of segments
        # because broken linkers can produce sections with
        # inconsistant virtual address to file offset mappings and
        # this will make elfweaver produce segments with incorrect
        # file sizes or memory sizes.
        #
        # "O Readers," said the developer, "You've had a pleasant run!
        # Shall we start the code again?" But answer came there none--
        # And this was scarcely odd, because no-one would read this far
        # for fun.

        self._ph_offset = hdr.e_phoff
        self.segments = []

        # Short circuit the return.
        if hdr.e_phoff == 0:
            return

        ph_list = self._get_headers(hdr, file_, ELF_PH_CLASSES, hdr.e_phoff,
                                    hdr.e_phentsize, hdr.e_phnum)

        # Map segments to sections, pass 1.
        for ph in ph_list:
            if ph.p_type != PT_PHDR:
                low = ph.p_vaddr
                high = low + ph.p_memsz
                sects = []
                for section in self.sections:
                    # See if the section's virtual address range falls within
                    # the virtual address range of the segment.
                    addr = section.address
                    if low <= addr < high and addr + section.get_size() <= high:
                        sects.append(section)

                if sects:
                    seg = SectionedElfSegment(self,
                                              prog_header=ph,
                                              sections=sects)
                else:
                    data = file_.get_data(ph.p_offset, ph.p_filesz)
                    seg = DataElfSegment(self,
                                         prog_header=ph,
                                         data=data,
                                         memsz=ph.p_memsz)
            else:
                seg = HeaderElfSegment(self, prog_header=ph)
            self.segments.append(seg)

        # Map segments to sections, pass 2
        sheaders = self._get_section_headers(hdr, file_)
        sect_offsets = [header.sh_offset for header in sheaders]
        for ph, seg in zip(ph_list, self.segments):
            if seg.has_sections():
                low = ph.p_offset
                high = low + ph.p_filesz
                for (section, offset) in zip(self.sections, sect_offsets):
                    # Scatter-load sections do not appear in multiple segments,
                    # so skip sections that are already in some segment.
                    if section.in_segment:
                        continue
                    # See if the section's file offset range falls within the
                    # file offset range of the segment.  Remember that the
                    # trailing BSS section can have the offset of the next
                    # section
                    if low <= offset <= high and \
                           ((section.type == SHT_NOBITS and offset != low) or \
                            (section.type != SHT_NOBITS and section.get_size() > 0 and \
                             offset + section.get_size() <= high)):
                        seg.add_section(section)
                        seg.set_scatter_load()

                # If we're a scatter-load segment we need to work out in segment
                # offsets for our sections
                if seg.is_scatter_load():
                    for section in seg.sections:
                        idx = self.sections.index(section)
                        offset = sect_offsets[idx]
                        section.set_in_segment_offset(offset - ph.p_offset)

        # If need be, we now prepare the segments
        if prepare:
            for ph, seg in zip(ph_list, self.segments):
                if ph.p_type == PT_PHDR:
                    prog_header_size = hdr.e_phentsize * hdr.e_phnum
                else:
                    prog_header_size = None
                seg.prepare(ph.p_offset, prog_header_size)
Exemplo n.º 2
0
Arquivo: core.py Projeto: BruceYi/okl4
    def _initialise_segments(self, hdr, file_, prepare):
        """Initialise instance from program headers."""
        # Now load all the program headers
        #
        # "The time has come," the developer said, "to talk of many
        # things: Of section to segment mapping and scatter load, of
        # cabbages and kings, and why the RVCT linker is on drugs and
        # whether pigs have wings."
        #
        # There are two ways of determining which sections belong in a
        # segment:
        #
        # 1) In most cases a section is in a segment if its virtual
        #    address range falls in the virtual address range of the
        #    segment.  These segments tend to contain multiple
        #    PROGBITS sections and may end with a NOBITS section.
        #
        # 2) In the case of segments build with RVCT's scatter load
        #    support the virtual address of the included sections can
        #    be anywhere in memory.  In this case a section is in the
        #    segment if its data file offset falls in the offset range
        #    of the segment.  These segments can contain multiple
        #    PROGBITS and NOBITS sections in any order.  The file size
        #    of the segment is the filesize of all of the PROGBITS
        #    sections.  The memory size of the segment is the sum of
        #    the size of all of the sections, not the difference
        #    between the lowest and highest virtual addresses.
        #
        # Some other things about ELF files that you need to know:
        #
        # a) Segments can overlap, and sections can appear in multiple
        #    segments.
        #
        # b) Some sections do not appear in any segments.  These tend
        #    to be the symbol table and other debugging data.
        #
        # c) The offsets of NOBITS sections tend to be the same as the
        #    offset for the next PROGBITS section, even if it is in
        #    the next segment.  However, sometimes NOBITS sections
        #    appear at the beginning of a segment.
        #
        # d) The address offset from the start of a segment and the
        #    file offset from the start of the segment are not
        #    necessarily the same.
        #
        # Therefore, to map sections to segments involves two passes:
        #
        # 1) Find all of the sections that fall in the segment virtual
        #    address range.
        #
        # 2) Find all of the remaining sections that fall in the file
        #    offset range.  If any are found then mark the segment as
        #    a scatter-load segment.
        #
        # The file size and memory size of a segment depends on
        # whether or not it is a scatter load segment.  For scatter
        # load files, the section that has the latest offset from the
        # beginning of the section is used, while for non-scatter-load
        # segments, the section with the largest virtual address is
        # used.
        #
        # File offsets cannot be used for both types of segments
        # because broken linkers can produce sections with
        # inconsistant virtual address to file offset mappings and
        # this will make elfweaver produce segments with incorrect
        # file sizes or memory sizes.
        #
        # "O Readers," said the developer, "You've had a pleasant run!
        # Shall we start the code again?" But answer came there none--
        # And this was scarcely odd, because no-one would read this far
        # for fun.

        self._ph_offset = hdr.e_phoff
        self.segments = []

        # Short circuit the return.
        if hdr.e_phoff == 0:
            return

        ph_list = self._get_headers(hdr, file_, ELF_PH_CLASSES, hdr.e_phoff,
                                    hdr.e_phentsize, hdr.e_phnum)

        # Map segments to sections, pass 1.
        for ph in ph_list:
            if ph.p_type != PT_PHDR:
                low = ph.p_vaddr
                high = low + ph.p_memsz
                sects = []
                for section in self.sections:
                    # See if the section's virtual address range falls within
                    # the virtual address range of the segment.
                    addr = section.address
                    if low <= addr < high and addr + section.get_size() <= high:
                        sects.append(section)

                if sects:
                    seg = SectionedElfSegment(self, prog_header=ph,
                                              sections=sects)
                else:
                    data = file_.get_data(ph.p_offset, ph.p_filesz)
                    seg = DataElfSegment(self, prog_header=ph, data=data,
                                         memsz=ph.p_memsz)
            else:
                seg = HeaderElfSegment(self, prog_header=ph)
            self.segments.append(seg)

        # Map segments to sections, pass 2
        sheaders = self._get_section_headers(hdr, file_)
        sect_offsets = [header.sh_offset for header in sheaders]
        for ph, seg in zip(ph_list, self.segments):
            if seg.has_sections():
                low = ph.p_offset
                high = low + ph.p_filesz
                for (section, offset) in zip(self.sections, sect_offsets):
                    # Scatter-load sections do not appear in multiple segments,
                    # so skip sections that are already in some segment.
                    if section.in_segment:
                        continue
                    # See if the section's file offset range falls within the
                    # file offset range of the segment.  Remember that the
                    # trailing BSS section can have the offset of the next
                    # section
                    if low <= offset <= high and \
                           ((section.type == SHT_NOBITS and offset != low) or \
                            (section.type != SHT_NOBITS and section.get_size() > 0 and \
                             offset + section.get_size() <= high)):
                        seg.add_section(section)
                        seg.set_scatter_load()

                # If we're a scatter-load segment we need to work out in segment
                # offsets for our sections
                if seg.is_scatter_load():
                    for section in seg.sections:
                        idx = self.sections.index(section)
                        offset = sect_offsets[idx]
                        section.set_in_segment_offset(offset - ph.p_offset)

        # If need be, we now prepare the segments
        if prepare:
            for ph, seg in zip(ph_list, self.segments):
                if ph.p_type == PT_PHDR:
                    prog_header_size = hdr.e_phentsize * hdr.e_phnum
                else:
                    prog_header_size = None
                seg.prepare(ph.p_offset, prog_header_size)