Upstream version 8.36.161.0
[platform/framework/web/crosswalk.git] / src / third_party / pyelftools / elftools / elf / segments.py
1 #-------------------------------------------------------------------------------
2 # elftools: elf/segments.py
3 #
4 # ELF segments
5 #
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
9 from ..construct import CString
10 from ..common.utils import struct_parse
11 from .constants import SH_FLAGS
12
13
14 class Segment(object):
15     def __init__(self, header, stream):
16         self.header = header
17         self.stream = stream
18     
19     def data(self):
20         """ The segment data from the file.
21         """
22         self.stream.seek(self['p_offset'])
23         return self.stream.read(self['p_filesz'])
24
25     def __getitem__(self, name):
26         """ Implement dict-like access to header entries
27         """
28         return self.header[name]
29
30     def section_in_segment(self, section):
31         """ Is the given section contained in this segment?
32
33             Note: this tries to reproduce the intricate rules of the 
34             ELF_SECTION_IN_SEGMENT_STRICT macro of the header 
35             elf/include/internal.h in the source of binutils.
36         """
37         # Only the 'strict' checks from ELF_SECTION_IN_SEGMENT_1 are included
38         segtype = self['p_type']
39         sectype = section['sh_type']
40         secflags = section['sh_flags']
41
42         # Only PT_LOAD, PT_GNU_RELR0 and PT_TLS segments can contain SHF_TLS
43         # sections
44         if (    secflags & SH_FLAGS.SHF_TLS and 
45                 segtype in ('PT_TLS', 'PT_GNU_RELR0', 'PT_LOAD')):
46             return False
47         # PT_TLS segment contains only SHF_TLS sections, PT_PHDR no sections
48         # at all
49         elif (  (secflags & SH_FLAGS.SHF_TLS) != 0 and
50                 segtype not in ('PT_TLS', 'PT_PHDR')):
51             return False
52
53         # In ELF_SECTION_IN_SEGMENT_STRICT the flag check_vma is on, so if
54         # this is an alloc section, check whether its VMA is in bounds.
55         if secflags & SH_FLAGS.SHF_ALLOC:
56             secaddr = section['sh_addr']
57             vaddr = self['p_vaddr']
58
59             # This checks that the section is wholly contained in the segment.
60             # The third condition is the 'strict' one - an empty section will
61             # not match at the very end of the segment (unless the segment is
62             # also zero size, which is handled by the second condition).
63             if not (secaddr >= vaddr and
64                     secaddr - vaddr + section['sh_size'] <= self['p_memsz'] and 
65                     secaddr - vaddr <= self['p_memsz'] - 1):
66                 return False
67
68         # If we've come this far and it's a NOBITS section, it's in the segment
69         if sectype == 'SHT_NOBITS':
70             return True
71
72         secoffset = section['sh_offset']
73         poffset = self['p_offset']
74
75         # Same logic as with secaddr vs. vaddr checks above, just on offsets in
76         # the file
77         return (secoffset >= poffset and 
78                 secoffset - poffset + section['sh_size'] <= self['p_filesz'] and
79                 secoffset - poffset <= self['p_filesz'] - 1)
80
81
82 class InterpSegment(Segment):
83     """ INTERP segment. Knows how to obtain the path to the interpreter used
84         for this ELF file.
85     """
86     def __init__(self, header, stream):
87         super(InterpSegment, self).__init__(header, stream)
88
89     def get_interp_name(self):
90         """ Obtain the interpreter path used for this ELF file.
91         """
92         path_offset = self['p_offset']
93         return struct_parse(
94             CString(''),
95             self.stream,
96             stream_pos=path_offset)
97
98