lib/tldr/src/formats/elf/archive/object.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const root = @import("../../../root.zig");
  3 const elf = @import("../root.zig");
  4 const definition = @import("definition.zig");
  5 
  6 const Allocator = std.mem.Allocator;
  7 const model = root.model;
  8 const ObjectFile = elf.parser.ObjectFile;
  9 const Symbol = elf.format.Symbol;
 10 const globalSymbolCanBeAdded = elf.symbol_table.globalSymbolCanBeAdded;
 11 
 12 pub fn record(
 13     allocator: Allocator,
 14     objects: []const ObjectFile,
 15     object_index: usize,
 16     definitions: *definition.Index,
 17     unresolved_names: *usize,
 18     active_candidate_counts: []usize,
 19     pending: *definition.Queue,
 20 ) model.Error!void {
 21     const parsed_object = objects[object_index];
 22     for (parsed_object.symbols) |symbol| {
 23         try recordSymbol(
 24             allocator,
 25             symbol,
 26             globalSymbolCanBeAdded(parsed_object, symbol),
 27             definitions,
 28             unresolved_names,
 29             active_candidate_counts,
 30             pending,
 31         );
 32     }
 33 }
 34 
 35 pub fn recordSymbols(
 36     allocator: Allocator,
 37     symbols: []const Symbol,
 38     definitions: *definition.Index,
 39     unresolved_names: *usize,
 40     active_candidate_counts: []usize,
 41     pending: *definition.Queue,
 42 ) model.Error!void {
 43     for (symbols) |symbol| {
 44         try recordSymbol(
 45             allocator,
 46             symbol,
 47             symbol.isGlobalDefinition(),
 48             definitions,
 49             unresolved_names,
 50             active_candidate_counts,
 51             pending,
 52         );
 53     }
 54 }
 55 
 56 fn recordSymbol(
 57     allocator: Allocator,
 58     symbol: Symbol,
 59     records_definition: bool,
 60     definitions: *definition.Index,
 61     unresolved_names: *usize,
 62     active_candidate_counts: []usize,
 63     pending: *definition.Queue,
 64 ) model.Error!void {
 65     if (records_definition) {
 66         return definition.define(allocator, definitions, unresolved_names, active_candidate_counts, symbol.name);
 67     }
 68     if (!symbol.isUndefined()) return;
 69     if (symbol.name.len == 0) return;
 70     if (symbol.binding() != std.elf.STB_GLOBAL) return;
 71     try definition.require(allocator, definitions, unresolved_names, active_candidate_counts, pending, symbol.name);
 72 }
 73 
 74 fn testSymbol(name: []const u8, section_index: u16, symbol_binding: u8) Symbol {
 75     return .{
 76         .name_offset = 0,
 77         .info = symbol_binding << 4,
 78         .other = 0,
 79         .section_index = section_index,
 80         .value = 0,
 81         .size = 0,
 82         .name = name,
 83     };
 84 }
 85 
 86 test "recording symbols resolves required names through definitions" {
 87     const allocator = std.testing.allocator;
 88     var definitions: definition.Index = .{};
 89     defer definition.deinit(allocator, &definitions);
 90     var counts = [_]usize{0};
 91     var pending = definition.Queue.initContext({});
 92     defer pending.deinit(allocator);
 93     var unresolved_names: usize = 0;
 94 
 95     try definition.add(allocator, &definitions, "puts", 0, &counts, &pending);
 96 
 97     const undefined_global = testSymbol("puts", std.elf.SHN_UNDEF, std.elf.STB_GLOBAL);
 98     const undefined_weak = testSymbol("vfork", std.elf.SHN_UNDEF, std.elf.STB_WEAK);
 99     const undefined_local = testSymbol("tls", std.elf.SHN_UNDEF, std.elf.STB_LOCAL);
100     try recordSymbols(
101         allocator,
102         &.{ undefined_global, undefined_weak, undefined_local },
103         &definitions,
104         &unresolved_names,
105         &counts,
106         &pending,
107     );
108     try std.testing.expectEqual(@as(usize, 1), unresolved_names);
109     try std.testing.expectEqual(@as(usize, 1), counts[0]);
110     try std.testing.expectEqual(@as(?usize, 0), pending.peek());
111 
112     const defining_global = testSymbol("puts", 1, std.elf.STB_GLOBAL);
113     try recordSymbols(allocator, &.{defining_global}, &definitions, &unresolved_names, &counts, &pending);
114     try std.testing.expectEqual(@as(usize, 0), unresolved_names);
115     try std.testing.expectEqual(@as(usize, 0), counts[0]);
116 
117     try recordSymbols(allocator, &.{undefined_global}, &definitions, &unresolved_names, &counts, &pending);
118     try std.testing.expectEqual(@as(usize, 0), unresolved_names);
119     try std.testing.expectEqual(@as(usize, 0), counts[0]);
120 }