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 }