from ..common.utils import struct_parse, elf_assert
from ..construct import ConstructError
from .structs import ELFStructs
-from .sections import Section, StringTableSection, SymbolTableSection
+from .sections import (
+ Section, StringTableSection, SymbolTableSection, NullSection)
from .segments import Segment, InterpSegment
if sectype == 'SHT_STRTAB':
return StringTableSection(section_header, name, self.stream)
+ elif sectype == 'SHT_NULL':
+ return NullSection(section_header, name, self.stream)
elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM'):
return self._make_symbol_table_section(section_header, name)
else:
self.stream.seek(self['sh_offset'])
return self.stream.read(self['sh_size'])
+ def is_null(self):
+ """ Is this a null section?
+ """
+ return False
+
def __getitem__(self, name):
""" Implement dict-like access to header entries
"""
return self.header[name]
+class NullSection(Section):
+ """ ELF NULL section
+ """
+ def __init__(self, header, name, stream):
+ super(NullSection, self).__init__(header, name, stream)
+
+ def is_null(self):
+ return True
+
+
class StringTableSection(Section):
""" ELF string table section.
"""
#-------------------------------------------------------------------------------
from ..construct import CString
from ..common.utils import struct_parse
+from .constants import SH_FLAGS
class Segment(object):
"""
return self.header[name]
+ def section_in_segment(self, section):
+ """ Is the given section contained in this segment?
+
+ Note: this tries to reproduce the intricate rules of the
+ ELF_SECTION_IN_SEGMENT_STRICT macro of the header
+ elf/include/internal.h in the source of binutils.
+ """
+ # Only the 'strict' checks from ELF_SECTION_IN_SEGMENT_1 are included
+ segtype = self['p_type']
+ sectype = section['sh_type']
+ secflags = section['sh_flags']
+
+ # Only PT_LOAD, PT_GNU_RELR0 and PT_TLS segments can contain SHF_TLS
+ # sections
+ if ( secflags & SH_FLAGS.SHF_TLS and
+ segtype in ('PT_TLS', 'PT_GNU_RELR0', 'PT_LOAD')):
+ return False
+ # PT_TLS segment contains only SHF_TLS sections, PT_PHDR no sections
+ # at all
+ elif ( (secflags & SH_FLAGS.SHF_TLS) != 0 and
+ segtype not in ('PT_TLS', 'PT_PHDR')):
+ return False
+
+ # In ELF_SECTION_IN_SEGMENT_STRICT the flag check_vma is on, so if
+ # this is an alloc section, check whether its VMA is in bounds.
+ if secflags & SH_FLAGS.SHF_ALLOC:
+ secaddr = section['sh_addr']
+ vaddr = self['p_vaddr']
+
+ # This checks that the section is wholly contained in the segment.
+ # The third condition is the 'strict' one - an empty section will
+ # not match at the very end of the segment (unless the segment is
+ # also zero size, which is handled by the second condition).
+ if not (secaddr >= vaddr and
+ secaddr - vaddr + section['sh_size'] <= self['p_memsz'] and
+ secaddr - vaddr <= self['p_memsz'] - 1):
+ return False
+
+ # If we've come this far and it's a NOBITS section, it's in the segment
+ if sectype == 'SHT_NOBITS':
+ return True
+
+ secoffset = section['sh_offset']
+ poffset = self['p_offset']
+
+ # Same logic as with secaddr vs. vaddr checks above, just on offsets in
+ # the file
+ return (secoffset >= poffset and
+ secoffset - poffset + section['sh_size'] <= self['p_filesz'] and
+ secoffset - poffset <= self['p_filesz'] - 1)
+
class InterpSegment(Segment):
""" INTERP segment. Knows how to obtain the path to the interpreter used
self._emitline(' [Requesting program interpreter: %s]' %
segment.get_interp_name())
+ # Sections to segments mapping
+ #
+ if self.elffile.num_sections() == 0:
+ # No sections? We're done
+ return
+
+ self._emitline('\n Section to Segment mapping:')
+ self._emitline(' Segment Sections...\n')
+
+ for nseg, segment in enumerate(self.elffile.iter_segments()):
+ self._emit(' %2.2d ' % nseg)
+
+ for section in self.elffile.iter_sections():
+ if ( not section.is_null() and
+ segment.section_in_segment(section)):
+ self._emit('%s ' % section.name)
+
+ self._emitline('')
+