| author | |
| committer | |
| log | b478a0dd1ab6acab92e2b1a4198fdf6428caad8d |
| tree | 2cc078eea11e27b9e3bcd2fdcb69d750719b90ad |
| parent | 962b46148d573f62146a2752a0ab8cfd5f8da132 |
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 |
| 1047 | 1047 | ||
| 1048 | // Resolve symbols | 1048 | // Resolve symbols |
| 1049 | self.resolveSymbols(); | 1049 | self.resolveSymbols(); |
| 1050 | self.markImportsExports(); | ||
| 1050 | 1051 | ||
| 1051 | if (self.unresolved.keys().len > 0) try self.reportUndefined(); | 1052 | if (self.unresolved.keys().len > 0) try self.reportUndefined(); |
| 1052 | 1053 | ||
| ... | @@ -1336,6 +1337,52 @@ fn resolveSymbols(self: *Elf) void { | ... | @@ -1336,6 +1337,52 @@ fn resolveSymbols(self: *Elf) void { |
| 1336 | } | 1337 | } |
| 1337 | } | 1338 | } |
| 1338 | 1339 | ||
| 1340 | fn 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 | |||
| 1339 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1386 | fn 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 | } |
| 2943 | 2990 | ||
| 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 | } |
| 2998 | 3052 | ||
| 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 or | 432 | 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 | } |
| 528 | 528 | ||
| 529 | pub fn calcSymtabSize(self: *Object, elf_file: *Elf) !void { | 529 | pub 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 | } |
| 544 | 541 | ||
| 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 | } |
| 558 | 554 | ||
| 559 | pub fn writeSymtab(self: *Object, elf_file: *Elf, ctx: Elf.WriteSymtabCtx) !void { | 555 | pub 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 | } |
| 572 | 563 | ||
| 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, |
| 20 | output_section_index: u16 = 0, | 20 | output_section_index: u16 = 0, |
| 21 | 21 | ||
| 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. |
| 24 | esym_index: Index = 0, | 24 | esym_index: Index = 0, |
| 25 | 25 | ||
| 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 | } |
| 49 | 49 | ||
| 50 | pub fn @"type"(symbol: Symbol, elf_file: *Elf) u4 { | 50 | pub 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 | } |
| 68 | 68 | ||
| 69 | pub fn sourceSymbol(symbol: Symbol, elf_file: *Elf) elf.Elf64_Sym { | 69 | pub 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 { |
| 82 | 82 | ||
| 83 | pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { | 83 | pub 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 | } |
| 211 | 211 | ||
| ... | @@ -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 { |
| 105 | pub fn updateSymtabSize(self: *ZigModule, elf_file: *Elf) void { | 105 | pub 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; |