Class: Rubycc::Link::PartialLinker

Inherits:
Object
  • Object
show all
Includes:
ObjFile
Defined in:
lib/rubycc/link/partial_linker.rb

Overview

The static-link core, an ld -r equivalent: it merges an ordered list of ET_REL objects (and archive members pulled in lazily) into a single ET_REL object. Relocations are retargeted, not applied — an ld -r output keeps its relocations so a later final link can resolve them; the byte-patching apply engine belongs to the executable/.so writers, not here.

The pipeline is two phases over the reader structures directly (no linker IR, per the roadmap): a selection phase walks the inputs left to right to decide which objects take part — a .o joins unconditionally, an archive contributes only members that resolve a still-undefined symbol (iterated to a fixpoint within that archive; classic single-pass, so an archive already passed is never revisited) — and a merge phase concatenates same-named sections, resolves the global symbol table, and rewrites every relocation onto the merged sections and symbol table before handing the result to RelocatableWriter.

The single subtle point is a relocation against a section symbol: its target section's bytes move to a new offset in the merged section, so the addend, which is measured from that section's start, must gain the piece's placement offset. Named-symbol references need no addend fix-up because the symbol's own value already carries the shift.

Unresolved symbols are legal in an ld -r output and stay UND. COMMON symbols are diagnosed rather than allocated (out of scope; neither rubycc nor gcc's -fno-common default emits them). Output is deterministic (N4): sections appear in first-seen order, symbols in a fixed local-then-global order, so identical inputs yield byte-identical output.

Defined Under Namespace

Classes: Input, Merger

Constant Summary collapse

ELFMAG =
"\x7FELF".b
AR_MAGIC =
"!<arch>\n".b
SHT_NULL =

Section header types the merge treats specially. Everything else — any named PROGBITS/NOBITS/NOTE/*_ARRAY the compiler emits or gcc adds — is carried through and concatenated by name.

0
SHT_SYMTAB =
2
SHT_STRTAB =
3
SHT_RELA =
4
SHT_REL =
9
SHT_NOBITS =
8
SHT_GROUP =
17
SHT_SYMTAB_SHNDX =
18
SKIPPED_TYPES =

Section kinds that describe the object's own linking metadata (symbol and string tables, relocation tables, section groups) — regenerated by the writer, so never carried from the inputs.

[SHT_NULL, SHT_SYMTAB, SHT_STRTAB, SHT_RELA, SHT_REL,
SHT_GROUP, SHT_SYMTAB_SHNDX].freeze
SHN_UNDEF =
0
SHN_ABS =
0xFFF1

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inputs) ⇒ PartialLinker

Returns a new instance of PartialLinker.



74
75
76
# File 'lib/rubycc/link/partial_linker.rb', line 74

def initialize(inputs)
  @inputs = inputs.each_with_index.map { |raw, i| load_input(raw, i) }
end

Class Method Details

Links inputs (an ordered array; each element a filesystem path, or the raw bytes of an ET_REL object or an ar archive) and returns the merged ET_REL object as an ASCII-8BIT String.



64
65
66
# File 'lib/rubycc/link/partial_linker.rb', line 64

def link(inputs)
  new(inputs).link
end

Convenience: link and write the merged object to path.



69
70
71
# File 'lib/rubycc/link/partial_linker.rb', line 69

def link_to(inputs, path)
  File.binwrite(path, link(inputs))
end

Instance Method Details



78
79
80
81
# File 'lib/rubycc/link/partial_linker.rb', line 78

def link
  included = select_inputs
  Merger.new(included).run
end