Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 66 additions & 15 deletions lib/caotral/assembler/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
module Caotral
class Assembler
class Writer
SECTION_TYPE_BY_NAME = {
nil => :null,
".symtab" => :symtab,
".shstrtab" => :strtab,
".strtab" => :strtab,
".text" => :progbits,
}.freeze

def self.write!(elf_obj:, output:, debug: false) = new(elf_obj:, output:, debug:).write
def initialize(elf_obj:, output:, debug: false)
@elf_obj = elf_obj
Expand Down Expand Up @@ -56,14 +64,10 @@ def write(output: @output)
body.build.size
end
offset = section.section_name.nil? ? 0 : offsets[section_name]
type = decide_type(section)
if ".symtab" == section.section_name
link = @elf_obj.index(".strtab")
info = 1
header.set!(name:, offset:, size:, type:, info:, link:)
else
header.set!(name:, offset:, size:, type:)
end
link = 0
type, flags, addralign, info, entsize = [*decide(section)]
link = @elf_obj.index(".strtab") if ".symtab" == section.section_name
header.set!(name:, flags:, offset:, size:, type:, info:, link:, entsize:, addralign:)
f.write(header.build)
end
@elf_obj.header.set!(shoffset:, shnum:, shstrndx:)
Expand All @@ -72,15 +76,62 @@ def write(output: @output)
end
output
end
private_constant :SECTION_TYPE_BY_NAME

private
def decide(section)
type = SECTION_TYPE_BY_NAME[section.section_name]
[
_type(type),
_flag(type),
_addralign(type, section.section_name),
_info(type),
_entsize(type),
]
end

def _type(type_name) = Caotral::Binary::ELF::SectionHeader::SHT[type_name]

def _flag(section_type)
case section_type
when :progbits
6
when :symtab, :strtab, :null
0
else
0
end
end

private def decide_type(section)
case section.section_name
when ".text"
def _addralign(type, section_name)
case
when (type == :progbits && section_name == ".text") || type == :strtab
1
when ".symtab"
2
when ".shstrtab", ".strtab"
3
when type == :symtab
8
when type == :null
0
else
0
end
end

def _info(section_type)
case section_type
when :symtab
1
when :progbits, :strtab, :null
0
else
0
end
end
def _entsize(section_type)
case section_type
when :symtab
24
when :progbits, :strtab, :null
0
else
0
end
Expand Down
1 change: 0 additions & 1 deletion lib/caotral/binary/elf/reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def read
info = sh_entry[44, 4].unpack("L<").first
addralign = sh_entry[48, 8].unpack("Q<").first
entsize = sh_entry[56, 8].unpack("Q<").first
type_sym = type(type_val)
section_header = Caotral::Binary::ELF::SectionHeader.new
section_header.set!(name:, type: type_val, flags:, addr:, offset:, size:, link:, info:, addralign:, entsize:)
section_name = i == shstrndx ? ".shstrtab" : nil
Expand Down
2 changes: 1 addition & 1 deletion lib/caotral/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require_relative "compiler/generator"

class Caotral::Compiler
attr_reader *%i(generator assembler linker)
attr_reader :generator, :assembler, :linker

def self.compile!(input:, output: "tmp.s", debug: false, compiler_options: ["-O0"], shared: false)
compiler = new(input:, output:, debug:, shared:,)
Expand Down
1 change: 0 additions & 1 deletion lib/caotral/linker/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def write
vaddr = base_addr + text_offset
paddr = base_addr + text_offset
start_len = start_bytes.length
start_addr = base_addr + text_offset
main_offset = main_sym.value + start_len
start_bytes[1, 4] = num2bytes((main_offset - 5), 4)
start_bytestring = start_bytes.pack("C*")
Expand Down
2 changes: 1 addition & 1 deletion test/caotral/assembler/writer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def test_write
output = "amd64.o"
instructions = Caotral::Assembler::Reader.new(input:).read
elf_obj = Caotral::Assembler::Builder.new(instructions:).build
writer = Caotral::Assembler::Writer.new(elf_obj:, output:).write
Caotral::Assembler::Writer.new(elf_obj:, output:).write
results = Caotral::Binary::ELF::Reader.new(input: output).read
shstrtab = results.find_by_name(".shstrtab")
text = results.find_by_name(".text")
Expand Down
2 changes: 1 addition & 1 deletion test/caotral/compiler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def test_sample_plus

def test_sample_variable
@file = "sample/variable.rb"
@caotral = Caotral.compile!(input: @file, assembler: "self")
@caotral = Caotral.compile!(input: @file, assembler: "self", linker: "self")
File.chmod(755, "tmp")
IO.popen("./tmp").close
exit_code, handle_code = check_process($?.to_i)
Expand Down
2 changes: 1 addition & 1 deletion test/caotral/linker/writer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_write
end

def test_execute_written
written_output = Caotral::Linker::Writer.write!(elf_obj: @elf_obj, output: "write", debug: false)
Caotral::Linker::Writer.write!(elf_obj: @elf_obj, output: "write", debug: false)
File.chmod(0755, "./write")
IO.popen("./write").close
exit_code, handle_code = check_process($?.to_i)
Expand Down