2014-04-19 22:25:46 +02:00
|
|
|
require_relative "constants"
|
|
|
|
require_relative "null_section"
|
|
|
|
|
2014-04-14 17:09:56 +02:00
|
|
|
module Elf
|
|
|
|
class ObjectFile
|
2014-04-19 22:25:46 +02:00
|
|
|
include Constants
|
2014-04-14 17:09:56 +02:00
|
|
|
|
|
|
|
def initialize(target)
|
|
|
|
@target = target
|
|
|
|
|
|
|
|
@sections = []
|
|
|
|
add_section NullSection.new
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_section(section)
|
|
|
|
@sections << section
|
|
|
|
section.index = @sections.length - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
def write(io)
|
2016-12-16 15:18:14 +01:00
|
|
|
write_preamble(io)
|
2014-04-14 17:09:56 +02:00
|
|
|
|
|
|
|
sh_offset_pos = io.tell
|
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
write_header(io)
|
|
|
|
|
|
|
|
string_table = write_string_table(io)
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_16 @sections.length # section header count
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_16 @sections.length-1 # section name string table index
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
section_data = write_sections(io)
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
sh_offset = io.tell
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
write_section_data(section_data, string_table , io)
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
io.seek sh_offset_pos
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 sh_offset
|
2016-12-16 15:18:14 +01:00
|
|
|
end
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
def write_string_table(io)
|
|
|
|
string_table = StringTableSection.new(".shstrtab")
|
|
|
|
@sections << string_table
|
|
|
|
@sections.each { |section|
|
|
|
|
string_table.add_string section.name
|
|
|
|
}
|
|
|
|
string_table
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_section_data(section_data, string_table,io)
|
2014-04-14 17:09:56 +02:00
|
|
|
section_data.each { |data|
|
|
|
|
section, offset, size = data[:section], data[:offset], data[:size]
|
|
|
|
# write header first
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 string_table.index_for(section.name)
|
|
|
|
io.write_unsigned_int_32 section.type
|
|
|
|
io.write_unsigned_int_32 section.flags
|
|
|
|
io.write_unsigned_int_32 section.addr
|
2014-04-14 17:09:56 +02:00
|
|
|
if (section.type == SHT_NOBITS)
|
|
|
|
raise 'SHT_NOBITS not handled yet'
|
|
|
|
elsif (section.type == SHT_NULL)
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 0
|
|
|
|
io.write_unsigned_int_32 0
|
2014-04-14 17:09:56 +02:00
|
|
|
else
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 offset
|
|
|
|
io.write_unsigned_int_32 size
|
2014-04-14 17:09:56 +02:00
|
|
|
end
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 section.link
|
|
|
|
io.write_unsigned_int_32 section.info
|
|
|
|
io.write_unsigned_int_32 section.alignment
|
|
|
|
io.write_unsigned_int_32 section.ent_size
|
2014-04-14 17:09:56 +02:00
|
|
|
}
|
2016-12-16 15:18:14 +01:00
|
|
|
end
|
2014-04-14 17:09:56 +02:00
|
|
|
|
2016-12-16 15:18:14 +01:00
|
|
|
def write_sections(io)
|
|
|
|
section_data = []
|
|
|
|
@sections.each { |section|
|
|
|
|
offset = io.tell
|
|
|
|
section.write(io)
|
|
|
|
size = io.tell - offset
|
|
|
|
section_data << {:section => section, :offset => offset, :size => size}
|
|
|
|
}
|
|
|
|
section_data
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_header(io)
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_32 0 # section header table offset
|
|
|
|
io.write_unsigned_int_32 0 # no flags
|
|
|
|
io.write_unsigned_int_16 52 # header length
|
|
|
|
io.write_unsigned_int_16 0 # program header length
|
|
|
|
io.write_unsigned_int_16 0 # program header count
|
|
|
|
io.write_unsigned_int_16 40 # section header length
|
2016-12-16 15:18:14 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def write_preamble(io)
|
|
|
|
io << "\x7fELF"
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_8 @target[0]
|
|
|
|
io.write_unsigned_int_8 @target[1]
|
|
|
|
io.write_unsigned_int_8 EV_CURRENT
|
|
|
|
io.write_unsigned_int_8 @target[2]
|
2016-12-16 15:18:14 +01:00
|
|
|
io << "\x00" * 8 # pad
|
2016-12-31 17:45:22 +01:00
|
|
|
io.write_unsigned_int_16 ET_REL
|
|
|
|
io.write_unsigned_int_16 @target[3]
|
|
|
|
io.write_unsigned_int_32 EV_CURRENT
|
|
|
|
io.write_unsigned_int_32 0 # entry point
|
|
|
|
io.write_unsigned_int_32 0 # no program header table
|
2014-04-14 17:09:56 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|