lib/tldr/src/formats/elf/icf/match.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 Rela = elf.format.Rela;
 8 const Symbol = elf.format.Symbol;
 9 const sectionBytes = elf.format.sectionBytes;
10 
11 pub fn sections(
12     left_object: ObjectFile,
13     left_index: usize,
14     right_object: ObjectFile,
15     right_index: usize,
16 ) model.Error!bool {
17     const left = left_object.sections[left_index];
18     const right = right_object.sections[right_index];
19     if (left.section_type != right.section_type) return false;
20     if (left.flags != right.flags) return false;
21     if (@max(left.alignment, 1) != @max(right.alignment, 1)) return false;
22     if (left.size != right.size) return false;
23 
24     const left_bytes = try sectionBytes(left_object.bytes, left);
25     const right_bytes = try sectionBytes(right_object.bytes, right);
26     if (!std.mem.eql(u8, left_bytes, right_bytes)) return false;
27 
28     return relocations(
29         left_object,
30         left_object.relocationsForSection(left_index),
31         right_object,
32         right_object.relocationsForSection(right_index),
33     );
34 }
35 
36 fn relocations(
37     left_object: ObjectFile,
38     left_relocations: []const Rela,
39     right_object: ObjectFile,
40     right_relocations: []const Rela,
41 ) model.Error!bool {
42     var left_index: usize = 0;
43     var right_index: usize = 0;
44     while (true) {
45         const left = nextRelocation(left_relocations, &left_index);
46         const right = nextRelocation(right_relocations, &right_index);
47         if (left == null or right == null) return left == null and right == null;
48         const left_relocation = left.?;
49         const right_relocation = right.?;
50 
51         if (left_relocation.offset != right_relocation.offset) return false;
52         if (left_relocation.relocationType() != right_relocation.relocationType()) return false;
53         if (left_relocation.addend != right_relocation.addend) return false;
54         if (left_relocation.symbolIndex() >= left_object.symbols.len) return error.UndefinedSymbol;
55         if (right_relocation.symbolIndex() >= right_object.symbols.len) return error.UndefinedSymbol;
56         if (!targets(
57             left_object.symbols[@intCast(left_relocation.symbolIndex())],
58             right_object.symbols[@intCast(right_relocation.symbolIndex())],
59         )) return false;
60     }
61 }
62 
63 fn nextRelocation(relocations_input: []const Rela, index: *usize) ?Rela {
64     while (index.* < relocations_input.len) {
65         const entry = relocations_input[index.*];
66         index.* += 1;
67         if (!elf.relocation.isNone(entry)) return entry;
68     }
69     return null;
70 }
71 
72 fn targets(left: Symbol, right: Symbol) bool {
73     if (left.name.len == 0 or right.name.len == 0) return false;
74     if (left.binding() == std.elf.STB_LOCAL or right.binding() == std.elf.STB_LOCAL) return false;
75     if (left.kind() != right.kind()) return false;
76     if (left.isUndefined() != right.isUndefined()) return false;
77     if (left.isCommon() != right.isCommon()) return false;
78     return std.mem.eql(u8, left.name, right.name);
79 }