summaryrefslogtreecommitdiff
path: root/tools/libelf/section.py
blob: 34f07a6839a793087538a4b225f3348c6f2993e8 (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import os

from typing import Optional, IO, List

from . import elf
from .util import *

class Section:
    id: int
    header: elf.SectionHeader
    name: Optional[str]
    data: bytearray
    addr: int
    size: int

    def __init__(self, header: elf.SectionHeader):
        self.header = header
        self.name = None
        self.data = None
        self.size = header.sh_size
        self.section = None
        self.addr = None
        self.file_addr = None
        self.alignment = header.sh_addralign
        self.object = None


    def getVirtualAddr(self, offset=0):
        return self.addr + offset

class ProgBitsSection(Section):
    def __init__(self, header: elf.SectionHeader, file: IO):
        super().__init__(header)

        if header.sh_size > 0:
            file.seek(header.sh_offset, os.SEEK_SET)
            self.data = bytearray(file.read(header.sh_size))

class NoBitsSection(Section):
    def __init__(self, header: elf.SectionHeader):
        super().__init__(header)


class StringTableSection(ProgBitsSection):
    def __init__(self, header: elf.SectionHeader, file: IO):
        super().__init__(header, file)

    def readString(self, offset: int) -> Optional[str]:
        return parse_null_string(self.data[offset:])


class SymbolTableSection(Section):
    symbols: List[elf.Symbol]

    def __init__(self, header: elf.SectionHeader, file: IO):
        super().__init__(header)
        self.symbols = []

        if header.sh_entsize != 0x10:
            fail("symtab section: invalid entry size")
        if header.sh_size % header.sh_entsize != 0:
            fail("symtab section: invalid size (not divisible by entry size) ")

        count = header.sh_size // header.sh_entsize
        file.seek(header.sh_offset, os.SEEK_SET)
        for _ in range(count):
            symbol = elf.Symbol()
            symbol.read(file)
            self.symbols.append(symbol)

RELOCATION_NAMES = {
    0x0: "R_PPC_NONE",
    0x1: "R_PPC_ADDR32",
    0x3: "R_PPC_ADDR16",
    0x4: "R_PPC_ADDR16_LO",
    0x5: "R_PPC_ADDR16_HI",
    0x6: "R_PPC_ADDR16_HA",
    0xA: "R_PPC_REL24",
    0xB: "R_PPC_REL14",
    0x18: "R_PPC_UADDR32",
    0x6D: "R_PPC_EMB_SDA21",
}

class RelocationASection(Section):
    relocations: List[elf.RelA]

    def __init__(self, header: elf.SectionHeader, file: IO):
        super().__init__(header)
        self.relocations = []

        if header.sh_entsize != 0x0C:
            fail("relocation section: invalid entry size")
        if header.sh_size % header.sh_entsize != 0:
            fail("relocation section: invalid size (not divisible by entry size) ")

        count = header.sh_size // header.sh_entsize
        file.seek(header.sh_offset, os.SEEK_SET)
        for _ in range(count):
            rela = elf.RelA()
            rela.read(file)
            self.relocations.append(rela)