From a33409cc08f9d206b1f96464bc74f93b62ad936b Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Sun, 11 Jan 2026 01:38:26 +0900 Subject: [PATCH 1/5] set assebmler section header fields --- lib/caotral/assembler/writer.rb | 72 ++++++++++++++++++++++++++------- test/caotral/compiler_test.rb | 2 +- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/lib/caotral/assembler/writer.rb b/lib/caotral/assembler/writer.rb index 58ea221..aba84b0 100644 --- a/lib/caotral/assembler/writer.rb +++ b/lib/caotral/assembler/writer.rb @@ -56,14 +56,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:) @@ -73,18 +69,64 @@ def write(output: @output) output end - private def decide_type(section) - case section.section_name - when ".text" + private + def decide(section) + type_num = _type(section.section_name) + type = Caotral::Binary::ELF::SectionHeader::SHT_BY_VALUE[type_num] + [ + type_num, + _flag(type), + _addralign(type, section.section_name), + _info(type), + _entsize(type), + ] + end + + def _type(section_name) = Caotral::Binary::ELF::SectionHeader::SHT[type_name(section_name)] + + def _flag(section_type) + case section_type + when :progbits + 6 + when :symtab, :strtab + 0 + else + 0 + end + end + + def _addralign(type, section_name) + return 1 if type == :progbits && section_name == ".text" + return 8 if type == :symtab + 1 + end + + def _info(section_type) + case section_type + when :symtab 1 - when ".symtab" - 2 - when ".shstrtab", ".strtab" - 3 + when :progbits, :strtab + 0 else 0 end end + def _entsize(section_type) + case section_type + when :symtab + 24 + when :progbits, :strtab + 0 + else + 0 + end + end + + def type_name(section_name) + name = section_name.nil? ? :null : section_name[1..].to_sym + name = :progbits if name == :text + name + end end end end 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) From ab52f1506b046ee30703e0a74397b56a5dfd0bae Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Sun, 11 Jan 2026 01:45:47 +0900 Subject: [PATCH 2/5] fix unused variables and wrong attr_reader usage --- lib/caotral/binary/elf/reader.rb | 1 - lib/caotral/compiler.rb | 2 +- lib/caotral/linker/writer.rb | 1 - test/caotral/assembler/writer_test.rb | 2 +- test/caotral/linker/writer_test.rb | 2 +- 5 files changed, 3 insertions(+), 5 deletions(-) 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/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) From 66618985fe34efbdfcc6301745a40d59f63299a5 Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Sun, 11 Jan 2026 01:57:52 +0900 Subject: [PATCH 3/5] add condition for shstrtab section name --- lib/caotral/assembler/writer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/caotral/assembler/writer.rb b/lib/caotral/assembler/writer.rb index aba84b0..d612d2c 100644 --- a/lib/caotral/assembler/writer.rb +++ b/lib/caotral/assembler/writer.rb @@ -125,6 +125,7 @@ def _entsize(section_type) def type_name(section_name) name = section_name.nil? ? :null : section_name[1..].to_sym name = :progbits if name == :text + name = :strtab if name == :shstrtab name end end From cd8446b503eb4593db26d475cfef7e00154305a5 Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Sun, 11 Jan 2026 02:16:29 +0900 Subject: [PATCH 4/5] set table for section type --- lib/caotral/assembler/writer.rb | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/caotral/assembler/writer.rb b/lib/caotral/assembler/writer.rb index d612d2c..da598a0 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 @@ -68,13 +76,13 @@ def write(output: @output) end output end + private_constant :SECTION_TYPE_BY_NAME private def decide(section) - type_num = _type(section.section_name) - type = Caotral::Binary::ELF::SectionHeader::SHT_BY_VALUE[type_num] + type = SECTION_TYPE_BY_NAME[section.section_name] [ - type_num, + _type(type), _flag(type), _addralign(type, section.section_name), _info(type), @@ -82,7 +90,7 @@ def decide(section) ] end - def _type(section_name) = Caotral::Binary::ELF::SectionHeader::SHT[type_name(section_name)] + def _type(type_name) = Caotral::Binary::ELF::SectionHeader::SHT[type_name] def _flag(section_type) case section_type @@ -121,13 +129,6 @@ def _entsize(section_type) 0 end end - - def type_name(section_name) - name = section_name.nil? ? :null : section_name[1..].to_sym - name = :progbits if name == :text - name = :strtab if name == :shstrtab - name - end end end end From 8a69e05f18495da0994748dce19ec50c2450d53c Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Sun, 11 Jan 2026 02:24:00 +0900 Subject: [PATCH 5/5] consider null section, and unknown sections --- lib/caotral/assembler/writer.rb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/caotral/assembler/writer.rb b/lib/caotral/assembler/writer.rb index da598a0..7d82a34 100644 --- a/lib/caotral/assembler/writer.rb +++ b/lib/caotral/assembler/writer.rb @@ -96,7 +96,7 @@ def _flag(section_type) case section_type when :progbits 6 - when :symtab, :strtab + when :symtab, :strtab, :null 0 else 0 @@ -104,16 +104,23 @@ def _flag(section_type) end def _addralign(type, section_name) - return 1 if type == :progbits && section_name == ".text" - return 8 if type == :symtab - 1 + case + when (type == :progbits && section_name == ".text") || type == :strtab + 1 + 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 + when :progbits, :strtab, :null 0 else 0 @@ -123,7 +130,7 @@ def _entsize(section_type) case section_type when :symtab 24 - when :progbits, :strtab + when :progbits, :strtab, :null 0 else 0