Skip to content

Commit

Permalink
MS COFF: support Constant section and relocations
Browse files Browse the repository at this point in the history
  • Loading branch information
Maratyszcza committed Sep 4, 2015
1 parent 7d8e3d6 commit 228f5f6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 8 deletions.
2 changes: 1 addition & 1 deletion peachpy/formats/mscoff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

from peachpy.formats.mscoff.image import MachineType, Image
from peachpy.formats.mscoff.section import Section, TextSection, ReadOnlyDataSection
from peachpy.formats.mscoff.symbol import Symbol, SymbolType, StorageClass
from peachpy.formats.mscoff.symbol import Symbol, SymbolType, StorageClass, Relocation, RelocationType
23 changes: 20 additions & 3 deletions peachpy/formats/mscoff/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class Image:
def __init__(self, abi, source=None):
from peachpy.formats.mscoff.section import StringTable
self.abi = abi
self.sections = []
self.symbols = []
self.sections = list()
self.symbols = list()
self.string_table = StringTable()

def add_section(self, section):
Expand Down Expand Up @@ -70,7 +70,17 @@ def encode(self):
section_offset_map[section] = data_offset
data_offset += section.content_size

# Layout section relocations
from peachpy.formats.mscoff.symbol import Relocation

section_relocations_map = dict()
for section in self.sections:
if section.relocations:
section_relocations_map[section] = data_offset
data_offset += Relocation.entry_size * len(section.relocations)

section_index_map = {section: index + 1 for index, section in enumerate(self.sections)}
symbol_index_map = {symbol: index for index, symbol in enumerate(self.symbols)}

# Write file header
timestamp = 0
Expand All @@ -85,7 +95,9 @@ def encode(self):

# Write section headers
for section in self.sections:
data += section.encode_header(encoder, self.string_table._strings, section_offset_map[section])
data += section.encode_header(encoder, self.string_table._strings,
section_offset_map[section],
section_relocations_map.get(section))

# Write symbol table and string table (immediately follows symbols table)
for symbol in self.symbols:
Expand All @@ -96,4 +108,9 @@ def encode(self):
for section in self.sections:
data += section.content

# Write section relocations
for section in self.sections:
for relocation in section.relocations:
data += relocation.encode_entry(encoder, symbol_index_map)

return data
2 changes: 1 addition & 1 deletion peachpy/formats/mscoff/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ def encode_header(self, encoder, name_index_map, offset, relocations_offset=None
encoder.uint32(address) + \
encoder.uint32(self.content_size) + \
encoder.uint32(offset) + \
encoder.uint32(line_numbers_offset) + \
encoder.uint32(relocations_offset) + \
encoder.uint32(line_numbers_offset) + \
encoder.uint16(len(self.relocations)) + \
encoder.uint16(line_numbers_count) + \
encoder.uint32(self.flags)
Expand Down
76 changes: 76 additions & 0 deletions peachpy/formats/mscoff/symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,79 @@ def encode_entry(self, encoder, name_index_map, section_index_map):
encoder.uint16(self.symbol_type) + \
encoder.uint8(self.storage_class) + \
encoder.uint8(auxiliary_entries)


class RelocationType(IntEnum):
# Relocation is ignored
absolute = 0

# 32-bit address
x86_address32 = 6
# 32-bit offset relative to image base
x86_imagebase_offset32 = 7
# 16-bit section index
x86_section_index = 10
# 32-bit offset relative to the section
x86_section_offset32 = 11
# CLR token
x86_clr_token = 12
# Unsigned 7-bit offset relative to the section
x86_section_offset7 = 13
# 32-bit offset relative to the end of relocation
x86_relocation_offset32 = 14

# 64-bit address
x86_64_address64 = 1
# 32-bit address
x86_64_address32 = 2
# 32-bit offset relative to image base
x86_64_imagebase_offset32 = 3
# 32-bit offset relative to the end of relocation
x86_64_relocation_offset32 = 4
# 32-bit offset relative to the end of relocation + 1 byte
x86_64_relocation_plus_1_offset32 = 5
# 32-bit offset relative to the end of relocation + 2 bytes
x86_64_relocation_plus_2_offset32 = 6
# 32-bit offset relative to the end of relocation + 3 bytes
x86_64_relocation_plus_3_offset32 = 7
# 32-bit offset relative to the end of relocation + 4 bytes
x86_64_relocation_plus_4_offset32 = 8
# 32-bit offset relative to the end of relocation + 5 bytes
x86_64_relocation_plus_5_offset32 = 9
# 16-bit section index
x86_64_section_index = 10
# 32-bit offset relative to the section
x86_64_section_offset32 = 11
# Unsigned 7-bit offset relative to the section
x86_64_section_offset7 = 12
# CLR token
x86_64_clr_token = 13


class Relocation:
entry_size = 10

def __init__(self, type, offset, symbol):
from peachpy.util import is_int, is_uint32
if not isinstance(type, RelocationType):
raise TypeError("Relocation type %s is not in RelocationType enumeration" % str(type))
if not is_int(offset):
raise TypeError("Offset %s is not an integer" % str(offset))
if not is_uint32(offset):
raise ValueError("Offset %d can not be represented as a 32-bit unsigned integer" % offset)
if not isinstance(symbol, Symbol):
raise TypeError("Symbol %s is not an instance of Symbol type" % str(symbol))

self.type = type
self.offset = offset
self.symbol = symbol

def encode_entry(self, encoder, symbol_index_map, section_address=0):
import peachpy.encoder
assert isinstance(encoder, peachpy.encoder.Encoder)
assert self.symbol in symbol_index_map

symbol_index = symbol_index_map[self.symbol]
return encoder.uint32(section_address + self.offset) + \
encoder.uint32(symbol_index) + \
encoder.uint16(self.type)
34 changes: 31 additions & 3 deletions peachpy/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,16 @@ def add_function(self, function):

class MSCOFFWriter:
def __init__(self, output_path, abi, input_path=None):
from peachpy.formats.mscoff.image import Image
from peachpy.formats.mscoff.section import TextSection
from peachpy.formats.mscoff import Image, 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.rdata_section = ReadOnlyDataSection()
self.image.add_section(self.rdata_section)

def __enter__(self):
global active_writer
Expand Down Expand Up @@ -286,6 +287,7 @@ def add_function(self, 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()

Expand All @@ -297,7 +299,33 @@ def add_function(self, function):
self.text_section.alignment = \
max(self.text_section.alignment, encoded_function.code_section.alignment)

from peachpy.formats.mscoff.symbol import Symbol, SymbolType, StorageClass
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
Expand Down

0 comments on commit 228f5f6

Please sign in to comment.