Class: Rubycc::ObjFile::RelocatableWriter
- Inherits:
-
Object
- Object
- Rubycc::ObjFile::RelocatableWriter
- Defined in:
- lib/rubycc/objfile/relocatable_writer.rb
Overview
Writes a general ELF64 relocatable object (ET_REL) for Linux x86_64: arbitrary named sections, an arbitrary symbol table, and full SHT_RELA relocation tables carrying any relocation type and addend.
It is the counterpart the linker's ld -r core needs and deliberately
NOT the compiler's ELFWriter. That writer serves a single translation
unit through a fixed menu — .text/.rodata/.data/.bss and three baked-in
relocation kinds — because a compiler always emits the same shape. A
merged object is open-ended: it may hold any section the inputs carried
(.comment, .note.*, .eh_frame, ...), section symbols pointing at merged
sections, and relocations of any numeric type against any symbol with any
addend. Rather than contort the compiler's writer, this one accepts those
pieces directly and lays them out.
The API is build-then-emit: #add_section, #add_symbol and #add_relocation
return opaque handles (the value structs below) that later calls reference
by identity, so the caller never computes on-disk indices itself. #to_binary
fixes the section order (NULL, the content sections in insertion order, one
.rela.
Two invariants the caller relies on: symbols are emitted with every STB_LOCAL before the first non-local (a stable partition of insertion order, so relocation handles stay valid) and sh_info of .symtab lands on the first global; output is fully deterministic (N4) — identical build calls yield byte-identical bytes, with no timestamps embedded.
Defined Under Namespace
Classes: LaidOut, Relocation, Section, Symbol
Constant Summary collapse
- ELFCLASS64 =
2- ELFDATA2LSB =
1- EV_CURRENT =
1- ET_REL =
1- EM_X86_64 =
62- EM_AARCH64 =
183- SHN_UNDEF =
0- SHN_ABS =
0xFFF1- SHT_SYMTAB =
2- SHT_STRTAB =
3- SHT_RELA =
4- SHT_NOBITS =
8- SHF_INFO_LINK =
0x40- BINDINGS =
Symbolic bind/type/visibility accepted from the caller, mapped to their st_info / st_other encodings. A caller may also pass the raw integer, which passes through unchanged.
{ local: 0, global: 1, weak: 2 }.freeze
- TYPES =
{ notype: 0, object: 1, func: 2, section: 3, file: 4, tls: 6, ifunc: 10 }.freeze
- VISIBILITIES =
{ default: 0, internal: 1, hidden: 2, protected: 3 }.freeze
- SYM_ENTSIZE =
24- RELA_ENTSIZE =
24- SHDR_ENTSIZE =
64- EHDR_SIZE =
64
Instance Attribute Summary collapse
-
#null_symbol ⇒ Object
readonly
Returns the value of attribute null_symbol.
Instance Method Summary collapse
-
#add_relocation(target:, offset:, symbol:, type:, addend:) ⇒ Object
Records a relocation to emit into
target's .rela table. -
#add_section(name:, type:, flags:, addralign:, entsize: 0, data: nil, size: nil) ⇒ Object
Registers a content section.
-
#add_symbol(name:, bind:, type:, visibility: :default, section: nil, shndx: SHN_UNDEF, value: 0, size: 0) ⇒ Object
Registers a symbol.
-
#initialize(machine: EM_X86_64) ⇒ RelocatableWriter
constructor
machineis the ELF e_machine value stamped into the output header. -
#to_binary ⇒ Object
Assembles and returns the object as an ASCII-8BIT String.
- #write(path) ⇒ Object
Constructor Details
#initialize(machine: EM_X86_64) ⇒ RelocatableWriter
machine is the ELF e_machine value stamped into the output header. It
defaults to x86_64 so an existing caller is unaffected; the partial-link
merge passes the inputs' own machine through so a merged aarch64 object
keeps its EM_AARCH64 identity (the final linker reads it back to pick the
target's relocation and crt logic).
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 88 def initialize(machine: EM_X86_64) @machine = machine @sections = [] # The reserved null symbol is index 0 by the ELF ABI; expose it so a # caller can re-point a "no symbol" relocation at it. @null_symbol = Symbol.new(name: nil, bind: 0, type: 0, visibility: 0, section: nil, shndx: SHN_UNDEF, value: 0, size: 0) @symbols = [@null_symbol] @relocations = [] end |
Instance Attribute Details
#null_symbol ⇒ Object (readonly)
Returns the value of attribute null_symbol.
99 100 101 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 99 def null_symbol @null_symbol end |
Instance Method Details
#add_relocation(target:, offset:, symbol:, type:, addend:) ⇒ Object
Records a relocation to emit into target's .rela table.
125 126 127 128 129 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 125 def add_relocation(target:, offset:, symbol:, type:, addend:) @relocations << Relocation.new(target: target, offset: offset, symbol: symbol, type: type, addend: addend) self end |
#add_section(name:, type:, flags:, addralign:, entsize: 0, data: nil, size: nil) ⇒ Object
Registers a content section. type/flags/entsize are raw ELF values;
data (bytes) or, for a NOBITS section, size gives its extent. Returns
the Section handle to reference from symbols and relocations.
104 105 106 107 108 109 110 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 104 def add_section(name:, type:, flags:, addralign:, entsize: 0, data: nil, size: nil) section = Section.new(name: name, type: type, flags: flags, addralign: [addralign, 1].max, entsize: entsize, data: data&.b, size: size) @sections << section section end |
#add_symbol(name:, bind:, type:, visibility: :default, section: nil, shndx: SHN_UNDEF, value: 0, size: 0) ⇒ Object
Registers a symbol. bind/type/visibility may be the symbolic forms
(:local, :func, :hidden, ...) or raw integers. Returns the Symbol handle.
114 115 116 117 118 119 120 121 122 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 114 def add_symbol(name:, bind:, type:, visibility: :default, section: nil, shndx: SHN_UNDEF, value: 0, size: 0) symbol = Symbol.new( name: name, bind: BINDINGS.fetch(bind, bind), type: TYPES.fetch(type, type), visibility: VISIBILITIES.fetch(visibility, visibility), section: section, shndx: shndx, value: value, size: size ) @symbols << symbol symbol end |
#to_binary ⇒ Object
Assembles and returns the object as an ASCII-8BIT String.
132 133 134 135 136 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 132 def to_binary order_symbols layout = build_layout assemble(layout) end |
#write(path) ⇒ Object
138 139 140 |
# File 'lib/rubycc/objfile/relocatable_writer.rb', line 138 def write(path) File.binwrite(path, to_binary) end |