authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-02 14:12:08+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-04 09:11:47+01:00
log481ee1b598b02cf5790ed12ed162a9f749a1ac92
treedc5e2c57578775a15f206837b66c96105f28f7a9
parentd2c4597eb5fcaba07f15c22092fc8c42c8b70ee3

elf: enable static-lib flush path


5 files changed, 57 insertions(+), 34 deletions(-)

src/arch/x86_64/Emit.zig+8-4
...@@ -85,15 +85,19 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -85,15 +85,19 @@ pub fn emitMir(emit: *Emit) Error!void {
85 @tagName(emit.lower.bin_file.tag),85 @tagName(emit.lower.bin_file.tag),
86 }),86 }),
87 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {87 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
88 const is_obj = emit.lower.bin_file.options.effectiveOutputMode() == .Obj;88 const is_obj_or_static_lib = switch (emit.lower.bin_file.options.output_mode) {
89 .Exe => false,
90 .Obj => true,
91 .Lib => emit.lower.bin_file.options.link_mode == .Static,
92 };
89 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;93 const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
90 const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);94 const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
91 const sym = elf_file.symbol(sym_index);95 const sym = elf_file.symbol(sym_index);
92 if (sym.flags.needs_zig_got and !is_obj) {96 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
93 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);97 _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
94 }98 }
95 if (emit.lower.bin_file.options.pic) {99 if (emit.lower.bin_file.options.pic) {
96 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj)100 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
97 link.File.Elf.R_X86_64_ZIG_GOTPCREL101 link.File.Elf.R_X86_64_ZIG_GOTPCREL
98 else if (sym.flags.needs_got)102 else if (sym.flags.needs_got)
99 std.elf.R_X86_64_GOTPCREL103 std.elf.R_X86_64_GOTPCREL
...@@ -105,7 +109,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -105,7 +109,7 @@ pub fn emitMir(emit: *Emit) Error!void {
105 .r_addend = -4,109 .r_addend = -4,
106 });110 });
107 } else {111 } else {
108 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj)112 const r_type: u32 = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
109 link.File.Elf.R_X86_64_ZIG_GOT32113 link.File.Elf.R_X86_64_ZIG_GOT32
110 else if (sym.flags.needs_got)114 else if (sym.flags.needs_got)
111 std.elf.R_X86_64_GOT32115 std.elf.R_X86_64_GOT32
src/arch/x86_64/Lower.zig+7-3
...@@ -327,7 +327,11 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -327,7 +327,11 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
327 }327 }
328 }.needsZigGot;328 }.needsZigGot;
329329
330 const is_obj = lower.bin_file.options.effectiveOutputMode() == .Obj;330 const is_obj_or_static_lib = switch (lower.bin_file.options.output_mode) {
331 .Exe => false,
332 .Obj => true,
333 .Lib => lower.bin_file.options.link_mode == .Static,
334 };
331 var emit_prefix = prefix;335 var emit_prefix = prefix;
332 var emit_mnemonic = mnemonic;336 var emit_mnemonic = mnemonic;
333 var emit_ops_storage: [4]Operand = undefined;337 var emit_ops_storage: [4]Operand = undefined;
...@@ -347,7 +351,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -347,7 +351,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
347 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };351 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
348 },352 },
349 .mov => {353 .mov => {
350 if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;354 if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
351 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };355 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
352 },356 },
353 else => unreachable,357 else => unreachable,
...@@ -360,7 +364,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -360,7 +364,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
360 break :op .{ .imm = Immediate.s(0) };364 break :op .{ .imm = Immediate.s(0) };
361 },365 },
362 .mov => {366 .mov => {
363 if (is_obj and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;367 if (is_obj_or_static_lib and needsZigGot(sym, lower.bin_file)) emit_mnemonic = .lea;
364 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{368 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
365 .base = .{ .reg = .ds },369 .base = .{ .reg = .ds },
366 }) };370 }) };
src/link/Elf.zig+36-22
...@@ -498,7 +498,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -498,7 +498,7 @@ pub fn initMetadata(self: *Elf) !void {
498498
499 const fillSection = struct {499 const fillSection = struct {
500 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void {500 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) void {
501 if (elf_file.isObject()) {501 if (elf_file.isRelocatable()) {
502 const off = elf_file.findFreeSpace(size, shdr.sh_addralign);502 const off = elf_file.findFreeSpace(size, shdr.sh_addralign);
503 shdr.sh_offset = off;503 shdr.sh_offset = off;
504 shdr.sh_size = size;504 shdr.sh_size = size;
...@@ -513,7 +513,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -513,7 +513,7 @@ pub fn initMetadata(self: *Elf) !void {
513513
514 comptime assert(number_of_zig_segments == 5);514 comptime assert(number_of_zig_segments == 5);
515515
516 if (!self.isObject()) {516 if (!self.isRelocatable()) {
517 if (self.phdr_zig_load_re_index == null) {517 if (self.phdr_zig_load_re_index == null) {
518 const filesz = self.base.options.program_code_size_hint;518 const filesz = self.base.options.program_code_size_hint;
519 const off = self.findFreeSpace(filesz, self.page_size);519 const off = self.findFreeSpace(filesz, self.page_size);
...@@ -597,7 +597,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -597,7 +597,7 @@ pub fn initMetadata(self: *Elf) !void {
597 });597 });
598 const shdr = &self.shdrs.items[self.zig_text_section_index.?];598 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
599 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);599 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
600 if (self.isObject()) {600 if (self.isRelocatable()) {
601 try zig_object.addSectionSymbol(self.zig_text_section_index.?, self);601 try zig_object.addSectionSymbol(self.zig_text_section_index.?, self);
602 self.zig_text_rela_section_index = try self.addRelaShdr(602 self.zig_text_rela_section_index = try self.addRelaShdr(
603 ".rela.text.zig",603 ".rela.text.zig",
...@@ -613,7 +613,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -613,7 +613,7 @@ pub fn initMetadata(self: *Elf) !void {
613 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});613 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
614 }614 }
615615
616 if (self.zig_got_section_index == null and !self.isObject()) {616 if (self.zig_got_section_index == null and !self.isRelocatable()) {
617 self.zig_got_section_index = try self.addSection(.{617 self.zig_got_section_index = try self.addSection(.{
618 .name = ".got.zig",618 .name = ".got.zig",
619 .type = elf.SHT_PROGBITS,619 .type = elf.SHT_PROGBITS,
...@@ -644,7 +644,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -644,7 +644,7 @@ pub fn initMetadata(self: *Elf) !void {
644 });644 });
645 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];645 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
646 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);646 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
647 if (self.isObject()) {647 if (self.isRelocatable()) {
648 try zig_object.addSectionSymbol(self.zig_data_rel_ro_section_index.?, self);648 try zig_object.addSectionSymbol(self.zig_data_rel_ro_section_index.?, self);
649 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(649 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(
650 ".rela.data.rel.ro.zig",650 ".rela.data.rel.ro.zig",
...@@ -670,7 +670,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -670,7 +670,7 @@ pub fn initMetadata(self: *Elf) !void {
670 });670 });
671 const shdr = &self.shdrs.items[self.zig_data_section_index.?];671 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
672 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);672 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
673 if (self.isObject()) {673 if (self.isRelocatable()) {
674 try zig_object.addSectionSymbol(self.zig_data_section_index.?, self);674 try zig_object.addSectionSymbol(self.zig_data_section_index.?, self);
675 self.zig_data_rela_section_index = try self.addRelaShdr(675 self.zig_data_rela_section_index = try self.addRelaShdr(
676 ".rela.data.zig",676 ".rela.data.zig",
...@@ -904,10 +904,6 @@ pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link...@@ -904,10 +904,6 @@ pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link
904 if (use_lld) {904 if (use_lld) {
905 return self.linkWithLLD(comp, prog_node);905 return self.linkWithLLD(comp, prog_node);
906 }906 }
907 if (self.base.options.output_mode == .Lib and self.isStatic()) {
908 // TODO writing static library files
909 return error.TODOImplementWritingLibFiles;
910 }
911 try self.flushModule(comp, prog_node);907 try self.flushModule(comp, prog_node);
912}908}
913909
...@@ -943,7 +939,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -943,7 +939,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
943 } else null;939 } else null;
944 const gc_sections = self.base.options.gc_sections orelse false;940 const gc_sections = self.base.options.gc_sections orelse false;
945941
946 if (self.isObject() and self.zig_object_index == null) {942 if (self.isRelocatable() and self.zig_object_index == null) {
943 if (self.isStaticLib()) {
944 var err = try self.addErrorWithNotes(0);
945 try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{});
946 return;
947 }
947 // TODO this will become -r route I guess. For now, just copy the object file.948 // TODO this will become -r route I guess. For now, just copy the object file.
948 assert(self.base.file == null); // TODO uncomment once we implement -r949 assert(self.base.file == null); // TODO uncomment once we implement -r
949 const the_object_path = blk: {950 const the_object_path = blk: {
...@@ -1389,6 +1390,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1389,6 +1390,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1389 }1390 }
13901391
1391 if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self);1392 if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self);
1393 if (self.isStaticLib()) return self.flushStaticLib(comp);
13921394
1393 // Dedup shared objects1395 // Dedup shared objects
1394 {1396 {
...@@ -1424,9 +1426,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1424,9 +1426,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1424 self.resolveSymbols();1426 self.resolveSymbols();
1425 self.markEhFrameAtomsDead();1427 self.markEhFrameAtomsDead();
14261428
1427 if (self.isObject()) {1429 if (self.isObject()) return self.flushObject(comp);
1428 return self.flushObject(comp);
1429 }
14301430
1431 try self.convertCommonSymbols();1431 try self.convertCommonSymbols();
1432 self.markImportsExports();1432 self.markImportsExports();
...@@ -1511,7 +1511,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1511,7 +1511,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1511 try self.writeAtoms();1511 try self.writeAtoms();
1512 try self.writeSyntheticSections();1512 try self.writeSyntheticSections();
15131513
1514 if (self.entry_index == null and self.base.options.effectiveOutputMode() == .Exe) {1514 if (self.entry_index == null and self.isExe()) {
1515 log.debug("flushing. no_entry_point_found = true", .{});1515 log.debug("flushing. no_entry_point_found = true", .{});
1516 self.error_flags.no_entry_point_found = true;1516 self.error_flags.no_entry_point_found = true;
1517 } else {1517 } else {
...@@ -1521,6 +1521,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1521,6 +1521,12 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1521 }1521 }
1522}1522}
15231523
1524pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void {
1525 _ = comp;
1526 var err = try self.addErrorWithNotes(0);
1527 try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{});
1528}
1529
1524pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {1530pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {
1525 _ = comp;1531 _ = comp;
1526 self.claimUnresolvedObject();1532 self.claimUnresolvedObject();
...@@ -2822,7 +2828,7 @@ fn writeHeader(self: *Elf) !void {...@@ -2822,7 +2828,7 @@ fn writeHeader(self: *Elf) !void {
28222828
2823 assert(index == 16);2829 assert(index == 16);
28242830
2825 const elf_type: elf.ET = switch (self.base.options.effectiveOutputMode()) {2831 const elf_type: elf.ET = switch (self.base.options.output_mode) {
2826 .Exe => if (self.base.options.pie) .DYN else .EXEC,2832 .Exe => if (self.base.options.pie) .DYN else .EXEC,
2827 .Obj => .REL,2833 .Obj => .REL,
2828 .Lib => switch (self.base.options.link_mode) {2834 .Lib => switch (self.base.options.link_mode) {
...@@ -3147,11 +3153,11 @@ fn initSections(self: *Elf) !void {...@@ -3147,11 +3153,11 @@ fn initSections(self: *Elf) !void {
3147 };3153 };
3148 const ptr_size = self.ptrWidthBytes();3154 const ptr_size = self.ptrWidthBytes();
31493155
3150 for (self.objects.items) |index| {3156 if (!self.isStaticLib()) for (self.objects.items) |index| {
3151 try self.file(index).?.object.initOutputSections(self);3157 try self.file(index).?.object.initOutputSections(self);
3152 }3158 };
31533159
3154 const needs_eh_frame = for (self.objects.items) |index| {3160 const needs_eh_frame = if (self.isStaticLib()) false else for (self.objects.items) |index| {
3155 if (self.file(index).?.object.cies.items.len > 0) break true;3161 if (self.file(index).?.object.cies.items.len > 0) break true;
3156 } else false;3162 } else false;
3157 if (needs_eh_frame) {3163 if (needs_eh_frame) {
...@@ -4954,15 +4960,23 @@ pub fn isStatic(self: Elf) bool {...@@ -4954,15 +4960,23 @@ pub fn isStatic(self: Elf) bool {
4954}4960}
49554961
4956pub fn isObject(self: Elf) bool {4962pub fn isObject(self: Elf) bool {
4957 return self.base.options.effectiveOutputMode() == .Obj;4963 return self.base.options.output_mode == .Obj;
4958}4964}
49594965
4960pub fn isExe(self: Elf) bool {4966pub fn isExe(self: Elf) bool {
4961 return self.base.options.effectiveOutputMode() == .Exe;4967 return self.base.options.output_mode == .Exe;
4968}
4969
4970pub fn isStaticLib(self: Elf) bool {
4971 return self.base.options.output_mode == .Lib and self.isStatic();
4972}
4973
4974pub fn isRelocatable(self: Elf) bool {
4975 return self.isObject() or self.isStaticLib();
4962}4976}
49634977
4964pub fn isDynLib(self: Elf) bool {4978pub fn isDynLib(self: Elf) bool {
4965 return self.base.options.effectiveOutputMode() == .Lib and self.base.options.link_mode == .Dynamic;4979 return self.base.options.output_mode == .Lib and !self.isStatic();
4966}4980}
49674981
4968pub fn isZigSection(self: Elf, shndx: u16) bool {4982pub fn isZigSection(self: Elf, shndx: u16) bool {
src/link/Elf/Atom.zig+2-1
...@@ -605,7 +605,8 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {...@@ -605,7 +605,8 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {
605}605}
606606
607fn outputType(elf_file: *Elf) u2 {607fn outputType(elf_file: *Elf) u2 {
608 return switch (elf_file.base.options.effectiveOutputMode()) {608 assert(!elf_file.isRelocatable());
609 return switch (elf_file.base.options.output_mode) {
609 .Obj => unreachable,610 .Obj => unreachable,
610 .Lib => 0,611 .Lib => 0,
611 .Exe => if (elf_file.base.options.pie) 1 else 2,612 .Exe => if (elf_file.base.options.pie) 1 else 2,
src/link/Elf/ZigObject.zig+4-4
...@@ -287,7 +287,7 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {...@@ -287,7 +287,7 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
287}287}
288288
289pub fn addSectionSymbol(self: *ZigObject, shndx: u16, elf_file: *Elf) !void {289pub fn addSectionSymbol(self: *ZigObject, shndx: u16, elf_file: *Elf) !void {
290 assert(elf_file.isObject());290 assert(elf_file.isRelocatable());
291 const gpa = elf_file.base.allocator;291 const gpa = elf_file.base.allocator;
292 const symbol_index = try elf_file.addSymbol();292 const symbol_index = try elf_file.addSymbol();
293 try self.local_symbols.append(gpa, symbol_index);293 try self.local_symbols.append(gpa, symbol_index);
...@@ -886,7 +886,7 @@ fn updateDeclCode(...@@ -886,7 +886,7 @@ fn updateDeclCode(
886 sym.value = atom_ptr.value;886 sym.value = atom_ptr.value;
887 esym.st_value = atom_ptr.value;887 esym.st_value = atom_ptr.value;
888888
889 if (!elf_file.isObject()) {889 if (!elf_file.isRelocatable()) {
890 log.debug(" (writing new offset table entry)", .{});890 log.debug(" (writing new offset table entry)", .{});
891 assert(sym.flags.has_zig_got);891 assert(sym.flags.has_zig_got);
892 const extra = sym.extra(elf_file).?;892 const extra = sym.extra(elf_file).?;
...@@ -904,7 +904,7 @@ fn updateDeclCode(...@@ -904,7 +904,7 @@ fn updateDeclCode(
904 sym.flags.needs_zig_got = true;904 sym.flags.needs_zig_got = true;
905 esym.st_value = atom_ptr.value;905 esym.st_value = atom_ptr.value;
906906
907 if (!elf_file.isObject()) {907 if (!elf_file.isRelocatable()) {
908 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);908 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
909 try elf_file.zig_got.writeOne(elf_file, gop.index);909 try elf_file.zig_got.writeOne(elf_file, gop.index);
910 }910 }
...@@ -1160,7 +1160,7 @@ fn updateLazySymbol(...@@ -1160,7 +1160,7 @@ fn updateLazySymbol(
1160 local_sym.flags.needs_zig_got = true;1160 local_sym.flags.needs_zig_got = true;
1161 local_esym.st_value = atom_ptr.value;1161 local_esym.st_value = atom_ptr.value;
11621162
1163 if (!elf_file.isObject()) {1163 if (!elf_file.isRelocatable()) {
1164 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);1164 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
1165 try elf_file.zig_got.writeOne(elf_file, gop.index);1165 try elf_file.zig_got.writeOne(elf_file, gop.index);
1166 }1166 }