diff --git a/lib/caotral/linker.rb b/lib/caotral/linker.rb index 58f97c8..e2d3e7a 100644 --- a/lib/caotral/linker.rb +++ b/lib/caotral/linker.rb @@ -5,16 +5,18 @@ module Caotral class Linker - def self.link!(inputs:, output: "a.out", linker: "mold", debug: false, shared: false) = new(inputs:, output:, linker:, debug:, shared:).link + def self.link!(inputs:, output: "a.out", linker: "mold", debug: false, shared: false, executable: true) + new(inputs:, output:, linker:, debug:, shared:, executable:).link + end - def initialize(inputs:, output: "a.out", linker: "mold", linker_options: [], shared: false, debug: false) + def initialize(inputs:, output: "a.out", linker: "mold", linker_options: [], executable: true, shared: false, debug: false) @inputs, @output, @linker = inputs, output, linker @options = linker_options - @debug, @shared = debug, shared + @executable, @debug, @shared = executable, debug, shared end - def link(inputs: @inputs, output: @output, debug: @debug, shared: @shared) - return to_elf(inputs:, output:, debug:) if @linker == "self" + def link(inputs: @inputs, output: @output, debug: @debug, shared: @shared, executable: @executable) + return to_elf(inputs:, output:, debug:, shared:, executable:) if @linker == "self" IO.popen(link_command).close end @@ -47,12 +49,14 @@ def link_command(inputs: @inputs, output: @output) def libpath = @libpath ||= File.dirname(Dir.glob("/usr/lib*/**/crti.o").last) def gcc_libpath = @gcc_libpath ||= File.dirname(Dir.glob("/usr/lib/gcc/x86_64-*/*/crtbegin.o").last) - def to_elf(inputs: @inputs, output: @output, debug: @debug) + def to_elf(inputs: @inputs, output: @output, debug: @debug, shared: @shared, executable: @executable) elf_objs = inputs.map { |input| Caotral::Binary::ELF::Reader.new(input:, debug:).read } - builder = Caotral::Linker::Builder.new(elf_objs:) + builder = Caotral::Linker::Builder.new(elf_objs:, debug:, shared:, executable:) builder.resolve_symbols elf_obj = builder.build - Caotral::Linker::Writer.new(elf_obj:, output:, debug:).write + Caotral::Linker::Writer.new(elf_obj:, output:, debug:, shared:, executable:).write + File.chmod(0755, output) if executable + output end end end diff --git a/lib/caotral/linker/builder.rb b/lib/caotral/linker/builder.rb index f95934b..fc97df7 100644 --- a/lib/caotral/linker/builder.rb +++ b/lib/caotral/linker/builder.rb @@ -14,10 +14,10 @@ class Builder attr_reader :symbols, :executable, :debug - def initialize(elf_objs:, executable: true, debug: false) + def initialize(elf_objs:, executable: true, debug: false, shared: false) @elf_objs = elf_objs + @executable, @debug, @shared = executable, debug, shared @symbols = { locals: Set.new, globals: Set.new, weaks: Set.new } - @executable, @debug = executable, debug end def build diff --git a/lib/caotral/linker/writer.rb b/lib/caotral/linker/writer.rb index c393023..203f44b 100644 --- a/lib/caotral/linker/writer.rb +++ b/lib/caotral/linker/writer.rb @@ -9,11 +9,11 @@ class Writer ALLOW_RELOCATION_TYPES = [R_X86_64_PC32, R_X86_64_PLT32].freeze RELOCATION_SECTION_NAMES = [".rela.text", ".rel.text"].freeze attr_reader :elf_obj, :output, :entry, :debug - def self.write!(elf_obj:, output:, entry: nil, debug: false) - new(elf_obj:, output:, entry:, debug:).write + def self.write!(elf_obj:, output:, entry: nil, debug: false, executable: true, shared: false) + new(elf_obj:, output:, entry:, debug:, shared:, executable:).write end - def initialize(elf_obj:, output:, entry: nil, debug: false) - @elf_obj, @output, @entry, @debug = elf_obj, output, entry, debug + def initialize(elf_obj:, output:, entry: nil, debug: false, executable: true, shared: false) + @elf_obj, @output, @entry, @debug, @executable, @shared = elf_obj, output, entry, debug, executable, shared @write_sections = write_order_sections end def write diff --git a/sig/caotral/linker.rbs b/sig/caotral/linker.rbs index d3971f9..ec8e2b5 100644 --- a/sig/caotral/linker.rbs +++ b/sig/caotral/linker.rbs @@ -3,15 +3,16 @@ class Caotral::Linker @output: String @linker: String @options: Array[String] + @executable: bool @shared: bool @debug: bool - def self.link!: (inputs: Array[String], ?output: String, ?linker: String, ?debug: bool, ?shared: bool) -> void - def initialize: (inputs: Array[String], ?output: String, ?linker: String, ?linker_options: Array[String], ?shared: bool, ?debug: bool) -> void - def link: (inputs: Array[String], ?output: String, ?shared: bool, ?debug: bool) -> void + def self.link!: (inputs: Array[String], ?output: String, ?linker: String, ?debug: bool, ?shared: bool, ?executable: bool) -> void + def initialize: (inputs: Array[String], ?output: String, ?linker: String, ?linker_options: Array[String], ?executable: bool, ?shared: bool, ?debug: bool) -> void + def link: (inputs: Array[String], ?output: String, ?shared: bool, ?debug: bool, ?executable: bool) -> void def link_command: (inputs: Array[String], ?output: String, ?shared: bool, ?debug: bool) -> String def libpath: () -> String def gcc_libpath: () -> String - def to_elf: (inputs: Array[String], ?output: String, ?debug: bool) -> String + def to_elf: (inputs: Array[String], ?output: String, ?debug: bool, ?shared: bool, ?executable: bool) -> String end diff --git a/sig/caotral/linker/builder.rbs b/sig/caotral/linker/builder.rbs index 0160a38..172e3b2 100644 --- a/sig/caotral/linker/builder.rbs +++ b/sig/caotral/linker/builder.rbs @@ -1,9 +1,13 @@ class Caotral::Linker::Builder - @elf_obj: Caotral::Binary::ELF + @elf_objs: Array[Caotral::Binary::ELF] @symbols: Hash[Symbol, Set[String]] + @executable: bool + @debug: bool + @shared: bool attr_reader symbols: Hash[Symbol, Set[String]] - def initialize: (elf_obj: Caotral::Binary::ELF) -> void + def initialize: (elf_objs: Array[Caotral::Binary::ELF], ?executable: bool, ?debug: bool, ?shared: bool) -> void + def build: () -> Caotral::Binary::ELF def resolve_symbols: () -> Hash[Symbol, Set[String]] end diff --git a/sig/caotral/linker/writer.rbs b/sig/caotral/linker/writer.rbs index d47f1ef..87b6091 100644 --- a/sig/caotral/linker/writer.rbs +++ b/sig/caotral/linker/writer.rbs @@ -1,5 +1,5 @@ class Caotral::Linker::Writer - def self.write!: (elf_obj: Caotral::Binary::ELF, output: String, ?entry: Integer, ?debug: bool) -> String - def initialize: (elf_obj: Caotral::Binary::ELF, output: String, ?entry: Integer, ?debug: bool) -> void + def self.write!: (elf_obj: Caotral::Binary::ELF, output: String, ?entry: Integer, ?debug: bool, ?executable: bool, ?shared: bool) -> String + def initialize: (elf_obj: Caotral::Binary::ELF, output: String, ?entry: Integer, ?debug: bool, ?executable: bool, ?shared: bool) -> void def write: () -> String end