summaryrefslogtreecommitdiff
path: root/tools/libdol2asm/data/section.py
blob: 84b6e8110507891aababd5713c6253ef468b3c14 (plain)
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

from typing import List, Dict, Tuple
from dataclasses import dataclass, field
from .symbol import *

@dataclass
class ExecutableSection:
    name: str
    addr: int
    size: int
    base_addr: int
    data: bytearray = field(repr=False)
    code_segments: List[Tuple[int,int]] = field(default_factory=list)
    relocations: Dict[int, "relib.Relocation"] = field(default_factory=dict,repr=False)
    first_padding: int = 0
    offset_padding: int = 0
    alignment: int = 4

    @property
    def start(self):
        return self.addr

    @property
    def end(self):
        return self.addr + self.size

    @property
    def is_code(self):
        return len(self.code_segments) > 0

    def __contains__(self, addr):
        return addr >= self.start and addr < self.end
        
@dataclass
class Section:
    name: str
    addr: int
    size: int
    data: bytearray = field(repr=False)
    symbols: List[Symbol] = field(default_factory=list, repr=False)
    relocations: Dict[int, "Relocation"] = field(
        default_factory=dict, repr=False)
    base_addr: int = None
    index: int = None
    offset: int = None
    alignment: int = 4

    @property
    def start(self):
        return self.addr

    @property
    def end(self):
        return self.addr + self.size

    def get_data(self, start, end):
        assert start >= self.start
        assert end <= self.end
        return self.data[start - self.start:end - self.start]

    def data_for_symbol(self, symbol):
        return self.get_data(symbol.start, symbol.end)

    def add_symbol(self, symbol: Symbol):
        self.symbols.append(symbol)

    def replace_symbol(self, old: Symbol, new: Symbol):
        new.section = self
        for i, sym in enumerate(self.symbols):
            if sym == old:
                self.symbols[i] = new
                return

        assert False

    def relocations_in_range(self, symbol_table, start, end):
        symbols = set()
        for addr, relocation in self.relocations.items():
            if addr < start or addr >= end:
                continue

            access_addr, symbol = symbol_table[-1, relocation, addr]
            symbols.add(symbol)
        return symbols