lib/tldr/src/formats/elf/relocation/kind.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const elf = @import("../root.zig");
3
4 const ObjectFile = elf.parser.ObjectFile;
5 const Symbol = elf.format.Symbol;
6 const Rela = elf.format.Rela;
7
8 pub fn isNone(relocation: Rela) bool {
9 return relocation.relocationType() == @backingInt(std.elf.R_X86_64.NONE);
10 }
11
12 pub fn applicationSupported(relocation_type: u32) bool {
13 return switch (relocation_type) {
14 @backingInt(std.elf.R_X86_64.NONE),
15 @backingInt(std.elf.R_X86_64.@"64"),
16 @backingInt(std.elf.R_X86_64.@"32"),
17 @backingInt(std.elf.R_X86_64.@"32S"),
18 @backingInt(std.elf.R_X86_64.@"16"),
19 @backingInt(std.elf.R_X86_64.@"8"),
20 @backingInt(std.elf.R_X86_64.PC64),
21 @backingInt(std.elf.R_X86_64.PC32),
22 @backingInt(std.elf.R_X86_64.PLT32),
23 @backingInt(std.elf.R_X86_64.PC16),
24 @backingInt(std.elf.R_X86_64.PC8),
25 @backingInt(std.elf.R_X86_64.GOTPCREL),
26 @backingInt(std.elf.R_X86_64.GOTPCRELX),
27 @backingInt(std.elf.R_X86_64.REX_GOTPCRELX),
28 @backingInt(std.elf.R_X86_64.SIZE32),
29 @backingInt(std.elf.R_X86_64.SIZE64),
30 @backingInt(std.elf.R_X86_64.TPOFF32),
31 @backingInt(std.elf.R_X86_64.TPOFF64),
32 @backingInt(std.elf.R_X86_64.DTPOFF32),
33 @backingInt(std.elf.R_X86_64.DTPOFF64),
34 @backingInt(std.elf.R_X86_64.GOTTPOFF),
35 @backingInt(std.elf.R_X86_64.TLSGD),
36 @backingInt(std.elf.R_X86_64.TLSLD),
37 => true,
38 else => false,
39 };
40 }
41
42 test "application support pins the apply switch arms" {
43 try std.testing.expect(applicationSupported(@backingInt(std.elf.R_X86_64.NONE)));
44 try std.testing.expect(applicationSupported(@backingInt(std.elf.R_X86_64.PC32)));
45 try std.testing.expect(applicationSupported(@backingInt(std.elf.R_X86_64.REX_GOTPCRELX)));
46 try std.testing.expect(applicationSupported(@backingInt(std.elf.R_X86_64.TLSLD)));
47 try std.testing.expect(!applicationSupported(@backingInt(std.elf.R_X86_64.GOT32)));
48 try std.testing.expect(!applicationSupported(@backingInt(std.elf.R_X86_64.COPY)));
49 try std.testing.expect(!applicationSupported(@backingInt(std.elf.R_X86_64.JUMP_SLOT)));
50 try std.testing.expect(!applicationSupported(@backingInt(std.elf.R_X86_64.TLSDESC)));
51 }
52
53 pub fn isRelaxedTlsRuntimeResolver(object: ObjectFile, relocations: []const Rela, relocation_index: usize) bool {
54 const relocation = relocations[relocation_index];
55 if (!isTlsRuntimeResolverRelocationType(relocation.relocationType())) return false;
56 if (relocation.symbolIndex() >= object.symbols.len) return false;
57 if (!isTlsRuntimeResolverSymbol(object.symbols[@intCast(relocation.symbolIndex())])) return false;
58
59 var index = relocation_index;
60 while (index > 0) {
61 index -= 1;
62 const marker = relocations[index];
63 if (isNone(marker)) continue;
64 if (!isTlsDynamicModelRelocationType(marker.relocationType())) return false;
65 if (relocation.offset <= marker.offset) return false;
66 return relocation.offset - marker.offset <= 12;
67 }
68 return false;
69 }
70
71 fn isTlsRuntimeResolverRelocationType(relocation_type: u32) bool {
72 return switch (relocation_type) {
73 @backingInt(std.elf.R_X86_64.PLT32),
74 @backingInt(std.elf.R_X86_64.GOTPCREL),
75 @backingInt(std.elf.R_X86_64.GOTPCRELX),
76 @backingInt(std.elf.R_X86_64.REX_GOTPCRELX),
77 => true,
78 else => false,
79 };
80 }
81
82 fn isTlsDynamicModelRelocationType(relocation_type: u32) bool {
83 return switch (relocation_type) {
84 @backingInt(std.elf.R_X86_64.TLSGD),
85 @backingInt(std.elf.R_X86_64.TLSLD),
86 => true,
87 else => false,
88 };
89 }
90
91 fn isTlsRuntimeResolverSymbol(symbol: Symbol) bool {
92 return std.mem.eql(u8, symbol.name, "__tls_get_addr");
93 }