File: symbol.py

package info (click to toggle)
python-peachpy 0.0~git20211013.257881e-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 2,452 kB
  • sloc: python: 29,286; ansic: 54; makefile: 44; cpp: 31
file content (136 lines) | stat: -rw-r--r-- 4,746 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
#    See license.rst for the full text of the license.


from enum import IntEnum


class StorageClass(IntEnum):
    """
    External symbol. If section number is undefined (0), value specifies symbol size. Otherwise value specifies offset
    within section.
    """
    external = 2

    """Static symbol. value specifies offset within section. value of 0 means that symbol represents section name."""
    static = 3

    """A function .bf (beginning of function), .ef (end of function) or .lf (lines in function record) """
    function = 101
    """Source-file symbol record. Followed by auxiliary records that name the file"""
    file = 103


class SymbolType(IntEnum):
    non_function = 0
    function = 0x20


class Symbol:
    entry_size = 18

    def __init__(self):
        # Name of the symbol
        self.name = None
        # Value of the symbol. Interpretation depends on section_index and storage_class
        self.value = None
        # Relevant section
        self.section = None
        # Symbol type. Microsoft tools use only 0x20 (function) or 0x0 (not a function)
        self.symbol_type = None
        # Storage class
        self.storage_class = None

    def encode_entry(self, encoder, name_index_map, section_index_map):
        from peachpy.encoder import Encoder
        assert isinstance(encoder, Encoder)

        try:
            name_8_bytes = encoder.fixed_string(self.name, 8)
        except ValueError:
            name_index = name_index_map[self.name]
            name_8_bytes = encoder.uint32(0) + encoder.uint32(name_index)
        section_index = section_index_map[self.section]
        auxiliary_entries = 0
        return name_8_bytes + \
            encoder.uint32(self.value) + \
            encoder.uint16(section_index) + \
            encoder.uint16(self.symbol_type) + \
            encoder.uint8(self.storage_class) + \
            encoder.uint8(auxiliary_entries)


class RelocationType(IntEnum):
    # Relocation is ignored
    absolute = 0

    # 32-bit address
    x86_address32 = 6
    # 32-bit offset relative to image base
    x86_imagebase_offset32 = 7
    # 16-bit section index
    x86_section_index = 10
    # 32-bit offset relative to the section
    x86_section_offset32 = 11
    # CLR token
    x86_clr_token = 12
    # Unsigned 7-bit offset relative to the section
    x86_section_offset7 = 13
    # 32-bit offset relative to the end of relocation
    x86_relocation_offset32 = 14

    # 64-bit address
    x86_64_address64 = 1
    # 32-bit address
    x86_64_address32 = 2
    # 32-bit offset relative to image base
    x86_64_imagebase_offset32 = 3
    # 32-bit offset relative to the end of relocation
    x86_64_relocation_offset32 = 4
    # 32-bit offset relative to the end of relocation + 1 byte
    x86_64_relocation_plus_1_offset32 = 5
    # 32-bit offset relative to the end of relocation + 2 bytes
    x86_64_relocation_plus_2_offset32 = 6
    # 32-bit offset relative to the end of relocation + 3 bytes
    x86_64_relocation_plus_3_offset32 = 7
    # 32-bit offset relative to the end of relocation + 4 bytes
    x86_64_relocation_plus_4_offset32 = 8
    # 32-bit offset relative to the end of relocation + 5 bytes
    x86_64_relocation_plus_5_offset32 = 9
    # 16-bit section index
    x86_64_section_index = 10
    # 32-bit offset relative to the section
    x86_64_section_offset32 = 11
    # Unsigned 7-bit offset relative to the section
    x86_64_section_offset7 = 12
    # CLR token
    x86_64_clr_token = 13


class Relocation:
    entry_size = 10

    def __init__(self, type, offset, symbol):
        from peachpy.util import is_int, is_uint32
        if not isinstance(type, RelocationType):
            raise TypeError("Relocation type %s is not in RelocationType enumeration" % str(type))
        if not is_int(offset):
            raise TypeError("Offset %s is not an integer" % str(offset))
        if not is_uint32(offset):
            raise ValueError("Offset %d can not be represented as a 32-bit unsigned integer" % offset)
        if not isinstance(symbol, Symbol):
            raise TypeError("Symbol %s is not an instance of Symbol type" % str(symbol))

        self.type = type
        self.offset = offset
        self.symbol = symbol

    def encode_entry(self, encoder, symbol_index_map, section_address=0):
        import peachpy.encoder
        assert isinstance(encoder, peachpy.encoder.Encoder)
        assert self.symbol in symbol_index_map

        symbol_index = symbol_index_map[self.symbol]
        return encoder.uint32(section_address + self.offset) + \
            encoder.uint32(symbol_index) + \
            encoder.uint16(self.type)