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
20 changes: 12 additions & 8 deletions lib/caotral/linker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
4 changes: 2 additions & 2 deletions lib/caotral/linker/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions lib/caotral/linker/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions sig/caotral/linker.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 6 additions & 2 deletions sig/caotral/linker/builder.rbs
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions sig/caotral/linker/writer.rbs
Original file line number Diff line number Diff line change
@@ -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