diff --git a/src/link/Elf.zig b/src/link/Elf.zig index cde8243d57..24140cd1d0 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1047,6 +1047,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Resolve symbols self.resolveSymbols(); + self.markImportsExports(); if (self.unresolved.keys().len > 0) try self.reportUndefined(); @@ -1336,6 +1337,52 @@ fn resolveSymbols(self: *Elf) void { } } +fn markImportsExports(self: *Elf) void { + const is_dyn_lib = self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic; + + if (self.zig_module_index) |index| { + const zig_module = self.file(index).?.zig_module; + for (zig_module.globals()) |global_index| { + const global = self.symbol(global_index); + if (global.version_index == elf.VER_NDX_LOCAL) continue; + const file_ptr = global.file(self) orelse continue; + const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other)); + if (vis == .HIDDEN) continue; + // if (file == .shared and !global.isAbs(self)) { + // global.flags.import = true; + // continue; + // } + if (file_ptr.index() == index) { + global.flags.@"export" = true; + if (is_dyn_lib and vis != .PROTECTED) { + global.flags.import = true; + } + } + } + } + + for (self.objects.items) |index| { + const object = self.file(index).?.object; + for (object.globals()) |global_index| { + const global = self.symbol(global_index); + if (global.version_index == elf.VER_NDX_LOCAL) continue; + const file_ptr = global.file(self) orelse continue; + const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other)); + if (vis == .HIDDEN) continue; + // if (file == .shared and !global.isAbs(self)) { + // global.flags.import = true; + // continue; + // } + if (file_ptr.index() == index) { + global.flags.@"export" = true; + if (is_dyn_lib and vis != .PROTECTED) { + global.flags.import = true; + } + } + } + } +} + fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); @@ -2941,6 +2988,13 @@ fn updateSymtabSize(self: *Elf) !void { sizes.nglobals += zig_module.output_symtab_size.nglobals; } + for (self.objects.items) |index| { + const object = self.file(index).?.object; + object.updateSymtabSize(self); + sizes.nlocals += object.output_symtab_size.nlocals; + sizes.nglobals += object.output_symtab_size.nglobals; + } + if (self.got_section_index) |_| { self.got.updateSymtabSize(self); sizes.nlocals += self.got.output_symtab_size.nlocals; @@ -2996,6 +3050,13 @@ fn writeSymtab(self: *Elf) !void { ctx.iglobal += zig_module.output_symtab_size.nglobals; } + for (self.objects.items) |index| { + const object = self.file(index).?.object; + object.writeSymtab(self, ctx); + ctx.ilocal += object.output_symtab_size.nlocals; + ctx.iglobal += object.output_symtab_size.nglobals; + } + if (self.got_section_index) |_| { try self.got.writeSymtab(self, ctx); ctx.ilocal += self.got.output_symtab_size.nlocals; diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index e2b45f45e4..7d85509901 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -430,7 +430,7 @@ pub fn markLive(self: *Object, elf_file: *Elf) void { const global = elf_file.symbol(index); const file = global.getFile(elf_file) orelse continue; const should_keep = sym.st_shndx == elf.SHN_UNDEF or - (sym.st_shndx == elf.SHN_COMMON and global.sourceSymbol(elf_file).st_shndx != elf.SHN_COMMON); + (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON); if (should_keep and !file.isAlive()) { file.setAlive(); file.markLive(elf_file); @@ -526,25 +526,22 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { } } -pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void { - if (elf_file.options.strip_all) return; - +pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void { for (self.locals()) |local_index| { const local = elf_file.symbol(local_index); if (local.atom(elf_file)) |atom| if (!atom.alive) continue; - const s_sym = local.getSourceSymbol(elf_file); - switch (s_sym.st_type()) { + const esym = local.elfSym(elf_file); + switch (esym.st_type()) { elf.STT_SECTION, elf.STT_NOTYPE => continue, else => {}, } local.flags.output_symtab = true; self.output_symtab_size.nlocals += 1; - self.output_symtab_size.strsize += @as(u32, @intCast(local.getName(elf_file).len + 1)); } for (self.globals()) |global_index| { const global = elf_file.symbol(global_index); - if (global.getFile(elf_file)) |file| if (file.getIndex() != self.index) continue; + if (global.file(elf_file)) |file| if (file.index() != self.index) continue; if (global.atom(elf_file)) |atom| if (!atom.alive) continue; global.flags.output_symtab = true; if (global.isLocal()) { @@ -552,35 +549,28 @@ pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void { } else { self.output_symtab_size.nglobals += 1; } - self.output_symtab_size.strsize += @as(u32, @intCast(global.getName(elf_file).len + 1)); } } -pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: Elf.WriteSymtabCtx) !void { - if (elf_file.options.strip_all) return; - - const gpa = elf_file.base.allocator; - +pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void { var ilocal = ctx.ilocal; for (self.locals()) |local_index| { const local = elf_file.symbol(local_index); if (!local.flags.output_symtab) continue; - const st_name = try ctx.strtab.insert(gpa, local.getName(elf_file)); - ctx.symtab[ilocal] = local.asElfSym(st_name, elf_file); + local.setOutputSym(elf_file, &ctx.symtab[ilocal]); ilocal += 1; } var iglobal = ctx.iglobal; for (self.globals()) |global_index| { const global = elf_file.symbol(global_index); - if (global.getFile(elf_file)) |file| if (file.getIndex() != self.index) continue; + if (global.file(elf_file)) |file| if (file.index() != self.index) continue; if (!global.flags.output_symtab) continue; - const st_name = try ctx.strtab.insert(gpa, global.getName(elf_file)); if (global.isLocal()) { - ctx.symtab[ilocal] = global.asElfSym(st_name, elf_file); + global.setOutputSym(elf_file, &ctx.symtab[ilocal]); ilocal += 1; } else { - ctx.symtab[iglobal] = global.asElfSym(st_name, elf_file); + global.setOutputSym(elf_file, &ctx.symtab[iglobal]); iglobal += 1; } } diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 22d3376b31..db7e69d5e4 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -20,7 +20,7 @@ atom_index: Atom.Index = 0, output_section_index: u16 = 0, /// Index of the source symbol this symbol references. -/// Use `sourceSymbol` to pull the source symbol from the relevant file. +/// Use `elfSym` to pull the source symbol from the relevant file. esym_index: Index = 0, /// Index of the source version symbol this symbol references if any. @@ -48,7 +48,7 @@ pub inline fn isIFunc(symbol: Symbol, elf_file: *Elf) bool { } pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 { - const s_sym = symbol.sourceSymbol(elf_file); + const s_sym = symbol.elfSym(elf_file); // const file_ptr = symbol.file(elf_file).?; // if (s_sym.st_type() == elf.STT_GNU_IFUNC and file_ptr == .shared) return elf.STT_FUNC; return s_sym.st_type(); @@ -66,7 +66,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File { return elf_file.file(symbol.file_index); } -pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { +pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { const file_ptr = symbol.file(elf_file).?; switch (file_ptr) { .zig_module => |x| { @@ -82,7 +82,7 @@ pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { const file_ptr = symbol.file(elf_file) orelse return std.math.maxInt(u32); - const sym = symbol.sourceSymbol(elf_file); + const sym = symbol.elfSym(elf_file); const in_archive = switch (file_ptr) { .object => |x| !x.alive, else => false, @@ -173,13 +173,13 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { out.* = Elf.null_sym; return; }; - const s_sym = symbol.sourceSymbol(elf_file); + const esym = symbol.elfSym(elf_file); const st_type = symbol.type(elf_file); const st_bind: u8 = blk: { if (symbol.isLocal()) break :blk 0; if (symbol.flags.weak) break :blk elf.STB_WEAK; // if (file_ptr == .shared) break :blk elf.STB_GLOBAL; - break :blk s_sym.st_bind(); + break :blk esym.st_bind(); }; const st_shndx = blk: { // if (symbol.flags.copy_rel) break :blk elf_file.copy_rel_sect_index.?; @@ -202,10 +202,10 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { out.* = .{ .st_name = symbol.name_offset, .st_info = (st_bind << 4) | st_type, - .st_other = s_sym.st_other, + .st_other = esym.st_other, .st_shndx = st_shndx, .st_value = st_value, - .st_size = s_sym.st_size, + .st_size = esym.st_size, }; } @@ -274,7 +274,7 @@ fn format2( try writer.print("%{d} : {s} : @{x}", .{ symbol.index, symbol.fmtName(ctx.elf_file), symbol.value }); if (symbol.file(ctx.elf_file)) |file_ptr| { if (symbol.isAbs(ctx.elf_file)) { - if (symbol.sourceSymbol(ctx.elf_file).st_shndx == elf.SHN_UNDEF) { + if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) { try writer.writeAll(" : undef"); } else { try writer.writeAll(" : absolute"); diff --git a/src/link/Elf/ZigModule.zig b/src/link/Elf/ZigModule.zig index 8a4e712310..f9df0d33ea 100644 --- a/src/link/Elf/ZigModule.zig +++ b/src/link/Elf/ZigModule.zig @@ -105,7 +105,7 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void { pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void { for (self.locals()) |local_index| { const local = elf_file.symbol(local_index); - const esym = local.sourceSymbol(elf_file); + const esym = local.elfSym(elf_file); switch (esym.st_type()) { elf.STT_SECTION, elf.STT_NOTYPE => { local.flags.output_symtab = false;