#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 # -*- coding: utf-8 -*- import struct import re from math import ceil from Utils import Utils from Utils import log_e, log_d # Symbol types STT_NOTYPE = 0 STT_OBJECT = 1 STT_FUNC = 2 STT_SECTION = 3 STT_FILE = 4 STT_COMMON = 5 STT_LOOS = 10 STT_HIOS = 12 STT_LOPROC = 13 STT_SPARC_REGISTER = 13 STT_HIPROC = 15 # Symbol bind STB_LOCAL = 0 STB_GLOBAL = 1 STB_WEAK = 2 STB_LOOS = 10 STB_HIOS = 12 STB_LOPROC = 13 STB_HIPROC = 15 # Symbol visibility STV_DEFAULT = 0 STV_INTERNAL = 1 STV_HIDDEN = 2 STV_PROTECTED = 3 STV_EXPORTED = 4 STV_SINGLETON = 5 STV_ELIMINATE = 6 # defines from /arch/arm64/include/asm/elf.h R_ARM_NONE = 0 R_AARCH64_NONE = 256 # Data. R_AARCH64_ABS64 = 257 R_AARCH64_ABS32 = 258 R_AARCH64_ABS16 = 259 R_AARCH64_PREL64 = 260 R_AARCH64_PREL32 = 261 R_AARCH64_PREL16 = 262 # Instructions. R_AARCH64_MOVW_UABS_G0 = 263 R_AARCH64_MOVW_UABS_G0_NC = 264 R_AARCH64_MOVW_UABS_G1 = 265 R_AARCH64_MOVW_UABS_G1_NC = 266 R_AARCH64_MOVW_UABS_G2 = 267 R_AARCH64_MOVW_UABS_G2_NC = 268 R_AARCH64_MOVW_UABS_G3 = 269 R_AARCH64_MOVW_SABS_G0 = 270 R_AARCH64_MOVW_SABS_G1 = 271 R_AARCH64_MOVW_SABS_G2 = 272 R_AARCH64_LD_PREL_LO19 = 273 R_AARCH64_ADR_PREL_LO21 = 274 R_AARCH64_ADR_PREL_PG_HI21 = 275 R_AARCH64_ADR_PREL_PG_HI21_NC = 276 R_AARCH64_ADD_ABS_LO12_NC = 277 R_AARCH64_LDST8_ABS_LO12_NC = 278 R_AARCH64_TSTBR14 = 279 R_AARCH64_CONDBR19 = 280 R_AARCH64_JUMP26 = 282 R_AARCH64_CALL26 = 283 R_AARCH64_LDST16_ABS_LO12_NC = 284 R_AARCH64_LDST32_ABS_LO12_NC = 285 R_AARCH64_LDST64_ABS_LO12_NC = 286 R_AARCH64_LDST128_ABS_LO12_NC = 299 R_AARCH64_MOVW_PREL_G0 = 287 R_AARCH64_MOVW_PREL_G0_NC = 288 R_AARCH64_MOVW_PREL_G1 = 289 R_AARCH64_MOVW_PREL_G1_NC = 290 R_AARCH64_MOVW_PREL_G2 = 291 R_AARCH64_MOVW_PREL_G2_NC = 292 R_AARCH64_MOVW_PREL_G3 = 293 R_AARCH64_RELATIVE = 1027 SHT_NULL = 0 SHT_PROGBITS = 1 SHT_SYMTAB = 2 SHT_STRTAB = 3 SHT_RELA = 4 SHT_HASH = 5 SHT_DYNAMIC = 6 SHT_NOTE = 7 SHT_NOBITS = 8 SHT_REL = 9 SHT_SHLIB = 10 SHT_DYNSYM = 11 SHT_NUM = 12 ARCH_SHF_SMALL = 0 SHF_WRITE = 0x1 SHF_ALLOC = 0x2 SHF_EXECINSTR = 0x4 SHF_RELA_LIVEPATCH = 0x00100000 SHF_RO_AFTER_INIT = 0x00200000 SHF_MASKPROC = 0xf0000000 DEFAULT_NAME_SECTION_SYMTAB = ".symtab" DEFAULT_NAME_SECTION_SHSTRTAB = ".shstrtab" DEFAULT_NAME_SECTION_STRTAB = ".strtab" DEFAULT_NAME_SECTION_ALTINSTR = ".altinstructions" DEFAULT_RELA_PREFIX = ".rela" DEFAULT_CFI_ENDING = ".__cfi_check" DEFAULT_NAME_SECTION_JUMPTBL = "__jump_table" PREFIX_SECTION_DEBUG = ".debug" CFI_MARKER_NAME_FUNCTION = "__cfi_check" DEFAULT_ARM_INSTRUCTION_LEN = 4 #DEFAULT_RELA_GAP_LEN = 4 SAMPLE_NAME_SECTION_SYMBOL_MARKER = "I_m_section_marker_symbol_" def string_to_bytearray(__string: str): test = bytearray(__string, "utf-8") test.append(0x00) return test def find_pattern(blob, pattern: str): """ return list of offsets """ idx_list = [] idx = 0 while idx != -1: idx = blob[idx: -1].find(pattern) if idx != -1: idx_list.append(idx) idx = idx + 1 return idx_list def remove_prefix(string : str, prefix: str) -> str: if string.startswith(prefix): return string[len(prefix):] return None # support class for altinstructions handling class Sec_Altinstructions_Data: orig_sec_idx = -1 orig_offset = -1 orig_len = -1 alt_sec_idx = -1 alt_offset = -1 alt_len = -1 cpufeature = -1 class Sec_Jumptable_Data: target_sec_idx = -1 target_offset = -1 code = -1 key = -1 class Sec_Symtable_data: st_name = -1 # Symbol name, index in string tbl st_info = -1 # Type and binding attributes st_other = -1 # No defined meaning, 0 st_shndx = -1 # Associated section index st_value = -1 # Value of the symbol st_size = -1 # Associated symbol size sym_name_str = "" # symbol name string class Elf_Section: bin_img = None def __init__(self, img: bytearray): self.bin_img = bytearray(img) def find_bin_pattern(self, byte_pattern): return find_pattern(self.bin_img, byte_pattern) def find_symbols(self, *argv): return def write_img_by_offset(self, offset: int, data: bytearray): self.bin_img[offset: offset + len(data)] = data class Elf64_Rela(Elf_Section): """ typedef struct elf64_rela { Elf64_Addr r_offset; /* Location at which to apply the action */ Elf64_Xword r_info; /* index and type of relocation */ Elf64_Sxword r_addend; /* Constant addend used to compute value */ } Elf64_Rela; """ rela_struct_format = 'QQQ' section = None # list of lists [ target_sec_offset, target_len, ref_sec_idx, ref_sec_offset ] rela_info = None def __init__(self, img: bytearray): super().__init__(img) self.derive_rela_info(img) def derive_rela_info(self, img: bytearray): self.rela_info = [] __rela_struct_size = struct.calcsize(self.rela_struct_format) for i in range(ceil(len(img)/__rela_struct_size)): __begin = i * __rela_struct_size __end = i * __rela_struct_size + __rela_struct_size [ r_offset, r_info, r_addend ] = list(struct.unpack(self.rela_struct_format, self.bin_img[__begin: __end])) __rela_type = r_info & 0x00000000ffffffff __ref_sec_ndx = r_info >> 32 # to be added extra handling __ref_sec_offset = r_addend # to be added extra handling self.rela_info.append([ r_offset, self.get_gap_len(__rela_type), __ref_sec_ndx, __ref_sec_offset]) # Note: here __ref_sec_ndx __ref_sec_offset actually contain # sumbol Num and offset/addent respectively def zeroize_mapping_relocations_info(self, sym_sec): """ rela_info.ref_sec_idx contains section index as number in symbol section rela_info.ref_sec_offset contains offset from the symbol position more convenient to operate direct section index and offset from section zero, the function updates the fields properly """ for __ri in self.rela_info: __ref_sym_idx = __ri[2] __ri[2] = sym_sec.section.get_sec_idx_by_num(__ri[2]) __ri[3] = sym_sec.section.get_sym_offset_by_num(__ref_sym_idx) + __ri[3] # offset of "data source for relocation" from the section zero is # sum of referenced symbol offset and addend def get_section_gaps(self) -> list: ret_list = [] for i in self.rela_info: ret_list.append([i[0], i[1]]) return ret_list def get_full_rela_info(self) -> list: return self.rela_info def get_gap_len(self, rela_type: int) -> int: if rela_type in ( R_AARCH64_MOVW_UABS_G0, R_AARCH64_MOVW_UABS_G0_NC, R_AARCH64_MOVW_UABS_G1, R_AARCH64_MOVW_UABS_G1_NC, R_AARCH64_MOVW_UABS_G2, R_AARCH64_MOVW_UABS_G2_NC, R_AARCH64_MOVW_UABS_G3, R_AARCH64_MOVW_SABS_G0, R_AARCH64_MOVW_SABS_G1, R_AARCH64_MOVW_SABS_G2, R_AARCH64_LD_PREL_LO19, R_AARCH64_ADR_PREL_LO21, R_AARCH64_ADR_PREL_PG_HI21, R_AARCH64_ADR_PREL_PG_HI21_NC, R_AARCH64_ADD_ABS_LO12_NC, R_AARCH64_LDST8_ABS_LO12_NC,R_AARCH64_TSTBR14, R_AARCH64_CONDBR19, R_AARCH64_JUMP26, R_AARCH64_CALL26, R_AARCH64_LDST16_ABS_LO12_NC, R_AARCH64_LDST32_ABS_LO12_NC, R_AARCH64_LDST64_ABS_LO12_NC, R_AARCH64_LDST128_ABS_LO12_NC, R_AARCH64_MOVW_PREL_G0, R_AARCH64_MOVW_PREL_G0_NC, R_AARCH64_MOVW_PREL_G1, R_AARCH64_MOVW_PREL_G1_NC, R_AARCH64_MOVW_PREL_G2, R_AARCH64_MOVW_PREL_G2_NC, R_AARCH64_MOVW_PREL_G3): return 4 if rela_type in ( R_AARCH64_ABS64, R_AARCH64_ABS32, R_AARCH64_ABS16, R_AARCH64_PREL64, R_AARCH64_PREL32, R_AARCH64_PREL16, R_AARCH64_RELATIVE): return 8 return 4 class ELF64_jumptable(Elf_Section): """ __jumptable section item described in jump_label.h struct jump_entry { s32 code; s32 target; long key; // key may be far away from the core kernel under KASLR }; class Sec_Jumptable_Data: target_sec_idx = -1, target_offset = -1 code = -1, key = -1 """ jumptable_struct_format = ' list: ret_list = [] for i in self.jumptable_rec: if i.target_sec_idx == sec_idx: ret_list.append([i.target_offset, DEFAULT_ARM_INSTRUCTION_LEN]) return ret_list class Elf64_altinstructions(Elf_Section): """ .altinstructions section contains an array of struct alt_instr. As instance, for kernel 4.14 from /arch/arm64/include/asm/alternative.h struct alt_instr { s32 orig_offset; /* offset to original instruction */ s32 alt_offset; /* offset to replacement instruction */ u16 cpufeature; /* cpufeature bit set for replacement */ u8 orig_len; /* size of original instruction(s) */ u8 alt_len; /* size of new instruction(s), <= orig_len */ }; class section_altinstructions_data: orig_sec_idx = -1, orig_offset = -1, orig_len = -1, alt_sec_idx = -1, alt_offset = -1, alt_len = -1, cpufeature = -1 """ altinstructions_struct_format = ' list: ret_list = [] for _, value in self.altinstruction_rec.items(): if value.orig_sec_idx == sec_idx: ret_list.append([value.orig_offset, value.orig_len]) return ret_list class Elf64_Sym(Elf_Section): """ structure mappinng based on /include/uapi/linux/elf.h typedef struct elf64_sym { Elf64_Word st_name; /* Symbol name, index in string tbl */ unsigned char st_info; /* Type and binding attributes */ unsigned char st_other; /* No defined meaning, 0 */ Elf64_Half st_shndx; /* Associated section index */ Elf64_Addr st_value; /* Value of the symbol */ Elf64_Xword st_size; /* Associated symbol size */ } Elf64_Sym; """ str_sym_table_format = 'IBBHQQ' section = None syms = None # list of instances of Sec_Symtable_data def __init__(self, img: bytearray): self.syms = [] super().__init__(img) def find_symbols(self, strtab: bytearray): __struct_size = struct.calcsize(self.str_sym_table_format) for i in range(int(len(self.bin_img)/__struct_size)): __temp_sym = Sec_Symtable_data() [ __temp_sym.st_name, __temp_sym.st_info, __temp_sym.st_other, __temp_sym.st_shndx, __temp_sym.st_value, __temp_sym.st_size ] = list(struct.unpack(self.str_sym_table_format, self.bin_img[i * __struct_size: i * __struct_size + __struct_size])) __temp_sym.sym_name_str = strtab[__temp_sym.st_name:].split(b'\x00')[0].decode("utf-8") # look at specific section symbols if __temp_sym.st_info == STT_SECTION: __temp_sym.sym_name_str = SAMPLE_NAME_SECTION_SYMBOL_MARKER + str(__temp_sym.st_shndx) # look at mapping symbols $x $d $t ... which can be # met several times in the same section if (__temp_sym.sym_name_str.startswith('$x') or __temp_sym.sym_name_str.startswith('$d') or __temp_sym.sym_name_str.startswith('$t') or __temp_sym.sym_name_str.startswith('$a') or __temp_sym.sym_name_str.startswith('$v')): __temp_sym.sym_name_str = __temp_sym.sym_name_str + "_sec_" + str(__temp_sym.st_shndx) uniq_id = 0 while __temp_sym.sym_name_str + "_" + str(uniq_id) in (_l.sym_name_str for _l in self.syms): uniq_id = uniq_id + 1 __temp_sym.sym_name_str = __temp_sym.sym_name_str + "_" + str(uniq_id) self.syms.append(__temp_sym) self.show_class_content() def lookup_symbol_name(self, sym_name_pattern: str) -> list: ret_lst = [] __r = re.compile(sym_name_pattern) for _l in self.syms: if len(__r.findall(_l.sym_name_str)) > 0: ret_lst.append(_l.sym_name_str) # to provide original symbol name at the list head, sort it return sorted(ret_lst) def get_sym_by_name(self, sym_name: str): for _l in self.syms: if _l.sym_name_str == sym_name: return _l return None def get_sym_offset_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_value def get_sec_idx_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_shndx def get_sym_size_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_size def get_sym_type_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_info & 0x0f def get_sym_bind_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_info >> 4 def get_sym_vis_by_name(self, sym_name: str) -> int: return self.get_sym_by_name(sym_name).st_other & 0x03 def get_sec_idx_by_num(self, num: int) -> int: return self.syms[num].st_shndx def get_sym_offset_by_num(self, num: int) -> int: return self.syms[num].st_value def get_all_sym_names_by_sec_idx(self, sec_idx: int) -> list: return [ __item.sym_name_str for __item in self.syms if __item.st_shndx == sec_idx ] def show_class_content(self): log_d(" Symbols -------- ") for i, _l in zip(range(len(self.syms)), self.syms): log_d(" {:4} {:65} {:6} {:6} {:6} {:6} {:10} {:6}".format( i, _l.sym_name_str, hex(_l.st_name), hex(_l.st_info), hex(_l.st_other), hex(_l.st_shndx), hex(_l.st_value), hex(_l.st_size))) class Elf64_Shdr: """ structure mappinng based on /include/uapi/linux/elf.h or general ELF specification """ shdr_struct_format = 'IIQQQQIIQQ' section = None section_name_str = None section_gaps = None section_is_init = False def __init__(self, shdr_img): self.section_gaps = [] sh_struct_len = struct.calcsize(Elf64_Shdr.shdr_struct_format) [ self.sh_name, self.sh_type, self.sh_flags, self.sh_addr, self.sh_offset, self.sh_size, self.sh_link, self.sh_info, self.sh_addralign, self.sh_entsize ] = list(struct.unpack(self.shdr_struct_format, shdr_img[0: sh_struct_len])) def sh_set_name(self, sh_strtab_sec: bytearray): __name = sh_strtab_sec[self.sh_name:].split(b'\x00') self.section_name_str = __name[0].decode() def sh_populate(self, sec_bin: bytearray): if self.sh_type == SHT_SYMTAB: self.section = Elf64_Sym(sec_bin) elif self.sh_type == SHT_RELA: self.section = Elf64_Rela(sec_bin) elif self.section_name_str == DEFAULT_NAME_SECTION_ALTINSTR: self.section = Elf64_altinstructions(sec_bin) elif self.section_name_str == DEFAULT_NAME_SECTION_JUMPTBL: self.section = ELF64_jumptable(sec_bin) else: self.section = Elf_Section(sec_bin) def sh_find_symbols(self, img_strtab: bytearray): self.section.find_symbols(img_strtab) def get_all_sym_names_by_sec_idx(self, sec_idx: int) -> list: return self.section.get_all_sym_names_by_sec_idx(sec_idx) def get_section_gaps(self) -> list: return self.section.get_section_gaps() def get_type(self): return self.sh_type def get_flags(self): return self.sh_flags def sh_lookup_symbol_name(self, sym_name_pattern : str) -> list: return self.section.lookup_symbol_name(sym_name_pattern) class Elf64_Ehdr: """ typedef struct elf64_hdr { unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; /* Entry point virtual address */ Elf64_Off e_phoff; /* Program header table file offset */ Elf64_Off e_shoff; /* Section header table file offset */ Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr; """ ehdr_struct_format = '16shhIQQQIhhhhhh' def __init__(self, img): __elf_hdr_len = struct.calcsize(self.ehdr_struct_format) [ self.e_ident, self.e_type, self.e_machine, self.e_version, self.e_entry, self.e_phoff, self.e_shoff, self.e_flags, self.e_ehsize, self.e_phentsize, self.e_phnum, self.e_shentsize, self.e_shnum, self.e_shstrndx ] = list(struct.unpack(self.ehdr_struct_format, img[0: __elf_hdr_len])) log_d("\tSection headers num : {}".format(self.e_shnum)) class ELF: elf_file_name = None binary_img = None ehdr = None shdr = None def __init__(self, file_name): self.shdr = [] self.elf_file_name = file_name with open(file_name, "rb") as file: self.binary_img = file.read() self.ehdr = Elf64_Ehdr(self.binary_img) __sh_off = self.ehdr.e_shoff for _ in range(0, self.ehdr.e_shnum): __shdr = Elf64_Shdr(self.binary_img[__sh_off: __sh_off + self.ehdr.e_shentsize]) __sh_off = __sh_off + self.ehdr.e_shentsize self.shdr.append(__shdr) # section names and sections data self.find_section_names() for __sh in self.shdr: __sh.sh_populate(self.binary_img[__sh.sh_offset: __sh.sh_offset + __sh.sh_size]) # symbols __strtab = self.get_section_by_name(DEFAULT_NAME_SECTION_STRTAB) for __sh in self.shdr: __sh.sh_find_symbols(__strtab.section.bin_img) # alternation instructions self.apply_relocation_for_alternation_instructions() # jumptable self.apply_relocation_for_jumptable_instructions() def calc_syms_info(self): __strtab = self.get_section_by_name(DEFAULT_NAME_SECTION_STRTAB) for __shdr in self.shdr: __shdr.calc_syms_info(__strtab) def find_section_names(self): __str_offset_sechdr_lst = [] for __shdr in self.shdr: if __shdr.sh_type == SHT_STRTAB: __start_bin_idx = __shdr.sh_offset __end_bin_idx = __shdr.sh_offset + __shdr.sh_size __temp_lst = find_pattern(self.binary_img[__start_bin_idx: __end_bin_idx], string_to_bytearray(DEFAULT_NAME_SECTION_SHSTRTAB)) if len(__temp_lst) > 0: __str_offset_sechdr_lst.append([__shdr, __temp_lst]) if len(__str_offset_sechdr_lst) != 1 or len(__str_offset_sechdr_lst[0][1]) != 1: for __shdr in self.shdr: if __shdr.sh_type == SHT_STRTAB: __start_bin_idx = __shdr.sh_offset __end_bin_idx = __shdr.sh_offset + __shdr.sh_size __temp_lst = find_pattern(self.binary_img[__start_bin_idx: __end_bin_idx], string_to_bytearray(DEFAULT_NAME_SECTION_STRTAB)) if len(__temp_lst) > 0: __str_offset_sechdr_lst.append([__shdr, __temp_lst]) if len(__str_offset_sechdr_lst) != 1 or len(__str_offset_sechdr_lst[0][1]) != 1: log_e(" ERROR: something wrong with section name string search ") raise RuntimeError __sh_strtab = __str_offset_sechdr_lst[0][0] for __shdr in self.shdr: __shdr.sh_set_name(self.binary_img[__sh_strtab.sh_offset: __sh_strtab.sh_offset + __sh_strtab.sh_size ]) def get_section_by_name(self, name: str) -> Elf64_Shdr: for i in self.shdr: if i.section_name_str == name: return i return None def get_section_idx_by_name(self, name: str) -> int: idx = 0 for i in self.shdr: if i.section_name_str == name: return idx idx = idx + 1 return idx def get_rela_gaps_for_section(self, sec_name: str) -> list: ret_list = [] rela_prefix = DEFAULT_RELA_PREFIX + sec_name for __sec in self.shdr: if __sec.section_name_str.startswith(rela_prefix): ret_list = ret_list + __sec.get_section_gaps() return ret_list def get_altinstr_gaps_for_section(self, sec_name: str) -> list: altinstr_sec = self.get_section_by_name(DEFAULT_NAME_SECTION_ALTINSTR) if altinstr_sec is None: return [] __sec_idx = self.get_section_idx_by_name(sec_name) return altinstr_sec.section.get_altinst_gaps_for_section_idx(__sec_idx) def get_jump_table_gaps_for_section(self, sec_name: str) -> list: jumptbl_sec = self.get_section_by_name(DEFAULT_NAME_SECTION_JUMPTBL) if jumptbl_sec is None: return [] __sec_idx = self.get_section_idx_by_name(sec_name) return jumptbl_sec.section.get_jumptable_gaps_for_section_idx(__sec_idx) def get_section_owner_of_sym(self, sym_name: str) -> Elf64_Shdr: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) __sh_idx = __sec_hdr.section.get_sec_idx_by_name(sym_name) return self.shdr[__sh_idx] def get_sections_all_names(self) -> list: ret_list = [] for i in self.shdr: ret_list.append(i.section_name_str) return ret_list def get_all_sym_names_by_sec_idx(self, sec_idx: int) -> list: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.get_all_sym_names_by_sec_idx(sec_idx) def get_symbol_offset_in_sec(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.section.get_sym_offset_by_name(sym_name) def get_symbol_by_voluntary_search(self, sym_name_pattern: str) -> list: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.sh_lookup_symbol_name(sym_name_pattern) def get_symbol_size(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.section.get_sym_size_by_name(sym_name) def get_symbol_type(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.section.get_sym_type_by_name(sym_name) def get_symbol_vis(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.section.get_sym_vis_by_name(sym_name) def get_symbol_bind(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) return __sec_hdr.section.get_sym_bind_by_name(sym_name) def get_section_size_where_sym_lives(self, sym_name: str) -> int: __sec_hdr = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) __sh_idx = __sec_hdr.section.get_sec_idx_by_name(sym_name) return self.shdr[__sh_idx].sh_size def get_symbol_offset_from_elf_begin(self, sym_name: str) -> int: __sec_hdr = self.get_section_owner_of_sym(sym_name) symbol_offset_in_sec = self.get_symbol_offset_in_sec(sym_name) section_ofset_in_file = __sec_hdr.sh_offset return symbol_offset_in_sec + section_ofset_in_file def write_symbol_value(self, sym_name: str, data: bytearray): # write to section img __sec_offset = self.get_symbol_offset_in_sec(sym_name) __sec_sym_owner = self.get_section_owner_of_sym(sym_name) __sec_sym_owner.section.write_img_by_offset(__sec_offset, data) __file_offset = self.get_symbol_offset_from_elf_begin(sym_name) Utils().file_write_data(self.elf_file_name, data, __file_offset) def apply_relocation_for_alternation_instructions(self): """ Should poppulate instance of class Elf64_altinstructions with data """ altinstr_sec = self.get_section_by_name(DEFAULT_NAME_SECTION_ALTINSTR) if altinstr_sec is None: return self.apply_relocations_for_section(altinstr_sec) altinstr_sec.section.show_class_content() def apply_relocation_for_jumptable_instructions(self): """ Should poppulate instance of class Elf64_jumptable with data: """ jumptable_sec = self.get_section_by_name(DEFAULT_NAME_SECTION_JUMPTBL) if jumptable_sec is None: return self.apply_relocations_for_section(jumptable_sec) jumptable_sec.section.show_class_content() def apply_relocations_for_section(self, target_sec): rela_info = None rela_target_sec = self.get_section_by_name(DEFAULT_RELA_PREFIX + target_sec.section_name_str) if rela_target_sec is not None: symtab_sec = self.get_section_by_name(DEFAULT_NAME_SECTION_SYMTAB) rela_target_sec.section.zeroize_mapping_relocations_info(symtab_sec) # rela info list of lists [ dest_sec_offset, dest_len, src_sec_idx, src_sec_offset ] rela_info = rela_target_sec.section.get_full_rela_info() # fill target section records for __rela_item in rela_info: offset_to_wr = __rela_item[0] sec_idx = __rela_item[2] sec_offset = __rela_item[3] target_sec.section.set_records_value_by_offset(offset_to_wr, sec_idx, sec_offset)