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 }