lib/tldr/src/formats/elf/image/zero.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const root = @import("../../../root.zig");
 3 const elf = @import("../root.zig");
 4 
 5 const model = root.model;
 6 const ObjectFile = elf.parser.ObjectFile;
 7 const ObjectLayout = elf.layout.ObjectLayout;
 8 const OutputSection = elf.layout.OutputSection;
 9 const output_section_count = elf.output_section.output_section_count;
10 const contributionAt = elf.layout.contributionAt;
11 
12 pub fn unwrittenFileRanges(
13     image: []u8,
14     objects: []const ObjectFile,
15     layouts: []const ObjectLayout,
16     output_sections: []const OutputSection,
17     metadata_start: u64,
18     metadata_end: u64,
19     section_header_offset: u64,
20 ) model.Error!void {
21     var section_cursors = @as([output_section_count]u64, @splat(0));
22     var file_cursor: u64 = 0;
23     for (output_sections, 0..) |section, output_index| {
24         if (section.logicalSize() == 0) continue;
25         try range(image, file_cursor, section.file_offset);
26         if (section.kind.isNoBits()) {
27             file_cursor = section.file_offset;
28             continue;
29         }
30 
31         const section_end = section.file_offset + section.fileLoadSize();
32         section_cursors[output_index] = section.file_offset;
33         file_cursor = section_end;
34     }
35 
36     try contributionGaps(image, objects, layouts, output_sections, &section_cursors);
37 
38     for (output_sections, 0..) |section, output_index| {
39         if (section.logicalSize() == 0) continue;
40         if (section.kind.isNoBits()) continue;
41         try range(image, section_cursors[output_index], section.file_offset + section.fileLoadSize());
42     }
43 
44     try range(image, file_cursor, metadata_start);
45     try range(image, metadata_end, section_header_offset);
46 }
47 
48 fn contributionGaps(
49     image: []u8,
50     objects: []const ObjectFile,
51     layouts: []const ObjectLayout,
52     output_sections: []const OutputSection,
53     section_cursors: *[output_section_count]u64,
54 ) model.Error!void {
55     for (objects, 0..) |object, object_index| {
56         const object_layout = layouts[object_index];
57         for (object.sections, 0..) |section, section_index| {
58             if (section.section_type == std.elf.SHT_NOBITS) continue;
59             const contribution = contributionAt(object_layout.sections, section_index) orelse continue;
60             const output_index = contribution.outputIndex();
61             const output = output_sections[output_index];
62 
63             const payload_start = output.file_offset + contribution.offset;
64             const payload_end = payload_start + contribution.size;
65             const reserve_end = output.file_offset + contribution.offset + contribution.reserved_size;
66             try range(image, section_cursors[output_index], payload_start);
67             try range(image, payload_end, reserve_end);
68             section_cursors[output_index] = reserve_end;
69         }
70     }
71 }
72 
73 pub fn range(image: []u8, start: u64, end: u64) model.Error!void {
74     if (end < start) return error.InvalidRange;
75     if (start == end) return;
76     const image_len: u64 = @intCast(image.len);
77     if (end > image_len) return error.InvalidRange;
78     const first: usize = @intCast(start);
79     const last: usize = @intCast(end);
80     @memset(image[first..last], 0);
81 }