tiny.tldr.formats.elf
Defined in formats.
API (30)
Actions
Public operations.
buildIdNoteRangefinishIncrementalMetadatalinkExecutableparseObjectMetadatapatchIncrementalMetadatapatchIncrementalMetadataRange
Namespaces
Public namespaces.
addressingdiagnosticehframeformatgot_tablegroupicfifuncimagelayoutlivenessmergenoteobjectoutput_sectionparserpayloadprogramrelinkrelocationsection_statestringsymbol_tableview
Source
Source: lib/tldr/src/formats/elf/link.zig:59
zig
pub fn linkExecutable( allocator: Allocator, inputs: []const model.Input, options: model.LinkOptions,) model.Error!root.LinkedImage { const link_phase = trace.scope("link.elf"); defer link_phase.end(); if (options.diagnostics) |diagnostics| diagnostics.clear(); if (options.requiresDynamicLinking()) return error.UnsupportedDynamicLinking; if (options.output_kind != .executable) return error.UnsupportedOutputKind; if (options.target.architecture != .x86_64 or options.target.endianness != .little) { return error.UnsupportedArchitecture; } if (inputs.len == 0) return error.NoAllocSections; var selection_state = std.heap.ArenaAllocator.init(allocator); defer selection_state.deinit(); var selection_lock = allocators.LockedAllocator.init(selection_state.allocator()); const selection = selection_lock.allocator(); var scratch_state = std.heap.ArenaAllocator.init(allocator); defer scratch_state.deinit(); const scratch = scratch_state.allocator(); var manifest_builder = build_manifest: { const manifest_phase = trace.product(.manifest_recording); defer manifest_phase.end(); var builder = try incremental.Builder.init(allocator, options); errdefer builder.deinit(); for (inputs) |input| try builder.addInput(input); break :build_manifest builder; }; errdefer manifest_builder.deinit(); var objects = std.ArrayListUnmanaged(ObjectFile).empty; defer objects.deinit(scratch); try objects.ensureTotalCapacity(scratch, inputs.len); var archive_state: archive_selection.ExtractionState = .{}; defer archive_state.deinit(scratch); var prefetcher = archive_selection.Prefetcher.init(selection, inputs, options); defer prefetcher.deinit(); prefetcher.advance(0); for (inputs, 0..) |input, input_index| { if (archive.isArchive(input.bytes)) { const archive_phase = trace.product(.archive_member_selection); defer archive_phase.end(); try archive_state.observeNewObjects(scratch, objects.items); try archive_selection.addCandidates(scratch, selection, input, input_index, &archive_state, options, &prefetcher); prefetcher.advance(input_index + 1); } else { var object = try parseInputObject(scratch, input, options); object.input_index = input_index; try objects.append(scratch, object); } if (archive_state.hasCandidates()) { const archive_phase = trace.product(.archive_member_selection); defer archive_phase.end(); try archive_state.observeNewObjects(scratch, objects.items); try archive_selection.extractCandidates( scratch, selection, &objects, &archive_state, options, ); } } if (manifest_builder.recordsContributions()) { const manifest_phase = trace.product(.manifest_recording); defer manifest_phase.end(); try relink.recordInputLinkEvidence(&manifest_builder, scratch, inputs, objects.items, &archive_state); } var globals: std.StringHashMapUnmanaged(GlobalSymbol) = .{}; defer globals.deinit(scratch); var global_symbol_refs = std.ArrayListUnmanaged(SymbolRef).empty; defer global_symbol_refs.deinit(scratch); { const symbol_phase = trace.product(.symbol_database); defer symbol_phase.end(); { const duplicate_phase = trace.product(.duplicate_policy); defer duplicate_phase.end(); try group.discardDuplicates(scratch, objects.items); } try collectGlobalSymbols(scratch, objects.items, &globals, &global_symbol_refs, options.max_link_jobs); if (options.gc_sections) { try liveness.discardUnreachable(scratch, objects.items, &globals, options); } if (options.icf == .all) { const duplicate_phase = trace.product(.duplicate_policy); defer duplicate_phase.end(); try icf.fold(scratch, objects.items); } try requireResolvedRelocationSymbols(scratch, objects.items, &globals, options); try requireSupportedRelocations(scratch, objects.items, options); try requireEntrySymbol(&globals, options); } if (options.commit_observer) |observer| observer.notify(); var output_sections = [output_section_count]OutputSection{ .{ .kind = .build_id_note, .alignment = 4 }, .{ .kind = .init, .alignment = 4 }, .{ .kind = .text, .alignment = 16 }, .{ .kind = .fini, .alignment = 4 }, .{ .kind = .iplt, .alignment = 16 }, .{ .kind = .eh_frame_hdr, .alignment = 4 }, .{ .kind = .eh_frame, .alignment = 8 }, .{ .kind = .rodata, .alignment = 1 }, .{ .kind = .rela_iplt, .alignment = 8 }, .{ .kind = .preinit_array, .alignment = 8 }, .{ .kind = .init_array, .alignment = 8 }, .{ .kind = .fini_array, .alignment = 8 }, .{ .kind = .data, .alignment = 8 }, .{ .kind = .got, .alignment = 8 }, .{ .kind = .igot, .alignment = 8 }, .{ .kind = .tdata, .alignment = 1 }, .{ .kind = .tbss, .alignment = 1 }, .{ .kind = .bss, .alignment = 1 }, .{ .kind = .debug_abbrev, .alignment = 1 }, .{ .kind = .debug_addr, .alignment = 1 }, .{ .kind = .debug_aranges, .alignment = 1 }, .{ .kind = .debug_cu_index, .alignment = 1 }, .{ .kind = .debug_frame, .alignment = 1 }, .{ .kind = .debug_info, .alignment = 1 }, .{ .kind = .debug_line, .alignment = 1 }, .{ .kind = .debug_line_str, .alignment = 1 }, .{ .kind = .debug_loc, .alignment = 1 }, .{ .kind = .debug_loclists, .alignment = 1 }, .{ .kind = .debug_macinfo, .alignment = 1 }, .{ .kind = .debug_macro, .alignment = 1 }, .{ .kind = .debug_names, .alignment = 1 }, .{ .kind = .debug_pubnames, .alignment = 1 }, .{ .kind = .debug_pubtypes, .alignment = 1 }, .{ .kind = .debug_ranges, .alignment = 1 }, .{ .kind = .debug_rnglists, .alignment = 1 }, .{ .kind = .debug_str, .alignment = 1 }, .{ .kind = .debug_str_offsets, .alignment = 1 }, .{ .kind = .debug_tu_index, .alignment = 1 }, .{ .kind = .debug_types, .alignment = 1 }, }; var layouts = try scratch.alloc(ObjectLayout, objects.items.len); var layout_count: usize = 0; var section_contributions: []SectionContribution = &.{}; defer { for (layouts[0..layout_count]) |*object_layout| object_layout.deinit(scratch); scratch.free(section_contributions); scratch.free(layouts); } { const layout_phase = trace.product(.section_contribution_graph); defer layout_phase.end(); const section_contribution_count = try layout.collect.countObjectSections(objects.items); section_contributions = try scratch.alloc(SectionContribution, section_contribution_count); try layout.collect.sections(scratch, objects.items, &output_sections, layouts, section_contributions, &layout_count, &globals, options); reserveBuildIdNote(&output_sections, options); try ehframe.reserveHeader(&output_sections, objects.items, layouts[0..layout_count], options); } var ifunc_collector: elf.ifunc.Collector = undefined; var got_layout: layout.GotLayout = undefined; var ifunc_layout: elf.ifunc.IfuncLayout = undefined; { const layout_phase = trace.product(.layout_groups); defer layout_phase.end(); ifunc_collector = try elf.ifunc.Collector.init(scratch, objects.items, &globals, options.max_link_jobs); errdefer ifunc_collector.deinit(scratch); const collect_ifunc = ifunc_collector.enabled(); got_layout = if (collect_ifunc) try got_table.collectEntriesWithIfunc(scratch, objects.items, &output_sections, &globals, &ifunc_collector) else try collectGotEntries(scratch, objects.items, &output_sections, &globals); errdefer got_layout.deinit(scratch); ifunc_layout = if (collect_ifunc) try ifunc_collector.finish(scratch, &output_sections) else elf.ifunc.IfuncLayout{}; errdefer ifunc_layout.deinit(scratch); } defer ifunc_collector.deinit(scratch); defer got_layout.deinit(scratch); defer ifunc_layout.deinit(scratch); const live_output_count = layout.output.countLive(&output_sections); if (live_output_count == 0) return error.NoAllocSections; const program_header_count = try countProgramHeaders(&output_sections); { const layout_phase = trace.product(.address_assignment); defer layout_phase.end(); try layout.output.assign(&output_sections, options, program_header_count); } { const manifest_phase = trace.product(.manifest_recording); defer manifest_phase.end(); for (output_sections) |section| { if (section.logicalSize() == 0) continue; try manifest_builder.addSection( section.kind.name(), section.address, section.file_offset, section.logicalSize(), section.reserved_size, section.alignment, ); } if (manifest_builder.recordsContributions()) { try addContributionRecords(&manifest_builder, objects.items, layouts[0..layout_count], &output_sections); } } var symbol_addresses = try SymbolAddressCache.init(scratch, objects.items, layouts[0..layout_count], &output_sections); defer symbol_addresses.deinit(scratch); try elf.ifunc.finalize(objects.items, layouts[0..layout_count], &output_sections, &globals, &symbol_addresses, ifunc_layout); const entry_address = resolve_entry: { const symbol_phase = trace.product(.symbol_database); defer symbol_phase.end(); break :resolve_entry try resolveEntry(objects.items, layouts, &output_sections, &globals, &symbol_addresses, options.entry_symbol); }; var linked_image = write_image: { const write_phase = trace.product(.output_writing); defer write_phase.end(); break :write_image try image.write( scratch, allocator, objects.items, layouts, &output_sections, &globals, global_symbol_refs.items, &symbol_addresses, got_layout, options, entry_address, live_output_count, program_header_count, ); }; errdefer linked_image.deinit(allocator); const linked_bytes = linked_image.bytes; try elf.ifunc.write(linked_bytes, &output_sections, ifunc_layout); { const materialize_phase = trace.product(.payload_materialization); defer materialize_phase.end(); try relocation_namespace.materialize(scratch, objects.items, layouts, &output_sections, &globals, &symbol_addresses, got_layout, linked_bytes, options); } if (@import("builtin").mode == .debug) elf.payload.verifyMergePieceBytes(linked_bytes, objects.items, layouts, &output_sections); try finishBuildIdNote(linked_bytes, &output_sections, options); var manifest = finish_manifest: { const manifest_phase = trace.product(.manifest_recording); defer manifest_phase.end(); if (manifest_builder.recordsContributions()) { try addExternalTargetRecords( &manifest_builder, scratch, objects.items, layouts[0..layout_count], &output_sections, &globals, global_symbol_refs.items, &symbol_addresses, ); try addGotEntryRecords(&manifest_builder, objects.items, &output_sections, &globals, got_layout); try addMergePieceRecords(&manifest_builder, objects.items, layouts[0..layout_count], &output_sections); } break :finish_manifest try manifest_builder.finish(); }; errdefer manifest.deinit(allocator); return .{ .bytes = linked_bytes, .storage = linked_image.storage, .manifest = manifest, };}Source: lib/tldr/src/formats/elf/metadata.zig:57
zig
pub fn buildIdNoteRange(image: []const u8) model.Error!?MetadataRange { const note = linkedSectionByName(image, build_id_note.section_name) catch |err| switch (err) { error.MissingSection => return null, else => return err, }; return .{ .offset = std.math.cast(usize, note.offset) orelse return error.InvalidRange, .len = std.math.cast(usize, note.size) orelse return error.InvalidRange, };}Source: lib/tldr/src/formats/elf/metadata.zig:48
zig
pub fn finishIncrementalMetadata(image: []u8, options: model.LinkOptions) model.Error!void { try finishGeneratedBuildIdNote(image, options.build_id);}Source: lib/tldr/src/formats/elf/metadata.zig:35
zig
pub fn patchIncrementalMetadata(image: []u8, candidate_image: []const u8) model.Error!void { if (image.len != candidate_image.len) return error.InvalidRange; const image_metadata = try metadataLayout(image); const candidate_metadata = try metadataLayout(candidate_image); if (image_metadata.start != candidate_metadata.start) return error.InvalidElfHeader; if (image_metadata.section_header_offset != candidate_metadata.section_header_offset) return error.InvalidElfHeader; if (image_metadata.section_count != candidate_metadata.section_count) return error.InvalidElfHeader; if (image_metadata.string_section_index != candidate_metadata.string_section_index) return error.InvalidElfHeader; const start: usize = @intCast(image_metadata.start); @memcpy(image[start..], candidate_image[start..]); try patchGeneratedBuildIdNote(image, candidate_image);}Source: lib/tldr/src/formats/elf/metadata.zig:68
zig
pub fn patchIncrementalMetadataRange(image: []const u8) model.Error!MetadataRange { const image_metadata = try metadataLayout(image); const start = std.math.cast(usize, image_metadata.start) orelse return error.InvalidRange; return .{ .offset = start, .len = image.len - start };}Source: lib/tldr/src/formats/elf/root.zig
zig
const link = @import("link.zig");const metadata = @import("metadata.zig");pub const addressing = @import("address/root.zig");pub const diagnostic = @import("diagnostic.zig");pub const ehframe = @import("ehframe/root.zig");pub const format = @import("format.zig");pub const got_table = @import("got.zig");pub const ifunc = @import("ifunc.zig");pub const group = @import("group/root.zig");pub const icf = @import("icf/root.zig");pub const image = @import("image/root.zig");pub const layout = @import("layout/root.zig");pub const liveness = @import("liveness/root.zig");pub const merge = @import("merge/root.zig");pub const note = @import("note.zig");pub const object = @import("object/root.zig");pub const payload = @import("payload.zig");pub const program = @import("program.zig");pub const parser = @import("parser.zig");pub const relink = @import("relink.zig");pub const output_section = @import("section.zig");pub const relocation = @import("relocation/root.zig");pub const section_state = @import("sections.zig");pub const string = @import("string.zig");pub const symbol_table = @import("symbol.zig");pub const view = @import("view.zig");pub const parseObjectMetadata = parser.parseObjectMetadata;pub const linkExecutable = link.linkExecutable;pub const patchIncrementalMetadata = metadata.patchIncrementalMetadata;pub const finishIncrementalMetadata = metadata.finishIncrementalMetadata;pub const buildIdNoteRange = metadata.buildIdNoteRange;pub const patchIncrementalMetadataRange = metadata.patchIncrementalMetadataRange;Source: lib/tldr/src/formats/root.zig:3
zig
pub const elf = @import("elf/root.zig");Complete call list for formats.elf.linkExecutable
26 direct calls.
tiny.tldr.archive.isArchive[function] atlib/tldr/src/archive.zig:38lib.tldr.src.formats.elf.icf.fold[module] — private; no exact target atlib/tldr/src/formats/elf/icf/fold.zigtiny.tldr.formats.elf.ifunc.Collector.deinit[method] atlib/tldr/src/formats/elf/ifunc.zig:97tiny.tldr.formats.elf.ifunc.Collector.enabled[method] atlib/tldr/src/formats/elf/ifunc.zig:105tiny.tldr.formats.elf.ifunc.Collector.finish[method] atlib/tldr/src/formats/elf/ifunc.zig:128tiny.tldr.formats.elf.ifunc.Collector.init[function] atlib/tldr/src/formats/elf/ifunc.zig:56tiny.tldr.formats.elf.ifunc.IfuncLayout.deinit[method] atlib/tldr/src/formats/elf/ifunc.zig:44tiny.tldr.formats.elf.ifunc.finalize[function] atlib/tldr/src/formats/elf/ifunc.zig:235tiny.tldr.formats.elf.ifunc.write[function] atlib/tldr/src/formats/elf/ifunc.zig:264tiny.tldr.formats.elf.layout.collect.countObjectSections[function] atlib/tldr/src/formats/elf/layout/collect.zig:580tiny.tldr.formats.elf.layout.collect.sections[function] atlib/tldr/src/formats/elf/layout/collect.zig:65tiny.tldr.formats.elf.layout.output.assign[function] atlib/tldr/src/formats/elf/layout/output.zig:21tiny.tldr.formats.elf.layout.output.countLive[function] atlib/tldr/src/formats/elf/layout/output.zig:13lib.tldr.src.formats.elf.link.addContributionRecords[function] — private source atlib/tldr/src/formats/elf/link.zig:648in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.addExternalTargetRecords[function] — private source atlib/tldr/src/formats/elf/link.zig:700in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.addGotEntryRecords[function] — private source atlib/tldr/src/formats/elf/link.zig:746in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.addMergePieceRecords[function] — private source atlib/tldr/src/formats/elf/link.zig:777in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.parseInputObject[function] — private source atlib/tldr/src/formats/elf/link.zig:343in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.requireEntrySymbol[function] — private source atlib/tldr/src/formats/elf/link.zig:489in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.requireResolvedRelocationSymbols[function] — private source atlib/tldr/src/formats/elf/link.zig:504in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.requireSupportedRelocations[function] — private source atlib/tldr/src/formats/elf/link.zig:410in nearest public ownerlib.tldr.src.formats.elf.linklib.tldr.src.formats.elf.link.resolveEntry[function] — private source atlib/tldr/src/formats/elf/link.zig:829in nearest public ownerlib.tldr.src.formats.elf.linktiny.tldr.formats.elf.payload.verifyMergePieceBytes[function] atlib/tldr/src/formats/elf/payload.zig:138tiny.tldr.formats.elf.relink.recordInputLinkEvidence[function] atlib/tldr/src/formats/elf/relink.zig:48tiny.tldr.formats.elf.symbol_table.collectGlobalSymbols[function] atlib/tldr/src/formats/elf/symbol.zig:20tiny.tldr.trace.product[function] atlib/tldr/src/trace.zig:51
Audit
| Definitions | 6 |
|---|---|
| Public names | 6 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |