authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 15:14:38+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 15:14:38+02:00
logb478a0dd1ab6acab92e2b1a4198fdf6428caad8d
tree2cc078eea11e27b9e3bcd2fdcb69d750719b90ad
parent962b46148d573f62146a2752a0ab8cfd5f8da132

elf: mark imports-exports; populate symtab with objects


4 files changed, 81 insertions(+), 30 deletions(-)

src/link/Elf.zig+61
...@@ -1047,6 +1047,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1047,6 +1047,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10471047
1048 // Resolve symbols1048 // Resolve symbols
1049 self.resolveSymbols();1049 self.resolveSymbols();
1050 self.markImportsExports();
10501051
1051 if (self.unresolved.keys().len > 0) try self.reportUndefined();1052 if (self.unresolved.keys().len > 0) try self.reportUndefined();
10521053
...@@ -1336,6 +1337,52 @@ fn resolveSymbols(self: *Elf) void {...@@ -1336,6 +1337,52 @@ fn resolveSymbols(self: *Elf) void {
1336 }1337 }
1337}1338}
13381339
1340fn markImportsExports(self: *Elf) void {
1341 const is_dyn_lib = self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic;
1342
1343 if (self.zig_module_index) |index| {
1344 const zig_module = self.file(index).?.zig_module;
1345 for (zig_module.globals()) |global_index| {
1346 const global = self.symbol(global_index);
1347 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1348 const file_ptr = global.file(self) orelse continue;
1349 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
1350 if (vis == .HIDDEN) continue;
1351 // if (file == .shared and !global.isAbs(self)) {
1352 // global.flags.import = true;
1353 // continue;
1354 // }
1355 if (file_ptr.index() == index) {
1356 global.flags.@"export" = true;
1357 if (is_dyn_lib and vis != .PROTECTED) {
1358 global.flags.import = true;
1359 }
1360 }
1361 }
1362 }
1363
1364 for (self.objects.items) |index| {
1365 const object = self.file(index).?.object;
1366 for (object.globals()) |global_index| {
1367 const global = self.symbol(global_index);
1368 if (global.version_index == elf.VER_NDX_LOCAL) continue;
1369 const file_ptr = global.file(self) orelse continue;
1370 const vis = @as(elf.STV, @enumFromInt(global.elfSym(self).st_other));
1371 if (vis == .HIDDEN) continue;
1372 // if (file == .shared and !global.isAbs(self)) {
1373 // global.flags.import = true;
1374 // continue;
1375 // }
1376 if (file_ptr.index() == index) {
1377 global.flags.@"export" = true;
1378 if (is_dyn_lib and vis != .PROTECTED) {
1379 global.flags.import = true;
1380 }
1381 }
1382 }
1383 }
1384}
1385
1339fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {1386fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1340 const tracy = trace(@src());1387 const tracy = trace(@src());
1341 defer tracy.end();1388 defer tracy.end();
...@@ -2941,6 +2988,13 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -2941,6 +2988,13 @@ fn updateSymtabSize(self: *Elf) !void {
2941 sizes.nglobals += zig_module.output_symtab_size.nglobals;2988 sizes.nglobals += zig_module.output_symtab_size.nglobals;
2942 }2989 }
29432990
2991 for (self.objects.items) |index| {
2992 const object = self.file(index).?.object;
2993 object.updateSymtabSize(self);
2994 sizes.nlocals += object.output_symtab_size.nlocals;
2995 sizes.nglobals += object.output_symtab_size.nglobals;
2996 }
2997
2944 if (self.got_section_index) |_| {2998 if (self.got_section_index) |_| {
2945 self.got.updateSymtabSize(self);2999 self.got.updateSymtabSize(self);
2946 sizes.nlocals += self.got.output_symtab_size.nlocals;3000 sizes.nlocals += self.got.output_symtab_size.nlocals;
...@@ -2996,6 +3050,13 @@ fn writeSymtab(self: *Elf) !void {...@@ -2996,6 +3050,13 @@ fn writeSymtab(self: *Elf) !void {
2996 ctx.iglobal += zig_module.output_symtab_size.nglobals;3050 ctx.iglobal += zig_module.output_symtab_size.nglobals;
2997 }3051 }
29983052
3053 for (self.objects.items) |index| {
3054 const object = self.file(index).?.object;
3055 object.writeSymtab(self, ctx);
3056 ctx.ilocal += object.output_symtab_size.nlocals;
3057 ctx.iglobal += object.output_symtab_size.nglobals;
3058 }
3059
2999 if (self.got_section_index) |_| {3060 if (self.got_section_index) |_| {
3000 try self.got.writeSymtab(self, ctx);3061 try self.got.writeSymtab(self, ctx);
3001 ctx.ilocal += self.got.output_symtab_size.nlocals;3062 ctx.ilocal += self.got.output_symtab_size.nlocals;
src/link/Elf/Object.zig+10-20
...@@ -430,7 +430,7 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {...@@ -430,7 +430,7 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {
430 const global = elf_file.symbol(index);430 const global = elf_file.symbol(index);
431 const file = global.getFile(elf_file) orelse continue;431 const file = global.getFile(elf_file) orelse continue;
432 const should_keep = sym.st_shndx == elf.SHN_UNDEF or432 const should_keep = sym.st_shndx == elf.SHN_UNDEF or
433 (sym.st_shndx == elf.SHN_COMMON and global.sourceSymbol(elf_file).st_shndx != elf.SHN_COMMON);433 (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON);
434 if (should_keep and !file.isAlive()) {434 if (should_keep and !file.isAlive()) {
435 file.setAlive();435 file.setAlive();
436 file.markLive(elf_file);436 file.markLive(elf_file);
...@@ -526,25 +526,22 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -526,25 +526,22 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
526 }526 }
527}527}
528528
529pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void {529pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
530 if (elf_file.options.strip_all) return;
531
532 for (self.locals()) |local_index| {530 for (self.locals()) |local_index| {
533 const local = elf_file.symbol(local_index);531 const local = elf_file.symbol(local_index);
534 if (local.atom(elf_file)) |atom| if (!atom.alive) continue;532 if (local.atom(elf_file)) |atom| if (!atom.alive) continue;
535 const s_sym = local.getSourceSymbol(elf_file);533 const esym = local.elfSym(elf_file);
536 switch (s_sym.st_type()) {534 switch (esym.st_type()) {
537 elf.STT_SECTION, elf.STT_NOTYPE => continue,535 elf.STT_SECTION, elf.STT_NOTYPE => continue,
538 else => {},536 else => {},
539 }537 }
540 local.flags.output_symtab = true;538 local.flags.output_symtab = true;
541 self.output_symtab_size.nlocals += 1;539 self.output_symtab_size.nlocals += 1;
542 self.output_symtab_size.strsize += @as(u32, @intCast(local.getName(elf_file).len + 1));
543 }540 }
544541
545 for (self.globals()) |global_index| {542 for (self.globals()) |global_index| {
546 const global = elf_file.symbol(global_index);543 const global = elf_file.symbol(global_index);
547 if (global.getFile(elf_file)) |file| if (file.getIndex() != self.index) continue;544 if (global.file(elf_file)) |file| if (file.index() != self.index) continue;
548 if (global.atom(elf_file)) |atom| if (!atom.alive) continue;545 if (global.atom(elf_file)) |atom| if (!atom.alive) continue;
549 global.flags.output_symtab = true;546 global.flags.output_symtab = true;
550 if (global.isLocal()) {547 if (global.isLocal()) {
...@@ -552,35 +549,28 @@ pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void {...@@ -552,35 +549,28 @@ pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void {
552 } else {549 } else {
553 self.output_symtab_size.nglobals += 1;550 self.output_symtab_size.nglobals += 1;
554 }551 }
555 self.output_symtab_size.strsize += @as(u32, @intCast(global.getName(elf_file).len + 1));
556 }552 }
557}553}
558554
559pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: Elf.WriteSymtabCtx) !void {555pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: anytype) void {
560 if (elf_file.options.strip_all) return;
561
562 const gpa = elf_file.base.allocator;
563
564 var ilocal = ctx.ilocal;556 var ilocal = ctx.ilocal;
565 for (self.locals()) |local_index| {557 for (self.locals()) |local_index| {
566 const local = elf_file.symbol(local_index);558 const local = elf_file.symbol(local_index);
567 if (!local.flags.output_symtab) continue;559 if (!local.flags.output_symtab) continue;
568 const st_name = try ctx.strtab.insert(gpa, local.getName(elf_file));560 local.setOutputSym(elf_file, &ctx.symtab[ilocal]);
569 ctx.symtab[ilocal] = local.asElfSym(st_name, elf_file);
570 ilocal += 1;561 ilocal += 1;
571 }562 }
572563
573 var iglobal = ctx.iglobal;564 var iglobal = ctx.iglobal;
574 for (self.globals()) |global_index| {565 for (self.globals()) |global_index| {
575 const global = elf_file.symbol(global_index);566 const global = elf_file.symbol(global_index);
576 if (global.getFile(elf_file)) |file| if (file.getIndex() != self.index) continue;567 if (global.file(elf_file)) |file| if (file.index() != self.index) continue;
577 if (!global.flags.output_symtab) continue;568 if (!global.flags.output_symtab) continue;
578 const st_name = try ctx.strtab.insert(gpa, global.getName(elf_file));
579 if (global.isLocal()) {569 if (global.isLocal()) {
580 ctx.symtab[ilocal] = global.asElfSym(st_name, elf_file);570 global.setOutputSym(elf_file, &ctx.symtab[ilocal]);
581 ilocal += 1;571 ilocal += 1;
582 } else {572 } else {
583 ctx.symtab[iglobal] = global.asElfSym(st_name, elf_file);573 global.setOutputSym(elf_file, &ctx.symtab[iglobal]);
584 iglobal += 1;574 iglobal += 1;
585 }575 }
586 }576 }
src/link/Elf/Symbol.zig+9-9
...@@ -20,7 +20,7 @@ atom_index: Atom.Index = 0,...@@ -20,7 +20,7 @@ atom_index: Atom.Index = 0,
20output_section_index: u16 = 0,20output_section_index: u16 = 0,
2121
22/// Index of the source symbol this symbol references.22/// Index of the source symbol this symbol references.
23/// Use `sourceSymbol` to pull the source symbol from the relevant file.23/// Use `elfSym` to pull the source symbol from the relevant file.
24esym_index: Index = 0,24esym_index: Index = 0,
2525
26/// Index of the source version symbol this symbol references if any.26/// 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 {...@@ -48,7 +48,7 @@ pub inline fn isIFunc(symbol: Symbol, elf_file: *Elf) bool {
48}48}
4949
50pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {50pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 {
51 const s_sym = symbol.sourceSymbol(elf_file);51 const s_sym = symbol.elfSym(elf_file);
52 // const file_ptr = symbol.file(elf_file).?;52 // const file_ptr = symbol.file(elf_file).?;
53 // if (s_sym.st_type() == elf.STT_GNU_IFUNC and file_ptr == .shared) return elf.STT_FUNC;53 // if (s_sym.st_type() == elf.STT_GNU_IFUNC and file_ptr == .shared) return elf.STT_FUNC;
54 return s_sym.st_type();54 return s_sym.st_type();
...@@ -66,7 +66,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {...@@ -66,7 +66,7 @@ pub fn file(symbol: Symbol, elf_file: *Elf) ?File {
66 return elf_file.file(symbol.file_index);66 return elf_file.file(symbol.file_index);
67}67}
6868
69pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {69pub fn elfSym(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
70 const file_ptr = symbol.file(elf_file).?;70 const file_ptr = symbol.file(elf_file).?;
71 switch (file_ptr) {71 switch (file_ptr) {
72 .zig_module => |x| {72 .zig_module => |x| {
...@@ -82,7 +82,7 @@ pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {...@@ -82,7 +82,7 @@ pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym {
8282
83pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {83pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
84 const file_ptr = symbol.file(elf_file) orelse return std.math.maxInt(u32);84 const file_ptr = symbol.file(elf_file) orelse return std.math.maxInt(u32);
85 const sym = symbol.sourceSymbol(elf_file);85 const sym = symbol.elfSym(elf_file);
86 const in_archive = switch (file_ptr) {86 const in_archive = switch (file_ptr) {
87 .object => |x| !x.alive,87 .object => |x| !x.alive,
88 else => false,88 else => false,
...@@ -173,13 +173,13 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -173,13 +173,13 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
173 out.* = Elf.null_sym;173 out.* = Elf.null_sym;
174 return;174 return;
175 };175 };
176 const s_sym = symbol.sourceSymbol(elf_file);176 const esym = symbol.elfSym(elf_file);
177 const st_type = symbol.type(elf_file);177 const st_type = symbol.type(elf_file);
178 const st_bind: u8 = blk: {178 const st_bind: u8 = blk: {
179 if (symbol.isLocal()) break :blk 0;179 if (symbol.isLocal()) break :blk 0;
180 if (symbol.flags.weak) break :blk elf.STB_WEAK;180 if (symbol.flags.weak) break :blk elf.STB_WEAK;
181 // if (file_ptr == .shared) break :blk elf.STB_GLOBAL;181 // if (file_ptr == .shared) break :blk elf.STB_GLOBAL;
182 break :blk s_sym.st_bind();182 break :blk esym.st_bind();
183 };183 };
184 const st_shndx = blk: {184 const st_shndx = blk: {
185 // if (symbol.flags.copy_rel) break :blk elf_file.copy_rel_sect_index.?;185 // 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 {...@@ -202,10 +202,10 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
202 out.* = .{202 out.* = .{
203 .st_name = symbol.name_offset,203 .st_name = symbol.name_offset,
204 .st_info = (st_bind << 4) | st_type,204 .st_info = (st_bind << 4) | st_type,
205 .st_other = s_sym.st_other,205 .st_other = esym.st_other,
206 .st_shndx = st_shndx,206 .st_shndx = st_shndx,
207 .st_value = st_value,207 .st_value = st_value,
208 .st_size = s_sym.st_size,208 .st_size = esym.st_size,
209 };209 };
210}210}
211211
...@@ -274,7 +274,7 @@ fn format2(...@@ -274,7 +274,7 @@ fn format2(
274 try writer.print("%{d} : {s} : @{x}", .{ symbol.index, symbol.fmtName(ctx.elf_file), symbol.value });274 try writer.print("%{d} : {s} : @{x}", .{ symbol.index, symbol.fmtName(ctx.elf_file), symbol.value });
275 if (symbol.file(ctx.elf_file)) |file_ptr| {275 if (symbol.file(ctx.elf_file)) |file_ptr| {
276 if (symbol.isAbs(ctx.elf_file)) {276 if (symbol.isAbs(ctx.elf_file)) {
277 if (symbol.sourceSymbol(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {277 if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
278 try writer.writeAll(" : undef");278 try writer.writeAll(" : undef");
279 } else {279 } else {
280 try writer.writeAll(" : absolute");280 try writer.writeAll(" : absolute");
src/link/Elf/ZigModule.zig+1-1
...@@ -105,7 +105,7 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {...@@ -105,7 +105,7 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
105pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {105pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void {
106 for (self.locals()) |local_index| {106 for (self.locals()) |local_index| {
107 const local = elf_file.symbol(local_index);107 const local = elf_file.symbol(local_index);
108 const esym = local.sourceSymbol(elf_file);108 const esym = local.elfSym(elf_file);
109 switch (esym.st_type()) {109 switch (esym.st_type()) {
110 elf.STT_SECTION, elf.STT_NOTYPE => {110 elf.STT_SECTION, elf.STT_NOTYPE => {
111 local.flags.output_symtab = false;111 local.flags.output_symtab = false;