lib/tldr/src/formats/elf/merge/target.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const root = @import("../../../root.zig");
3 const elf = @import("../root.zig");
4 const order = @import("order.zig");
5 const record = @import("record.zig");
6
7 const Allocator = std.mem.Allocator;
8 const model = root.model;
9 const OutputSection = elf.layout.OutputSection;
10 const SectionContribution = elf.layout.SectionContribution;
11 const output_section_count = elf.output_section.output_section_count;
12 const alignForwardU64 = elf.format.alignForwardU64;
13 const contributionReserveSize = elf.layout.contributionReserveSize;
14 const Record = record.Record;
15
16 pub fn assign(
17 allocator: Allocator,
18 output_sections: *[output_section_count]OutputSection,
19 records: []Record,
20 options: model.LinkOptions,
21 ) model.Error!void {
22 try order.records(allocator, records, options.max_link_jobs);
23
24 var head: ?*const Record = null;
25 for (records) |*current| {
26 if (head) |store| {
27 if (!record.sameStorageGroup(store.*, current.*)) {
28 head = null;
29 } else if (tailIntraOffset(current.*, store.*)) |intra_offset| {
30 if (!current.external_start or intra_offset == 0) {
31 current.piece.contribution = store.piece.contribution;
32 current.piece.output_intra_offset = intra_offset;
33 continue;
34 }
35 }
36 }
37
38 var output = &output_sections[current.output_index];
39 const aligned_offset = alignForwardU64(output.file_size, current.alignment);
40 const size: u64 = @intCast(current.bytes.len);
41 const reserved_size = contributionReserveSize(size, current.alignment, options);
42 const contribution = SectionContribution.init(
43 current.output_index,
44 aligned_offset,
45 size,
46 reserved_size,
47 current.alignment,
48 );
49 current.piece.contribution = contribution;
50 current.piece.output_intra_offset = 0;
51 output.file_size = aligned_offset + reserved_size;
52 output.memory_size = output.file_size;
53 head = current;
54 }
55 }
56
57 fn tailIntraOffset(current: Record, store: Record) ?u64 {
58 if (current.bytes.len > store.bytes.len) return null;
59 const intra_offset = store.bytes.len - current.bytes.len;
60 if (!std.mem.eql(u8, current.bytes, store.bytes[intra_offset..])) return null;
61 return @intCast(intra_offset);
62 }