tp/tools/libelf/section.py

103 lines
2.8 KiB
Python

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)