diff --git a/lib/caotral/assembler/writer.rb b/lib/caotral/assembler/writer.rb index 58ea221..7d82a34 100644 --- a/lib/caotral/assembler/writer.rb +++ b/lib/caotral/assembler/writer.rb @@ -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 @@ -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:) @@ -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 diff --git a/lib/caotral/binary/elf/reader.rb b/lib/caotral/binary/elf/reader.rb index 2f6d590..856ac09 100644 --- a/lib/caotral/binary/elf/reader.rb +++ b/lib/caotral/binary/elf/reader.rb @@ -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 diff --git a/lib/caotral/compiler.rb b/lib/caotral/compiler.rb index dfcc32a..e51fbc0 100644 --- a/lib/caotral/compiler.rb +++ b/lib/caotral/compiler.rb @@ -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:,) diff --git a/lib/caotral/linker/writer.rb b/lib/caotral/linker/writer.rb index 73ec3b3..ce74edf 100644 --- a/lib/caotral/linker/writer.rb +++ b/lib/caotral/linker/writer.rb @@ -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*") diff --git a/test/caotral/assembler/writer_test.rb b/test/caotral/assembler/writer_test.rb index d16d36f..1cb1de4 100644 --- a/test/caotral/assembler/writer_test.rb +++ b/test/caotral/assembler/writer_test.rb @@ -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") diff --git a/test/caotral/compiler_test.rb b/test/caotral/compiler_test.rb index 2051cc6..54100a9 100644 --- a/test/caotral/compiler_test.rb +++ b/test/caotral/compiler_test.rb @@ -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) diff --git a/test/caotral/linker/writer_test.rb b/test/caotral/linker/writer_test.rb index 2d4fcc2..3b554fb 100644 --- a/test/caotral/linker/writer_test.rb +++ b/test/caotral/linker/writer_test.rb @@ -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)