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 }