def add_function(self, function): import peachpy.x86_64.function assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be bindinded to an ABI before its assembly can be used" from peachpy.util import roundup from peachpy.formats.mscoff import Symbol, SymbolType, StorageClass, Relocation, RelocationType 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)) 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) rdata_offset = self.rdata_section.content_size rdata_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(rdata_offset, encoded_function.const_section.alignment) - rdata_offset)) self.rdata_section.content += rdata_padding rdata_offset += len(rdata_padding) self.rdata_section.content += encoded_function.const_section.content self.rdata_section.alignment = \ max(self.rdata_section.alignment, encoded_function.const_section.alignment) # Map from PeachPy symbol to Mach-O symbol symbol_map = dict() for symbol in encoded_function.const_section.symbols: mscoff_symbol = Symbol() mscoff_symbol.name = symbol.name mscoff_symbol.value = rdata_offset + symbol.offset mscoff_symbol.section = self.rdata_section mscoff_symbol.symbol_type = SymbolType.non_function mscoff_symbol.storage_class = StorageClass.static self.image.add_symbol(mscoff_symbol) symbol_map[symbol] = mscoff_symbol for relocation in encoded_function.code_section.relocations: relocation_type_map = { 4: RelocationType.x86_64_relocation_offset32, 5: RelocationType.x86_64_relocation_plus_1_offset32, 6: RelocationType.x86_64_relocation_plus_2_offset32, 7: RelocationType.x86_64_relocation_plus_3_offset32, 8: RelocationType.x86_64_relocation_plus_4_offset32, 9: RelocationType.x86_64_relocation_plus_5_offset32 } relocation_type = relocation_type_map[relocation.program_counter - relocation.offset] mscoff_relocation = Relocation(relocation_type, code_offset + relocation.offset, symbol_map[relocation.symbol]) self.text_section.relocations.append(mscoff_relocation) function_symbol = Symbol() function_symbol.name = function.name function_symbol.value = code_offset function_symbol.section = self.text_section function_symbol.symbol_type = SymbolType.function function_symbol.storage_class = StorageClass.external self.image.add_symbol(function_symbol)
def add_function(self, function): import peachpy.x86_64.function assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be finalized with an ABI before its assembly can be used" from peachpy.formats.macho.symbol import Symbol, SymbolType, SymbolDescription, SymbolVisibility, \ Relocation, RelocationType from peachpy.util import roundup encoded_function = function.encode() code_offset = len(self.image.text_section.content) code_padding = bytearray([encoded_function.code_section.alignment_byte] * (roundup(code_offset, encoded_function.code_section.alignment) - code_offset)) self.image.text_section.content += code_padding code_offset += len(code_padding) self.image.text_section.content += encoded_function.code_section.content self.image.text_section.alignment = \ max(self.image.text_section.alignment, encoded_function.code_section.alignment) const_offset = self.image.const_section.content_size const_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(const_offset, encoded_function.const_section.alignment) - const_offset)) self.image.const_section.content += const_padding const_offset += len(const_padding) self.image.const_section.content += encoded_function.const_section.content self.image.const_section.alignment = \ max(self.image.const_section.alignment, encoded_function.const_section.alignment) # Map from PeachPy symbol to Mach-O symbol symbol_map = dict() for symbol in encoded_function.const_section.symbols: macho_symbol = Symbol("_" + function.mangled_name + "." + symbol.name, SymbolType.section_relative, self.image.const_section, const_offset + symbol.offset) macho_symbol.description = SymbolDescription.defined self.image.symbol_table.add_symbol(macho_symbol) symbol_map[symbol] = macho_symbol for relocation in encoded_function.code_section.relocations: macho_relocation = Relocation(RelocationType.x86_64_signed, code_offset + relocation.offset, 4, symbol_map[relocation.symbol], is_pc_relative=True) relocation_addend = relocation.offset + 4 - relocation.program_counter if relocation_addend != 0: self.image.text_section.content[code_offset + relocation.offset] = relocation_addend & 0xFF self.image.text_section.content[code_offset + relocation.offset + 1] = (relocation_addend >> 8) & 0xFF self.image.text_section.content[code_offset + relocation.offset + 2] = (relocation_addend >> 16) & 0xFF self.image.text_section.content[code_offset + relocation.offset + 3] = (relocation_addend >> 24) & 0xFF self.image.text_section.relocations.append(macho_relocation) function_symbol = Symbol("_" + function.mangled_name, SymbolType.section_relative, self.image.text_section, value=code_offset) function_symbol.description = SymbolDescription.defined function_symbol.visibility = SymbolVisibility.external self.image.symbol_table.add_symbol(function_symbol)
def add_function(self, function): import peachpy.x86_64.function assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be bindinded to an ABI before its assembly can be used" from peachpy.formats.macho.symbol import Symbol, SymbolType, SymbolDescription, SymbolVisibility, \ Relocation, RelocationType from peachpy.util import roundup encoded_function = function.encode() code_offset = len(self.image.text_section.content) code_padding = bytearray([encoded_function.code_section.alignment_byte] * (roundup(code_offset, encoded_function.code_section.alignment) - code_offset)) self.image.text_section.content += code_padding code_offset += len(code_padding) self.image.text_section.content += encoded_function.code_section.content self.image.text_section.alignment = \ max(self.image.text_section.alignment, encoded_function.code_section.alignment) const_offset = self.image.const_section.content_size const_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(const_offset, encoded_function.const_section.alignment) - const_offset)) self.image.const_section.content += const_padding const_offset += len(const_padding) self.image.const_section.content += encoded_function.const_section.content self.image.const_section.alignment = \ max(self.image.const_section.alignment, encoded_function.const_section.alignment) # Map from PeachPy symbol to Mach-O symbol symbol_map = dict() for symbol in encoded_function.const_section.symbols: macho_symbol = Symbol("_" + function.name + "." + symbol.name, SymbolType.section_relative, self.image.const_section, const_offset + symbol.offset) macho_symbol.description = SymbolDescription.defined self.image.symbol_table.add_symbol(macho_symbol) symbol_map[symbol] = macho_symbol for relocation in encoded_function.code_section.relocations: macho_relocation = Relocation(RelocationType.x86_64_signed, code_offset + relocation.offset, 4, symbol_map[relocation.symbol], is_pc_relative=True) relocation_addend = relocation.offset + 4 - relocation.program_counter if relocation_addend != 0: self.image.text_section.content[code_offset + relocation.offset] = relocation_addend & 0xFF self.image.text_section.content[code_offset + relocation.offset + 1] = (relocation_addend >> 8) & 0xFF self.image.text_section.content[code_offset + relocation.offset + 2] = (relocation_addend >> 16) & 0xFF self.image.text_section.content[code_offset + relocation.offset + 3] = (relocation_addend >> 24) & 0xFF self.image.text_section.relocations.append(macho_relocation) function_symbol = Symbol("_" + function.name, SymbolType.section_relative, self.image.text_section, value=code_offset) function_symbol.description = SymbolDescription.defined function_symbol.visibility = SymbolVisibility.external self.image.symbol_table.add_symbol(function_symbol)
def as_bytearray(self): import six from peachpy.formats.elf.file import FileHeader from peachpy.formats.elf.section import Section, StringSection, SymbolSection from peachpy.util import roundup file_header = FileHeader(self.abi) file_header.section_header_table_offset = file_header.size file_header.section_header_entries_count = len(self.sections) file_header.section_name_string_table_index = 1 data = file_header.as_bytearray # Collect strings from sections for section in self.sections: self.shstrtab.add(section.name) if isinstance(section, StringSection): pass elif isinstance(section, SymbolSection): for symbol in six.iterkeys(section.symbol_index_map): self.strtab.add(symbol.name) # Layout sections data_offset = file_header.size + Section.get_header_size( self.abi) * len(self.sections) section_offsets = [] for section in self.sections: if section.alignment != 0: data_offset = roundup(data_offset, section.alignment) section_offsets.append(data_offset) data_offset += section.get_content_size(self.abi) from peachpy.encoder import Encoder encoder = Encoder(self.abi.endianness, self.abi.elf_bitness) section_index_map = { section: index for index, section in enumerate(self.sections) } # Write section headers for section, offset in zip(self.sections, section_offsets): data += section.encode_header(encoder, self.shstrtab._string_index_map, section_index_map, offset) # Write section content for section in self.sections: padding = bytearray( roundup(len(data), section.alignment) - len(data)) data += padding data += section.encode_content(encoder, self.strtab._string_index_map, section_index_map, self.symtab.symbol_index_map) return data
def add_function(self, function): import peachpy.x86_64.function assert isinstance(function, peachpy.x86_64.function.ABIFunction), \ "Function must be bindinded to an ABI before its assembly can be used" from peachpy.util import roundup from peachpy.formats.mscoff import Symbol, SymbolType, StorageClass, Relocation, RelocationType 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)) 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) rdata_offset = self.rdata_section.content_size rdata_padding = bytearray([encoded_function.const_section.alignment_byte] * (roundup(rdata_offset, encoded_function.const_section.alignment) - rdata_offset)) self.rdata_section.content += rdata_padding rdata_offset += len(rdata_padding) self.rdata_section.content += encoded_function.const_section.content self.rdata_section.alignment = \ max(self.rdata_section.alignment, encoded_function.const_section.alignment) # Map from PeachPy symbol to Mach-O symbol symbol_map = dict() for symbol in encoded_function.const_section.symbols: mscoff_symbol = Symbol() mscoff_symbol.name = symbol.name mscoff_symbol.value = rdata_offset + symbol.offset mscoff_symbol.section = self.rdata_section mscoff_symbol.symbol_type = SymbolType.non_function mscoff_symbol.storage_class = StorageClass.static self.image.add_symbol(mscoff_symbol) symbol_map[symbol] = mscoff_symbol for relocation in encoded_function.code_section.relocations: mscoff_relocation = Relocation(RelocationType.x86_64_relocation_offset32, code_offset + relocation.offset, symbol_map[relocation.symbol]) self.text_section.relocations.append(mscoff_relocation) function_symbol = Symbol() function_symbol.name = function.name function_symbol.value = code_offset function_symbol.section = self.text_section function_symbol.symbol_type = SymbolType.function function_symbol.storage_class = StorageClass.external self.image.add_symbol(function_symbol)
def as_bytearray(self): import six from peachpy.formats.elf.file import FileHeader from peachpy.formats.elf.section import Section, StringSection, SymbolSection from peachpy.util import roundup file_header = FileHeader(self.abi) file_header.section_header_table_offset = file_header.size file_header.section_header_entries_count = len(self.sections) file_header.section_name_string_table_index = 1 data = file_header.as_bytearray # Collect strings from sections for section in self.sections: self.shstrtab.add(section.name) if isinstance(section, StringSection): pass elif isinstance(section, SymbolSection): for symbol in six.iterkeys(section.symbol_index_map): self.strtab.add(symbol.name) # Layout sections data_offset = file_header.size + Section.get_header_size(self.abi) * len(self.sections) section_offsets = [] for section in self.sections: if section.alignment != 0: data_offset = roundup(data_offset, section.alignment) section_offsets.append(data_offset) data_offset += section.get_content_size(self.abi) from peachpy.encoder import Encoder encoder = Encoder(self.abi.endianness, self.abi.elf_bitness) section_index_map = {section: index for index, section in enumerate(self.sections)} # Write section headers for section, offset in zip(self.sections, section_offsets): data += section.encode_header(encoder, self.shstrtab._string_index_map, section_index_map, offset) # Write section content for section in self.sections: padding = bytearray(roundup(len(data), section.alignment) - len(data)) data += padding data += section.encode_content( encoder, self.strtab._string_index_map, section_index_map, self.symtab.symbol_index_map ) return data
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)
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)
def encode(self): from peachpy.formats.macho.file import MachHeader from peachpy.formats.macho.symbol import Relocation from peachpy.util import roundup from peachpy.encoder import Encoder bitness = {4: 32, 8: 64}[self.abi.pointer_size] encoder = Encoder(self.abi.endianness, bitness) mach_header = MachHeader(self.abi) mach_header.commands_size = self.symbol_table.command_size mach_header.commands_count = 1 for segment in self.segments: mach_header.commands_size += segment.get_command_size(self.abi) mach_header.commands_count += 1 symbol_offset_map = dict() section_offset_map = dict() section_address_map = dict() section_relocations_map = dict() # Layout the commands data_offset = mach_header.get_size(self.abi) for segment in self.segments: data_offset += segment.get_command_size(self.abi) data_offset += self.symbol_table.command_size # Layout section data data_address = 0 for segment in self.segments: for section in segment.sections: data_offset = roundup(data_offset, section.alignment) data_address = roundup(data_address, section.alignment) section_offset_map[section] = data_offset section_address_map[section] = data_address data_offset += section.content_size data_address += section.content_size data_offset = roundup(data_offset, self.abi.pointer_size) # Layout the relocations for segment in self.segments: for section in segment.sections: if section.relocations: section_relocations_map[section] = data_offset data_offset += Relocation.size * len(section.relocations) # Layout the symbols for symbol in self.symbol_table.symbols: symbol_offset_map[symbol] = data_offset data_offset += symbol.get_entry_size(self.abi) # Layout the strings string_table_offset = data_offset # Create map: section->index section_index = 1 section_index_map = dict() for segment in self.segments: for section in segment.sections: section_index_map[section] = section_index section_index += 1 # Create map: symbol->index symbol_index_map = { symbol: index for index, symbol in enumerate(self.symbol_table.symbols) } # Write Mach-O header data = mach_header.encode(encoder) # Write commands for segment in self.segments: data += segment.encode_command(encoder, section_offset_map, section_address_map, section_relocations_map) data += self.symbol_table.encode_command(encoder, symbol_offset_map, string_table_offset) # Write section data for segment in self.segments: for section in segment.sections: padding = bytearray( roundup(len(data), section.alignment) - len(data)) data += padding + section.content padding = bytearray( roundup(len(data), self.abi.pointer_size) - len(data)) data += padding # Write relocations for segment in self.segments: for section in segment.sections: for relocation in section.relocations: data += relocation.encode(encoder, section_index_map, symbol_index_map) # Write symbols for symbol in self.symbol_table.symbols: data += symbol.encode(encoder, self.string_table.string_index_map, section_index_map, section_address_map) # Write string table data += self.string_table.encode() return data
def encode(self): from peachpy.formats.macho.file import MachHeader from peachpy.formats.macho.symbol import Relocation from peachpy.util import roundup from peachpy.encoder import Encoder bitness = {4: 32, 8: 64}[self.abi.pointer_size] encoder = Encoder(self.abi.endianness, bitness) mach_header = MachHeader(self.abi) mach_header.commands_size = self.symbol_table.command_size mach_header.commands_count = 1 for segment in self.segments: mach_header.commands_size += segment.get_command_size(self.abi) mach_header.commands_count += 1 symbol_offset_map = dict() section_offset_map = dict() section_address_map = dict() section_relocations_map = dict() # Layout the commands data_offset = mach_header.get_size(self.abi) for segment in self.segments: data_offset += segment.get_command_size(self.abi) data_offset += self.symbol_table.command_size # Layout section data data_address = 0 for segment in self.segments: for section in segment.sections: data_offset = roundup(data_offset, section.alignment) data_address = roundup(data_address, section.alignment) section_offset_map[section] = data_offset section_address_map[section] = data_address data_offset += section.content_size data_address += section.content_size data_offset = roundup(data_offset, self.abi.pointer_size) # Layout the relocations for segment in self.segments: for section in segment.sections: if section.relocations: section_relocations_map[section] = data_offset data_offset += Relocation.size * len(section.relocations) # Layout the symbols for symbol in self.symbol_table.symbols: symbol_offset_map[symbol] = data_offset data_offset += symbol.get_entry_size(self.abi) # Layout the strings string_table_offset = data_offset # Create map: section->index section_index = 1 section_index_map = dict() for segment in self.segments: for section in segment.sections: section_index_map[section] = section_index section_index += 1 # Create map: symbol->index symbol_index_map = {symbol: index for index, symbol in enumerate(self.symbol_table.symbols)} # Write Mach-O header data = mach_header.encode(encoder) # Write commands for segment in self.segments: data += segment.encode_command(encoder, section_offset_map, section_address_map, section_relocations_map) data += self.symbol_table.encode_command(encoder, symbol_offset_map, string_table_offset) # Write section data for segment in self.segments: for section in segment.sections: padding = bytearray(roundup(len(data), section.alignment) - len(data)) data += padding + section.content padding = bytearray(roundup(len(data), self.abi.pointer_size) - len(data)) data += padding # Write relocations for segment in self.segments: for section in segment.sections: for relocation in section.relocations: data += relocation.encode(encoder, section_index_map, symbol_index_map) # Write symbols for symbol in self.symbol_table.symbols: data += symbol.encode(encoder, self.string_table.string_index_map, section_index_map, section_address_map) # Write string table data += self.string_table.encode() return data