diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-07-01 17:25:51 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-07-15 18:49:46 +0200 |
| commit | 2b3bda43e352152f0150bf2e795419cf1bcfcd90 (patch) | |
| tree | f6c550980ea30b8e3ded451b6145ebb203101b22 /src/link/MachO | |
| parent | 3622fe08dbdcaccb04204b48257e1d5fcbe0d164 (diff) | |
| download | zig-2b3bda43e352152f0150bf2e795419cf1bcfcd90.tar.gz zig-2b3bda43e352152f0150bf2e795419cf1bcfcd90.zip | |
zld: abstract Symbol creation logic
Diffstat (limited to 'src/link/MachO')
| -rw-r--r-- | src/link/MachO/Dylib.zig | 22 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 35 | ||||
| -rw-r--r-- | src/link/MachO/StringTable.zig | 34 | ||||
| -rw-r--r-- | src/link/MachO/Symbol.zig | 189 | ||||
| -rw-r--r-- | src/link/MachO/Zld.zig | 133 |
5 files changed, 230 insertions, 183 deletions
diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 324c54d362..cfd5ae18d3 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -146,7 +146,12 @@ pub const CreateOpts = struct { id: ?Id = null, }; -pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8, opts: CreateOpts) Error!?[]*Dylib { +pub fn createAndParseFromPath( + allocator: *Allocator, + arch: Arch, + path: []const u8, + opts: CreateOpts, +) Error!?[]*Dylib { const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) { error.FileNotFound => return null, else => |e| return e, @@ -505,18 +510,7 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void { pub fn createProxy(self: *Dylib, sym_name: []const u8) !?*Symbol { if (!self.symbols.contains(sym_name)) return null; - - const name = try self.allocator.dupe(u8, sym_name); - const proxy = try self.allocator.create(Symbol.Proxy); - errdefer self.allocator.destroy(proxy); - - proxy.* = .{ - .base = .{ - .@"type" = .proxy, - .name = name, - }, + return Symbol.Proxy.new(self.allocator, sym_name, .{ .file = self, - }; - - return &proxy.base; + }); } diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index cb55dd1fd8..197c302316 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -9,12 +9,12 @@ const log = std.log.scoped(.object); const macho = std.macho; const mem = std.mem; const reloc = @import("reloc.zig"); +const parseName = @import("Zld.zig").parseName; const Allocator = mem.Allocator; const Arch = std.Target.Cpu.Arch; const Relocation = reloc.Relocation; const Symbol = @import("Symbol.zig"); -const parseName = @import("Zld.zig").parseName; usingnamespace @import("commands.zig"); @@ -437,47 +437,26 @@ pub fn parseSymbols(self: *Object) !void { if (Symbol.isWeakDef(sym) or Symbol.isPext(sym)) break :linkage .linkage_unit; break :linkage .global; }; - const regular = try self.allocator.create(Symbol.Regular); - errdefer self.allocator.destroy(regular); - regular.* = .{ - .base = .{ - .@"type" = .regular, - .name = name, - }, + break :symbol try Symbol.Regular.new(self.allocator, name, .{ .linkage = linkage, .address = sym.n_value, .section = sym.n_sect - 1, .weak_ref = Symbol.isWeakRef(sym), .file = self, - }; - break :symbol ®ular.base; + }); } if (sym.n_value != 0) { - const tentative = try self.allocator.create(Symbol.Tentative); - errdefer self.allocator.destroy(tentative); - tentative.* = .{ - .base = .{ - .@"type" = .tentative, - .name = name, - }, + break :symbol try Symbol.Tentative.new(self.allocator, name, .{ .size = sym.n_value, .alignment = (sym.n_desc >> 8) & 0x0f, .file = self, - }; - break :symbol &tentative.base; + }); } - const undef = try self.allocator.create(Symbol.Unresolved); - errdefer self.allocator.destroy(undef); - undef.* = .{ - .base = .{ - .@"type" = .unresolved, - .name = name, - }, + break :symbol try Symbol.Unresolved.new(self.allocator, name, .{ .file = self, - }; - break :symbol &undef.base; + }); }; try self.symbols.append(self.allocator, symbol); diff --git a/src/link/MachO/StringTable.zig b/src/link/MachO/StringTable.zig index 5437c70476..43770afdc1 100644 --- a/src/link/MachO/StringTable.zig +++ b/src/link/MachO/StringTable.zig @@ -8,7 +8,6 @@ const Allocator = mem.Allocator; allocator: *Allocator, buffer: std.ArrayListUnmanaged(u8) = .{}, -used_offsets: std.ArrayListUnmanaged(u32) = .{}, cache: std.StringHashMapUnmanaged(u32) = .{}, pub const Error = error{OutOfMemory}; @@ -22,8 +21,13 @@ pub fn init(allocator: *Allocator) Error!StringTable { } pub fn deinit(self: *StringTable) void { + { + var it = self.cache.keyIterator(); + while (it.next()) |key| { + self.allocator.free(key.*); + } + } self.cache.deinit(self.allocator); - self.used_offsets.deinit(self.allocator); self.buffer.deinit(self.allocator); } @@ -33,8 +37,6 @@ pub fn getOrPut(self: *StringTable, string: []const u8) Error!u32 { return off; } - const invalidate_cache = self.needsToGrow(string.len + 1); - try self.buffer.ensureUnusedCapacity(self.allocator, string.len + 1); const new_off = @intCast(u32, self.buffer.items.len); @@ -43,25 +45,7 @@ pub fn getOrPut(self: *StringTable, string: []const u8) Error!u32 { self.buffer.appendSliceAssumeCapacity(string); self.buffer.appendAssumeCapacity(0); - if (invalidate_cache) { - log.debug("invalidating cache", .{}); - // Re-create the cache. - self.cache.clearRetainingCapacity(); - for (self.used_offsets.items) |off| { - try self.cache.putNoClobber(self.allocator, self.get(off).?, off); - } - } - - { - log.debug("cache:", .{}); - var it = self.cache.iterator(); - while (it.next()) |entry| { - log.debug(" | {s} => {}", .{ entry.key_ptr.*, entry.value_ptr.* }); - } - } - - try self.cache.putNoClobber(self.allocator, self.get(new_off).?, new_off); - try self.used_offsets.append(self.allocator, new_off); + try self.cache.putNoClobber(self.allocator, try self.allocator.dupe(u8, string), new_off); return new_off; } @@ -78,7 +62,3 @@ pub fn asSlice(self: StringTable) []const u8 { pub fn size(self: StringTable) u64 { return self.buffer.items.len; } - -fn needsToGrow(self: StringTable, needed_space: u64) bool { - return self.buffer.capacity < needed_space + self.size(); -} diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig index 8da4704909..59a6f3d836 100644 --- a/src/link/MachO/Symbol.zig +++ b/src/link/MachO/Symbol.zig @@ -7,6 +7,7 @@ const mem = std.mem; const Allocator = mem.Allocator; const Dylib = @import("Dylib.zig"); const Object = @import("Object.zig"); +const StringTable = @import("StringTable.zig"); pub const Type = enum { regular, @@ -19,7 +20,7 @@ pub const Type = enum { @"type": Type, /// Symbol name. Owned slice. -name: []u8, +name: []const u8, /// Alias of. alias: ?*Symbol = null, @@ -43,23 +44,14 @@ pub const Regular = struct { section: u8, /// Whether the symbol is a weak ref. - weak_ref: bool, + weak_ref: bool = false, /// Object file where to locate this symbol. - file: *Object, + /// null means self-reference. + file: ?*Object = null, /// Debug stab if defined. - stab: ?struct { - /// Stab kind - kind: enum { - function, - global, - static, - }, - - /// Size of the stab. - size: u64, - } = null, + stab: ?Stab = null, /// True if symbol was already committed into the final /// symbol table. @@ -73,6 +65,68 @@ pub const Regular = struct { global, }; + pub const Stab = struct { + /// Stab kind + kind: enum { + function, + global, + static, + }, + + /// Size of the stab. + size: u64, + }; + + const Opts = struct { + linkage: Linkage = .translation_unit, + address: u64 = 0, + section: u8 = 0, + weak_ref: bool = false, + file: ?*Object = null, + stab: ?Stab = null, + }; + + pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol { + const reg = try allocator.create(Regular); + errdefer allocator.destroy(reg); + + reg.* = .{ + .base = .{ + .@"type" = .regular, + .name = try allocator.dupe(u8, name), + }, + .linkage = opts.linkage, + .address = opts.address, + .section = opts.section, + .weak_ref = opts.weak_ref, + .file = opts.file, + .stab = opts.stab, + }; + + return ®.base; + } + + pub fn asNlist(regular: *Regular, strtab: *StringTable) !macho.nlist_64 { + const n_strx = try strtab.getOrPut(regular.base.name); + var nlist = macho.nlist_64{ + .n_strx = n_strx, + .n_type = macho.N_SECT, + .n_sect = regular.section, + .n_desc = 0, + .n_value = regular.address, + }; + + if (regular.linkage != .translation_unit) { + nlist.n_type |= macho.N_EXT; + } + if (regular.linkage == .linkage_unit) { + nlist.n_type |= macho.N_PEXT; + nlist.n_desc |= macho.N_WEAK_DEF; + } + + return nlist; + } + pub fn isTemp(regular: *Regular) bool { if (regular.linkage == .translation_unit) { return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L"); @@ -97,6 +151,36 @@ pub const Proxy = struct { pub const base_type: Symbol.Type = .proxy; + const Opts = struct { + file: ?*Dylib = null, + }; + + pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol { + const proxy = try allocator.create(Proxy); + errdefer allocator.destroy(proxy); + + proxy.* = .{ + .base = .{ + .@"type" = .proxy, + .name = try allocator.dupe(u8, name), + }, + .file = opts.file, + }; + + return &proxy.base; + } + + pub fn asNlist(proxy: *Proxy, strtab: *StringTable) !macho.nlist_64 { + const n_strx = try strtab.getOrPut(proxy.base.name); + return macho.nlist_64{ + .n_strx = n_strx, + .n_type = macho.N_UNDF | macho.N_EXT, + .n_sect = 0, + .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, + .n_value = 0, + }; + } + pub fn deinit(proxy: *Proxy, allocator: *Allocator) void { proxy.bind_info.deinit(allocator); } @@ -115,6 +199,36 @@ pub const Unresolved = struct { file: ?*Object = null, pub const base_type: Symbol.Type = .unresolved; + + const Opts = struct { + file: ?*Object = null, + }; + + pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol { + const undef = try allocator.create(Unresolved); + errdefer allocator.destroy(undef); + + undef.* = .{ + .base = .{ + .@"type" = .unresolved, + .name = try allocator.dupe(u8, name), + }, + .file = opts.file, + }; + + return &undef.base; + } + + pub fn asNlist(undef: *Unresolved, strtab: *StringTable) !macho.nlist_64 { + const n_strx = try strtab.getOrPut(undef.base.name); + return macho.nlist_64{ + .n_strx = n_strx, + .n_type = macho.N_UNDF, + .n_sect = 0, + .n_desc = 0, + .n_value = 0, + }; + } }; pub const Tentative = struct { @@ -127,13 +241,49 @@ pub const Tentative = struct { alignment: u16, /// File where this symbol was referenced. - file: *Object, + file: ?*Object = null, pub const base_type: Symbol.Type = .tentative; + + const Opts = struct { + size: u64 = 0, + alignment: u16 = 0, + file: ?*Object = null, + }; + + pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol { + const tent = try allocator.create(Tentative); + errdefer allocator.destroy(tent); + + tent.* = .{ + .base = .{ + .@"type" = .tentative, + .name = try allocator.dupe(u8, name), + }, + .size = opts.size, + .alignment = opts.alignment, + .file = opts.file, + }; + + return &tent.base; + } + + pub fn asNlist(tent: *Tentative, strtab: *StringTable) !macho.nlist_64 { + // TODO + const n_strx = try strtab.getOrPut(tent.base.name); + return macho.nlist_64{ + .n_strx = n_strx, + .n_type = macho.N_UNDF, + .n_sect = 0, + .n_desc = 0, + .n_value = 0, + }; + } }; pub fn deinit(base: *Symbol, allocator: *Allocator) void { allocator.free(base.name); + switch (base.@"type") { .proxy => @fieldParentPtr(Proxy, "base", base).deinit(allocator), else => {}, @@ -154,6 +304,15 @@ pub fn getTopmostAlias(base: *Symbol) *Symbol { return base; } +pub fn asNlist(base: *Symbol, strtab: *StringTable) !macho.nlist_64 { + return switch (base.tag) { + .regular => @fieldParentPtr(Regular, "base", base).asNlist(strtab), + .proxy => @fieldParentPtr(Proxy, "base", base).asNlist(strtab), + .unresolved => @fieldParentPtr(Unresolved, "base", base).asNlist(strtab), + .tentative => @fieldParentPtr(Tentative, "base", base).asNlist(strtab), + }; +} + pub fn isStab(sym: macho.nlist_64) bool { return (macho.N_STAB & sym.n_type) != 0; } diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index d223e04fd7..a20879f856 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -17,6 +17,7 @@ const Archive = @import("Archive.zig"); const CodeSignature = @import("CodeSignature.zig"); const Dylib = @import("Dylib.zig"); const Object = @import("Object.zig"); +const StringTable = @import("StringTable.zig"); const Symbol = @import("Symbol.zig"); const Trie = @import("Trie.zig"); @@ -24,6 +25,7 @@ usingnamespace @import("commands.zig"); usingnamespace @import("bind.zig"); allocator: *Allocator, +strtab: StringTable, target: ?std.Target = null, page_size: ?u16 = null, @@ -109,9 +111,6 @@ tentatives: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, /// Set if the linker found tentative definitions in any of the objects. tentative_defs_offset: u64 = 0, -strtab: std.ArrayListUnmanaged(u8) = .{}, -strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, - threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, stubs: std.ArrayListUnmanaged(*Symbol) = .{}, @@ -138,8 +137,11 @@ const TlvOffset = struct { /// Default path to dyld const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; -pub fn init(allocator: *Allocator) Zld { - return .{ .allocator = allocator }; +pub fn init(allocator: *Allocator) !Zld { + return Zld{ + .allocator = allocator, + .strtab = try StringTable.init(allocator), + }; } pub fn deinit(self: *Zld) void { @@ -180,15 +182,7 @@ pub fn deinit(self: *Zld) void { self.tentatives.deinit(self.allocator); self.globals.deinit(self.allocator); self.unresolved.deinit(self.allocator); - self.strtab.deinit(self.allocator); - - { - var it = self.strtab_dir.keyIterator(); - while (it.next()) |key| { - self.allocator.free(key.*); - } - } - self.strtab_dir.deinit(self.allocator); + self.strtab.deinit(); } pub fn closeFiles(self: Zld) void { @@ -1137,16 +1131,7 @@ fn allocateTentativeSymbols(self: *Zld) !void { // Convert tentative definitions into regular symbols. for (self.tentatives.values()) |sym| { const tent = sym.cast(Symbol.Tentative) orelse unreachable; - const reg = try self.allocator.create(Symbol.Regular); - errdefer self.allocator.destroy(reg); - - reg.* = .{ - .base = .{ - .@"type" = .regular, - .name = try self.allocator.dupe(u8, tent.base.name), - .got_index = tent.base.got_index, - .stubs_index = tent.base.stubs_index, - }, + const reg = try Symbol.Regular.new(self.allocator, tent.base.name, .{ .linkage = .global, .address = base_address, .section = section, @@ -1156,16 +1141,18 @@ fn allocateTentativeSymbols(self: *Zld) !void { .kind = .global, .size = 0, }, - }; + }); + reg.got_index = tent.base.got_index; + reg.stubs_index = tent.base.stubs_index; - try self.globals.putNoClobber(self.allocator, reg.base.name, ®.base); - tent.base.alias = ®.base; + try self.globals.putNoClobber(self.allocator, reg.name, reg); + tent.base.alias = reg; if (tent.base.got_index) |idx| { - self.got_entries.items[idx] = ®.base; + self.got_entries.items[idx] = reg; } if (tent.base.stubs_index) |idx| { - self.stubs.items[idx] = ®.base; + self.stubs.items[idx] = reg; } const address = mem.alignForwardGeneric(u64, base_address + tent.size, alignment); @@ -1615,15 +1602,8 @@ fn resolveSymbols(self: *Zld) !void { { const name = try self.allocator.dupe(u8, "dyld_stub_binder"); errdefer self.allocator.free(name); - const undef = try self.allocator.create(Symbol.Unresolved); - errdefer self.allocator.destroy(undef); - undef.* = .{ - .base = .{ - .@"type" = .unresolved, - .name = name, - }, - }; - try unresolved.append(&undef.base); + const undef = try Symbol.Unresolved.new(self.allocator, name, .{}); + try unresolved.append(undef); } var referenced = std.AutoHashMap(*Dylib, void).init(self.allocator); @@ -1641,16 +1621,7 @@ fn resolveSymbols(self: *Zld) !void { // TODO this is just a temp patch until I work out what to actually // do with ___dso_handle and __mh_execute_header symbols which are // synthetically created by the linker on macOS. - const name = try self.allocator.dupe(u8, undef.name); - const proxy = try self.allocator.create(Symbol.Proxy); - errdefer self.allocator.destroy(proxy); - proxy.* = .{ - .base = .{ - .@"type" = .proxy, - .name = name, - }, - }; - break :inner &proxy.base; + break :inner try Symbol.Proxy.new(self.allocator, undef.name, .{}); } self.unresolved.putAssumeCapacityNoClobber(undef.name, undef); @@ -2126,7 +2097,6 @@ fn populateMetadata(self: *Zld) !void { .strsize = 0, }, }); - try self.strtab.append(self.allocator, 0); } if (self.dysymtab_cmd_index == null) { @@ -2752,7 +2722,7 @@ fn writeDebugInfo(self: *Zld) !void { const dirname = std.fs.path.dirname(tu_path) orelse "./"; // Current dir try stabs.append(.{ - .n_strx = try self.makeString(tu_path[0 .. dirname.len + 1]), + .n_strx = try self.strtab.getOrPut(tu_path[0 .. dirname.len + 1]), .n_type = macho.N_SO, .n_sect = 0, .n_desc = 0, @@ -2760,7 +2730,7 @@ fn writeDebugInfo(self: *Zld) !void { }); // Artifact name try stabs.append(.{ - .n_strx = try self.makeString(tu_path[dirname.len + 1 ..]), + .n_strx = try self.strtab.getOrPut(tu_path[dirname.len + 1 ..]), .n_type = macho.N_SO, .n_sect = 0, .n_desc = 0, @@ -2768,7 +2738,7 @@ fn writeDebugInfo(self: *Zld) !void { }); // Path to object file with debug info try stabs.append(.{ - .n_strx = try self.makeString(object.name.?), + .n_strx = try self.strtab.getOrPut(object.name.?), .n_type = macho.N_OSO, .n_sect = 0, .n_desc = 1, @@ -2801,7 +2771,7 @@ fn writeDebugInfo(self: *Zld) !void { .n_value = reg.address, }); try stabs.append(.{ - .n_strx = try self.makeString(sym.name), + .n_strx = try self.strtab.getOrPut(sym.name), .n_type = macho.N_FUN, .n_sect = reg.section, .n_desc = 0, @@ -2824,7 +2794,7 @@ fn writeDebugInfo(self: *Zld) !void { }, .global => { try stabs.append(.{ - .n_strx = try self.makeString(sym.name), + .n_strx = try self.strtab.getOrPut(sym.name), .n_type = macho.N_GSYM, .n_sect = 0, .n_desc = 0, @@ -2833,7 +2803,7 @@ fn writeDebugInfo(self: *Zld) !void { }, .static => { try stabs.append(.{ - .n_strx = try self.makeString(sym.name), + .n_strx = try self.strtab.getOrPut(sym.name), .n_type = macho.N_STSYM, .n_sect = reg.section, .n_desc = 0, @@ -2892,24 +2862,14 @@ fn writeSymbolTable(self: *Zld) !void { if (reg.isTemp()) continue; if (reg.visited) continue; + const nlist = try reg.asNlist(&self.strtab); + switch (reg.linkage) { .translation_unit => { - try locals.append(.{ - .n_strx = try self.makeString(sym.name), - .n_type = macho.N_SECT, - .n_sect = reg.section, - .n_desc = 0, - .n_value = reg.address, - }); + try locals.append(nlist); }, else => { - try exports.append(.{ - .n_strx = try self.makeString(sym.name), - .n_type = macho.N_SECT | macho.N_EXT, - .n_sect = reg.section, - .n_desc = 0, - .n_value = reg.address, - }); + try exports.append(nlist); }, } @@ -2922,13 +2882,8 @@ fn writeSymbolTable(self: *Zld) !void { for (self.imports.values()) |sym| { const proxy = sym.cast(Symbol.Proxy) orelse unreachable; - try undefs.append(.{ - .n_strx = try self.makeString(sym.name), - .n_type = macho.N_UNDF | macho.N_EXT, - .n_sect = 0, - .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, - .n_value = 0, - }); + const nlist = try proxy.asNlist(&self.strtab); + try undefs.append(nlist); } const nlocals = locals.items.len; @@ -3017,14 +2972,14 @@ fn writeStringTable(self: *Zld) !void { const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; symtab.stroff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); - symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); + symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.size(), @alignOf(u64))); seg.inner.filesize += symtab.strsize; log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); - try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); + try self.file.?.pwriteAll(self.strtab.asSlice(), symtab.stroff); - if (symtab.strsize > self.strtab.items.len and self.target.?.cpu.arch == .x86_64) { + if (symtab.strsize > self.strtab.size() and self.target.?.cpu.arch == .x86_64) { // This is the last section, so we need to pad it out. try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1); } @@ -3173,26 +3128,6 @@ fn writeHeader(self: *Zld) !void { try self.file.?.pwriteAll(mem.asBytes(&header), 0); } -fn makeString(self: *Zld, bytes: []const u8) !u32 { - if (self.strtab_dir.get(bytes)) |offset| { - log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset }); - return offset; - } - - try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1); - const offset = @intCast(u32, self.strtab.items.len); - log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); - self.strtab.appendSliceAssumeCapacity(bytes); - self.strtab.appendAssumeCapacity(0); - try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset); - return offset; -} - -fn getString(self: *const Zld, str_off: u32) []const u8 { - assert(str_off < self.strtab.items.len); - return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + str_off)); -} - pub fn parseName(name: *const [16]u8) []const u8 { const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; return name[0..len]; |
