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 }