lib/tldr/src/formats/elf/merge/lookup.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const elf = @import("../root.zig");
 2 
 3 const ObjectFile = elf.parser.ObjectFile;
 4 const ObjectLayout = elf.layout.ObjectLayout;
 5 const OutputSection = elf.layout.OutputSection;
 6 const SectionContribution = elf.layout.SectionContribution;
 7 const MergePieceLayout = elf.layout.MergePieceLayout;
 8 const mergeSectionLayout = elf.layout.mergeSection;
 9 
10 pub const Piece = struct {
11     contribution: SectionContribution,
12     intra_offset: u64,
13 };
14 
15 pub fn address(
16     object_layout: ObjectLayout,
17     object: ObjectFile,
18     output_sections: []const OutputSection,
19     section_index: usize,
20     offset: u64,
21 ) ?u64 {
22     const entry = piece(object_layout, object, section_index, offset) orelse return null;
23     const output = output_sections[entry.contribution.outputIndex()];
24     return output.address + entry.contribution.offset + entry.intra_offset;
25 }
26 
27 pub fn contribution(
28     object_layout: ObjectLayout,
29     object: ObjectFile,
30     section_index: usize,
31     offset: u64,
32 ) ?SectionContribution {
33     const entry = piece(object_layout, object, section_index, offset) orelse return null;
34     return entry.contribution;
35 }
36 
37 pub fn piece(
38     object_layout: ObjectLayout,
39     object: ObjectFile,
40     section_index: usize,
41     offset: u64,
42 ) ?Piece {
43     const merge_section = mergeSectionLayout(object_layout, section_index) orelse return null;
44     const section = object.sections[section_index];
45     if (offset >= section.size) return null;
46 
47     if (merge_section.fixed_piece_size != 0) {
48         const piece_index: usize = @intCast(offset / merge_section.fixed_piece_size);
49         if (piece_index >= merge_section.pieces.len) return null;
50         const fixed_piece = merge_section.pieces[piece_index];
51         return .{
52             .contribution = fixed_piece.contribution,
53             .intra_offset = fixed_piece.output_intra_offset + offset % merge_section.fixed_piece_size,
54         };
55     }
56 
57     const string_piece = stringPiece(merge_section.pieces, offset) orelse return null;
58     return .{
59         .contribution = string_piece.contribution,
60         .intra_offset = string_piece.output_intra_offset + offset - string_piece.input_offset,
61     };
62 }
63 
64 fn stringPiece(pieces: []const MergePieceLayout, offset: u64) ?MergePieceLayout {
65     var low: usize = 0;
66     var high: usize = pieces.len;
67     while (low < high) {
68         const mid = low + (high - low) / 2;
69         const current = pieces[mid];
70         if (offset < current.input_offset) {
71             high = mid;
72         } else if (offset >= current.input_offset + current.size) {
73             low = mid + 1;
74         } else {
75             return current;
76         }
77     }
78     return null;
79 }