lib/tldr/src/formats/elf/address/tls.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const root = @import("../../../root.zig");
 3 const elf = @import("../root.zig");
 4 const cache = @import("cache.zig");
 5 const contribution_module = @import("contribution.zig");
 6 
 7 const model = root.model;
 8 const format = elf.format;
 9 const layout = elf.layout;
10 const program = elf.program;
11 const section_state = elf.section_state;
12 
13 const Cache = cache.Cache;
14 const GlobalSymbol = layout.GlobalSymbol;
15 const ObjectFile = elf.parser.ObjectFile;
16 const ObjectLayout = layout.ObjectLayout;
17 const OutputSection = layout.OutputSection;
18 const Symbol = format.Symbol;
19 const SymbolRef = layout.SymbolRef;
20 const symbolSectionDiscarded = section_state.symbolSectionDiscarded;
21 const tlsSegment = program.tlsSegment;
22 
23 pub fn offset(
24     objects: []const ObjectFile,
25     layouts: []const ObjectLayout,
26     output_sections: []const OutputSection,
27     globals: *const std.StringHashMapUnmanaged(GlobalSymbol),
28     symbol_addresses: *Cache,
29     object_index: usize,
30     symbol_index: usize,
31 ) model.Error!u64 {
32     if (symbol_index >= objects[object_index].symbols.len) return error.UndefinedSymbol;
33 
34     const object = objects[object_index];
35     const symbol_record = object.symbols[symbol_index];
36     if (symbol_record.isUndefined()) {
37         const global = globals.get(symbol_record.name) orelse {
38             if (symbol_record.isWeakUndefined()) return 0;
39             return error.UndefinedSymbol;
40         };
41         return offset(objects, layouts, output_sections, globals, symbol_addresses, global.ref.object_index, global.ref.symbol_index);
42     }
43     if (symbolSectionDiscarded(object, symbol_record) and symbol_record.name.len != 0) {
44         const global = globals.get(symbol_record.name) orelse return error.MissingSection;
45         const current_ref = SymbolRef{ .object_index = object_index, .symbol_index = symbol_index };
46         if (global.ref.eql(current_ref)) return error.MissingSection;
47         return offset(objects, layouts, output_sections, globals, symbol_addresses, global.ref.object_index, global.ref.symbol_index);
48     }
49     if (symbol_record.isCommon() and symbol_record.name.len != 0) {
50         const global = globals.get(symbol_record.name) orelse return error.UndefinedSymbol;
51         const current_ref = SymbolRef{ .object_index = object_index, .symbol_index = symbol_index };
52         if (!global.ref.eql(current_ref)) return offset(objects, layouts, output_sections, globals, symbol_addresses, global.ref.object_index, global.ref.symbol_index);
53     }
54     if (symbol_record.isAbsolute() or symbol_record.isCommon()) return error.UnsupportedRelocation;
55     if (!isSymbol(object, symbol_record)) return error.UnsupportedRelocation;
56 
57     const symbol_contribution = try contribution_module.symbol(objects, layouts, object_index, symbol_index);
58     const output = output_sections[symbol_contribution.outputIndex()];
59     if (!output.kind.isTls()) return error.UnsupportedRelocation;
60     const segment = tlsSegment(output_sections) orelse return error.MissingSection;
61     return output.address - segment.address + symbol_contribution.offset + symbol_record.value;
62 }
63 
64 pub fn isSymbol(object: ObjectFile, symbol_record: Symbol) bool {
65     if (symbol_record.kind() == std.elf.STT_TLS) return true;
66     if (symbol_record.isUndefined() or symbol_record.isCommon() or symbol_record.isAbsolute()) return false;
67     if (symbol_record.section_index >= object.sections.len) return false;
68     return (object.sections[symbol_record.section_index].flags & std.elf.SHF_TLS) != 0;
69 }