class ELFWriter: def __init__(self, output_path, abi, input_path=None): from peachpy.formats.elf.image import Image from peachpy.formats.elf.section import TextSection, ReadOnlyDataSection self.output_path = output_path self.previous_writer = None self.abi = abi self.image = Image(abi, input_path) self.text_section = TextSection() self.image.add_section(self.text_section) self.text_rela_section = None self.rodata_section = None def __enter__(self): global active_writer self.previous_writer = active_writer active_writer = self self.output_file = open(self.output_path, "w", buffering=0) return self def __exit__(self, exc_type, exc_value, traceback): global active_writer active_writer = self.previous_writer self.previous_writer = None if exc_type is None: self.output_file.write(self.image.as_bytearray) self.output_file.close() self.output_file = None else: import os os.unlink(self.output_file.name) self.output_file = None raise def add_function(self, function): import peachpy.x86_64.function from peachpy.util import roundup assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be bindinded to an ABI before its assembly can be used" encoded_function = function.encode() code_offset = len(self.text_section.content) code_padding = bytearray([encoded_function.code_section.alignment_byte] * (roundup(code_offset, encoded_function.code_section.alignment) - code_offset)) self.text_section.content += code_padding code_offset += len(code_padding) self.text_section.content += encoded_function.code_section.content self.text_section.alignment = max(self.text_section.alignment, encoded_function.code_section.alignment) const_offset = 0 if encoded_function.const_section.content: if self.rodata_section is None: from peachpy.formats.elf.section import ReadOnlyDataSection self.rodata_section = ReadOnlyDataSection() self.image.add_section(self.rodata_section) const_offset = self.rodata_section.get_content_size(self.abi) const_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(const_offset, encoded_function.const_section.alignment) - const_offset)) self.rodata_section.content += const_padding const_offset += len(const_padding) self.rodata_section.content += encoded_function.const_section.content self.rodata_section.alignment = max(self.rodata_section.alignment, encoded_function.const_section.alignment) # Map from symbol name to symbol index from peachpy.formats.elf.symbol import Symbol, SymbolBinding, SymbolType symbol_map = dict() for symbol in encoded_function.const_section.symbols: const_symbol = Symbol() const_symbol.name = symbol.name const_symbol.value = const_offset + symbol.offset const_symbol.size = symbol.size const_symbol.section = self.rodata_section const_symbol.binding = SymbolBinding.local const_symbol.type = SymbolType.data_object self.image.symtab.add(const_symbol) symbol_map[symbol] = const_symbol if encoded_function.code_section.relocations: if self.text_rela_section is None: from peachpy.formats.elf.section import RelocationsWithAddendSection self.text_rela_section = RelocationsWithAddendSection(self.text_section, self.image.symtab) self.image.add_section(self.text_rela_section) from peachpy.formats.elf.symbol import RelocationWithAddend, RelocationType for relocation in encoded_function.code_section.relocations: elf_relocation = RelocationWithAddend(RelocationType.x86_64_pc32, relocation.offset, symbol_map[relocation.symbol], -4) self.text_rela_section.add(elf_relocation) function_symbol = Symbol() function_symbol.name = function.name function_symbol.value = code_offset function_symbol.content_size = len(encoded_function.code_section) function_symbol.section = self.text_section function_symbol.binding = SymbolBinding.global_ function_symbol.type = SymbolType.function self.image.symtab.add(function_symbol)
class ELFWriter(ImageWriter): def __init__(self, output_path, abi, input_path=None): super(ELFWriter, self).__init__(output_path) from peachpy.formats.elf.image import Image from peachpy.formats.elf.section import TextSection, ProgramBitsSection self.abi = abi self.image = Image(abi, input_path) self.text_section = TextSection() self.image.add_section(self.text_section) self.gnu_stack_section = ProgramBitsSection(".note.GNU-stack", allocate=False) self.image.add_section(self.gnu_stack_section) self.text_rela_section = None self.rodata_section = None def encode(self): return self.image.as_bytearray def add_function(self, function): import peachpy.x86_64.function from peachpy.util import roundup assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be finalized with an ABI before its assembly can be used" encoded_function = function.encode() code_offset = len(self.text_section.content) code_padding = bytearray([encoded_function.code_section.alignment_byte] * (roundup(code_offset, encoded_function.code_section.alignment) - code_offset)) self.text_section.content += code_padding code_offset += len(code_padding) self.text_section.content += encoded_function.code_section.content self.text_section.alignment = max(self.text_section.alignment, encoded_function.code_section.alignment) const_offset = 0 if encoded_function.const_section.content: if self.rodata_section is None: from peachpy.formats.elf.section import ReadOnlyDataSection self.rodata_section = ReadOnlyDataSection() self.image.add_section(self.rodata_section) const_offset = self.rodata_section.get_content_size(self.abi) const_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(const_offset, encoded_function.const_section.alignment) - const_offset)) self.rodata_section.content += const_padding const_offset += len(const_padding) self.rodata_section.content += encoded_function.const_section.content self.rodata_section.alignment = max(self.rodata_section.alignment, encoded_function.const_section.alignment) # Map from symbol name to symbol index from peachpy.formats.elf.symbol import Symbol, SymbolBinding, SymbolType symbol_map = dict() for symbol in encoded_function.const_section.symbols: const_symbol = Symbol() const_symbol.name = function.mangled_name + "." + symbol.name const_symbol.value = const_offset + symbol.offset const_symbol.size = symbol.size const_symbol.section = self.rodata_section const_symbol.binding = SymbolBinding.local const_symbol.type = SymbolType.data_object self.image.symtab.add(const_symbol) symbol_map[symbol] = const_symbol if encoded_function.code_section.relocations: if self.text_rela_section is None: from peachpy.formats.elf.section import RelocationsWithAddendSection self.text_rela_section = RelocationsWithAddendSection(self.text_section, self.image.symtab) self.image.add_section(self.text_rela_section) from peachpy.formats.elf.symbol import RelocationWithAddend, RelocationType for relocation in encoded_function.code_section.relocations: elf_relocation = RelocationWithAddend(RelocationType.x86_64_pc32, code_offset + relocation.offset, symbol_map[relocation.symbol], relocation.offset - relocation.program_counter) self.text_rela_section.add(elf_relocation) function_symbol = Symbol() function_symbol.name = function.mangled_name function_symbol.value = code_offset function_symbol.content_size = len(encoded_function.code_section) function_symbol.section = self.text_section function_symbol.binding = SymbolBinding.global_ function_symbol.type = SymbolType.function self.image.symtab.add(function_symbol)
class ELFWriter(ImageWriter): def __init__(self, output_path, abi, input_path=None): super(ELFWriter, self).__init__(output_path) from peachpy.formats.elf.image import Image from peachpy.formats.elf.section import TextSection self.abi = abi self.image = Image(abi, input_path) self.text_section = TextSection() self.image.add_section(self.text_section) self.text_rela_section = None self.rodata_section = None def encode(self): return self.image.as_bytearray def add_function(self, function): import peachpy.x86_64.function from peachpy.util import roundup assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be finalized with an ABI before its assembly can be used" encoded_function = function.encode() code_offset = len(self.text_section.content) code_padding = bytearray([encoded_function.code_section.alignment_byte] * (roundup(code_offset, encoded_function.code_section.alignment) - code_offset)) self.text_section.content += code_padding code_offset += len(code_padding) self.text_section.content += encoded_function.code_section.content self.text_section.alignment = max(self.text_section.alignment, encoded_function.code_section.alignment) const_offset = 0 if encoded_function.const_section.content: if self.rodata_section is None: from peachpy.formats.elf.section import ReadOnlyDataSection self.rodata_section = ReadOnlyDataSection() self.image.add_section(self.rodata_section) const_offset = self.rodata_section.get_content_size(self.abi) const_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(const_offset, encoded_function.const_section.alignment) - const_offset)) self.rodata_section.content += const_padding const_offset += len(const_padding) self.rodata_section.content += encoded_function.const_section.content self.rodata_section.alignment = max(self.rodata_section.alignment, encoded_function.const_section.alignment) # Map from symbol name to symbol index from peachpy.formats.elf.symbol import Symbol, SymbolBinding, SymbolType symbol_map = dict() for symbol in encoded_function.const_section.symbols: const_symbol = Symbol() const_symbol.name = function.mangled_name + "." + symbol.name const_symbol.value = const_offset + symbol.offset const_symbol.size = symbol.size const_symbol.section = self.rodata_section const_symbol.binding = SymbolBinding.local const_symbol.type = SymbolType.data_object self.image.symtab.add(const_symbol) symbol_map[symbol] = const_symbol if encoded_function.code_section.relocations: if self.text_rela_section is None: from peachpy.formats.elf.section import RelocationsWithAddendSection self.text_rela_section = RelocationsWithAddendSection(self.text_section, self.image.symtab) self.image.add_section(self.text_rela_section) from peachpy.formats.elf.symbol import RelocationWithAddend, RelocationType for relocation in encoded_function.code_section.relocations: elf_relocation = RelocationWithAddend(RelocationType.x86_64_pc32, code_offset + relocation.offset, symbol_map[relocation.symbol], relocation.offset - relocation.program_counter) self.text_rela_section.add(elf_relocation) function_symbol = Symbol() function_symbol.name = function.mangled_name function_symbol.value = code_offset function_symbol.content_size = len(encoded_function.code_section) function_symbol.section = self.text_section function_symbol.binding = SymbolBinding.global_ function_symbol.type = SymbolType.function self.image.symtab.add(function_symbol)