lib/tldr/src/formats/elf/liveness/symbols.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const root = @import("../../../root.zig");
  3 const elf = @import("../root.zig");
  4 const state = @import("state.zig");
  5 
  6 const model = root.model;
  7 const GlobalSymbol = elf.layout.GlobalSymbol;
  8 const ObjectFile = elf.parser.ObjectFile;
  9 const SectionRef = elf.parser.SectionRef;
 10 const State = state.State;
 11 const SymbolRef = elf.layout.SymbolRef;
 12 const SyntheticBoundary = elf.addressing.Boundary;
 13 const boundarySectionNameMatches = elf.addressing.boundarySectionNameMatches;
 14 const foldedSection = elf.section_state.foldedSection;
 15 const sectionDiscarded = elf.section_state.sectionDiscarded;
 16 const sectionIsAllocated = elf.format.sectionIsAllocated;
 17 const sectionNameOrEmpty = elf.parser.sectionNameOrEmpty;
 18 const symbolSectionDiscarded = elf.section_state.symbolSectionDiscarded;
 19 const syntheticBoundaryForSymbol = elf.addressing.boundaryForSymbol;
 20 
 21 pub fn mark(
 22     objects: []const ObjectFile,
 23     globals: *const std.StringHashMapUnmanaged(GlobalSymbol),
 24     live: *State,
 25     symbol_ref: SymbolRef,
 26     options: model.LinkOptions,
 27 ) model.Error!void {
 28     if (symbol_ref.object_index >= objects.len) return error.InvalidObject;
 29     const object = objects[symbol_ref.object_index];
 30     if (symbol_ref.symbol_index >= object.symbols.len) return error.UndefinedSymbol;
 31 
 32     const symbol = object.symbols[symbol_ref.symbol_index];
 33     if (symbol.isUndefined()) {
 34         const global = globals.get(symbol.name) orelse {
 35             if (symbol.isWeakUndefined()) return;
 36             const boundary = syntheticBoundaryForSymbol(symbol.name) orelse {
 37                 elf.diagnostic.recordUndefinedSymbol(options, object, symbol);
 38                 return error.UndefinedSymbol;
 39             };
 40             if (try markSyntheticBoundarySections(objects, live, boundary)) return;
 41             if (boundary.optional) return;
 42             elf.diagnostic.recordUndefinedSymbol(options, object, symbol);
 43             return error.UndefinedSymbol;
 44         };
 45         return mark(objects, globals, live, global.ref, options);
 46     }
 47     if (symbolSectionDiscarded(object, symbol) and symbol.name.len != 0) {
 48         const global = globals.get(symbol.name) orelse return error.MissingSection;
 49         return mark(objects, globals, live, global.ref, options);
 50     }
 51     if (symbol.isCommon()) return;
 52     if (symbol.isAbsolute()) return;
 53     if (symbol.section_index >= object.sections.len) return error.UnsupportedRelocation;
 54 
 55     try state.markSection(
 56         live,
 57         objects,
 58         .{
 59             .object_index = symbol_ref.object_index,
 60             .section_index = symbol.section_index,
 61         },
 62     );
 63 }
 64 
 65 fn markSyntheticBoundarySections(
 66     objects: []const ObjectFile,
 67     live: *State,
 68     boundary: SyntheticBoundary,
 69 ) model.Error!bool {
 70     var found = false;
 71     for (objects, 0..) |object, object_index| {
 72         for (object.sections, 0..) |section, section_index| {
 73             if (!sectionIsAllocated(section)) continue;
 74             if (section.size == 0) continue;
 75             if (sectionDiscarded(object, section_index)) continue;
 76             if (foldedSection(object, section_index) != null) continue;
 77             if (!boundarySectionNameMatches(boundary, sectionNameOrEmpty(object, section_index))) continue;
 78             try state.markSection(
 79                 live,
 80                 objects,
 81                 .{
 82                     .object_index = object_index,
 83                     .section_index = section_index,
 84                 },
 85             );
 86             found = true;
 87         }
 88     }
 89     return found;
 90 }
 91 
 92 pub fn markRelocationTargets(
 93     objects: []const ObjectFile,
 94     globals: *const std.StringHashMapUnmanaged(GlobalSymbol),
 95     live: *State,
 96     section_ref: SectionRef,
 97     options: model.LinkOptions,
 98 ) model.Error!void {
 99     const object = objects[section_ref.object_index];
100     for (object.relocationsForSection(section_ref.section_index)) |entry| {
101         if (elf.relocation.isNone(entry)) continue;
102         if (entry.symbolIndex() >= object.symbols.len) return error.UndefinedSymbol;
103         try mark(
104             objects,
105             globals,
106             live,
107             .{
108                 .object_index = section_ref.object_index,
109                 .symbol_index = @intCast(entry.symbolIndex()),
110             },
111             options,
112         );
113     }
114 }