Commit c654f3b0ee
Changed files (4)
src
src/link/Elf/file.zig
@@ -76,6 +76,12 @@ pub const File = union(enum) {
}
}
+ pub fn globals(file: File) []const Symbol.Index {
+ return switch (file) {
+ inline else => |x| x.globals(),
+ };
+ }
+
pub const Index = u32;
pub const Entry = union(enum) {
src/link/Elf/Object.zig
@@ -411,6 +411,34 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
}
}
+pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
+ const first_global = self.first_global orelse return;
+ for (self.globals(), 0..) |index, i| {
+ const esym_index = @as(u32, @intCast(first_global + i));
+ const esym = self.symtab[esym_index];
+ if (esym.st_shndx != elf.SHN_UNDEF) continue;
+
+ const global = elf_file.symbol(index);
+ if (global.file(elf_file)) |_| {
+ if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
+ }
+
+ const is_import = blk: {
+ if (!elf_file.isDynLib()) break :blk false;
+ const vis = @as(elf.STV, @enumFromInt(esym.st_other));
+ if (vis == .HIDDEN) break :blk false;
+ break :blk true;
+ };
+
+ global.value = 0;
+ global.atom_index = 0;
+ global.esym_index = esym_index;
+ global.file_index = self.index;
+ global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
+ global.flags.import = is_import;
+ }
+}
+
pub fn resetGlobals(self: *Object, elf_file: *Elf) void {
for (self.globals()) |index| {
const global = elf_file.symbol(index);
@@ -576,12 +604,12 @@ pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void {
}
}
-pub fn locals(self: *Object) []const u32 {
+pub fn locals(self: *Object) []const Symbol.Index {
const end = self.first_global orelse self.symbols.items.len;
return self.symbols.items[0..end];
}
-pub fn globals(self: *Object) []const u32 {
+pub fn globals(self: *Object) []const Symbol.Index {
const start = self.first_global orelse self.symbols.items.len;
return self.symbols.items[start..];
}
src/link/Elf/ZigModule.zig
@@ -102,6 +102,34 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
}
}
+pub fn claimUnresolved(self: *ZigModule, elf_file: *Elf) void {
+ for (self.globals(), 0..) |index, i| {
+ const esym_index = @as(Symbol.Index, @intCast(i)) | 0x10000000;
+ const esym = self.global_esyms.items[i];
+
+ if (esym.st_shndx != elf.SHN_UNDEF) continue;
+
+ const global = elf_file.symbol(index);
+ if (global.file(elf_file)) |_| {
+ if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF) continue;
+ }
+
+ const is_import = blk: {
+ if (!elf_file.isDynLib()) break :blk false;
+ const vis = @as(elf.STV, @enumFromInt(esym.st_other));
+ if (vis == .HIDDEN) break :blk false;
+ break :blk true;
+ };
+
+ global.value = 0;
+ global.atom_index = 0;
+ global.esym_index = esym_index;
+ global.file_index = self.index;
+ global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
+ global.flags.import = is_import;
+ }
+}
+
pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
for (self.locals()) |local_index| {
const local = elf_file.symbol(local_index);
src/link/Elf.zig
@@ -1048,6 +1048,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
// Resolve symbols
self.resolveSymbols();
self.markImportsExports();
+ self.claimUnresolved();
if (self.unresolved.keys().len > 0) try self.reportUndefined();
@@ -1338,48 +1339,45 @@ 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;
+ const mark = struct {
+ fn mark(elf_file: *Elf, file_index: File.Index) void {
+ for (elf_file.file(file_index).?.globals()) |global_index| {
+ const global = elf_file.symbol(global_index);
+ if (global.version_index == elf.VER_NDX_LOCAL) continue;
+ const file_ptr = global.file(elf_file) orelse continue;
+ const vis = @as(elf.STV, @enumFromInt(global.elfSym(elf_file).st_other));
+ if (vis == .HIDDEN) continue;
+ // if (file == .shared and !global.isAbs(self)) {
+ // global.flags.import = true;
+ // continue;
+ // }
+ if (file_ptr.index() == file_index) {
+ global.flags.@"export" = true;
+ if (elf_file.isDynLib() and vis != .PROTECTED) {
+ global.flags.import = true;
+ }
}
}
}
+ }.mark;
+
+ if (self.zig_module_index) |index| {
+ mark(self, index);
+ }
+
+ for (self.objects.items) |index| {
+ mark(self, index);
}
+}
+fn claimUnresolved(self: *Elf) void {
+ if (self.zig_module_index) |index| {
+ const zig_module = self.file(index).?.zig_module;
+ zig_module.claimUnresolved(self);
+ }
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;
- }
- }
- }
+ object.claimUnresolved(self);
}
}
@@ -3423,6 +3421,10 @@ pub fn defaultEntryAddress(self: Elf) u64 {
};
}
+pub fn isDynLib(self: Elf) bool {
+ return self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;
+}
+
pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
for (self.shdrs.items, 0..) |*shdr, i| {
const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);