authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 20:32:02+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 20:34:40+02:00
logb5b25d38a8fa4e66e54ff1279c1becee877793f6
tree38aeff3d774dc291e75dcdd869c1eb3b2653b804
parentbdab4f53c1fa614fcd89468f305184fa36520039

Fix improper reuse of global symbols in MachO

Signed-off-by: Jakub Konka <kubkon@jakubkonka.com>

4 files changed, 42 insertions(+), 9 deletions(-)

src/Module.zig+12-3
...@@ -93,7 +93,7 @@ pub const Export = struct {...@@ -93,7 +93,7 @@ pub const Export = struct {
93 /// Byte offset into the file that contains the export directive.93 /// Byte offset into the file that contains the export directive.
94 src: usize,94 src: usize,
95 /// Represents the position of the export, if any, in the output file.95 /// Represents the position of the export, if any, in the output file.
96 link: link.File.Elf.Export,96 link: link.File.Export,
97 /// The Decl that performs the export. Note that this is *not* the Decl being exported.97 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
98 owner_decl: *Decl,98 owner_decl: *Decl,
99 /// The Decl being exported. Note this is *not* the Decl performing the export.99 /// The Decl being exported. Note this is *not* the Decl performing the export.
...@@ -1712,7 +1712,10 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {...@@ -1712,7 +1712,10 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
1712 }1712 }
1713 }1713 }
1714 if (self.comp.bin_file.cast(link.File.Elf)) |elf| {1714 if (self.comp.bin_file.cast(link.File.Elf)) |elf| {
1715 elf.deleteExport(exp.link);1715 elf.deleteExport(exp.link.elf);
1716 }
1717 if (self.comp.bin_file.cast(link.File.MachO)) |macho| {
1718 macho.deleteExport(exp.link.macho);
1716 }1719 }
1717 if (self.failed_exports.remove(exp)) |entry| {1720 if (self.failed_exports.remove(exp)) |entry| {
1718 entry.value.destroy(self.gpa);1721 entry.value.destroy(self.gpa);
...@@ -1875,7 +1878,13 @@ pub fn analyzeExport(self: *Module, scope: *Scope, src: usize, borrowed_symbol_n...@@ -1875,7 +1878,13 @@ pub fn analyzeExport(self: *Module, scope: *Scope, src: usize, borrowed_symbol_n
1875 new_export.* = .{1878 new_export.* = .{
1876 .options = .{ .name = symbol_name },1879 .options = .{ .name = symbol_name },
1877 .src = src,1880 .src = src,
1878 .link = .{},1881 .link = switch (self.comp.bin_file.tag) {
1882 .coff => .{ .coff = {} },
1883 .elf => .{ .elf = link.File.Elf.Export{} },
1884 .macho => .{ .macho = link.File.MachO.Export{} },
1885 .c => .{ .c = {} },
1886 .wasm => .{ .wasm = {} },
1887 },
1879 .owner_decl = owner_decl,1888 .owner_decl = owner_decl,
1880 .exported_decl = exported_decl,1889 .exported_decl = exported_decl,
1881 .status = .in_progress,1890 .status = .in_progress,
src/link.zig+8
...@@ -133,6 +133,14 @@ pub const File = struct {...@@ -133,6 +133,14 @@ pub const File = struct {
133 wasm: ?Wasm.FnData,133 wasm: ?Wasm.FnData,
134 };134 };
135135
136 pub const Export = union {
137 elf: Elf.Export,
138 coff: void,
139 macho: MachO.Export,
140 c: void,
141 wasm: void,
142 };
143
136 /// For DWARF .debug_info.144 /// For DWARF .debug_info.
137 pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.hash, Type.eql, std.hash_map.DefaultMaxLoadPercentage);145 pub const DbgInfoTypeRelocsTable = std.HashMapUnmanaged(Type, DbgInfoTypeReloc, Type.hash, Type.eql, std.hash_map.DefaultMaxLoadPercentage);
138146
src/link/Elf.zig+2-2
...@@ -2588,7 +2588,7 @@ pub fn updateDeclExports(...@@ -2588,7 +2588,7 @@ pub fn updateDeclExports(
2588 },2588 },
2589 };2589 };
2590 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);2590 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);
2591 if (exp.link.sym_index) |i| {2591 if (exp.link.elf.sym_index) |i| {
2592 const sym = &self.global_symbols.items[i];2592 const sym = &self.global_symbols.items[i];
2593 sym.* = .{2593 sym.* = .{
2594 .st_name = try self.updateString(sym.st_name, exp.options.name),2594 .st_name = try self.updateString(sym.st_name, exp.options.name),
...@@ -2613,7 +2613,7 @@ pub fn updateDeclExports(...@@ -2613,7 +2613,7 @@ pub fn updateDeclExports(
2613 .st_size = decl_sym.st_size,2613 .st_size = decl_sym.st_size,
2614 };2614 };
26152615
2616 exp.link.sym_index = @intCast(u32, i);2616 exp.link.elf.sym_index = @intCast(u32, i);
2617 }2617 }
2618 }2618 }
2619}2619}
src/link/MachO.zig+20-4
...@@ -115,6 +115,9 @@ local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -115,6 +115,9 @@ local_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
115global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},115global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
116/// Table of all undefined symbols116/// Table of all undefined symbols
117undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},117undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
118
119global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},
120
118dyld_stub_binder_index: ?u16 = null,121dyld_stub_binder_index: ?u16 = null,
119122
120/// Table of symbol names aka the string table.123/// Table of symbol names aka the string table.
...@@ -178,6 +181,10 @@ pub const TextBlock = struct {...@@ -178,6 +181,10 @@ pub const TextBlock = struct {
178 };181 };
179};182};
180183
184pub const Export = struct {
185 sym_index: ?u32 = null,
186};
187
181pub const SrcFn = struct {188pub const SrcFn = struct {
182 pub const empty = SrcFn{};189 pub const empty = SrcFn{};
183};190};
...@@ -713,6 +720,7 @@ pub fn deinit(self: *MachO) void {...@@ -713,6 +720,7 @@ pub fn deinit(self: *MachO) void {
713 self.string_table.deinit(self.base.allocator);720 self.string_table.deinit(self.base.allocator);
714 self.undef_symbols.deinit(self.base.allocator);721 self.undef_symbols.deinit(self.base.allocator);
715 self.global_symbols.deinit(self.base.allocator);722 self.global_symbols.deinit(self.base.allocator);
723 self.global_symbol_free_list.deinit(self.base.allocator);
716 self.local_symbols.deinit(self.base.allocator);724 self.local_symbols.deinit(self.base.allocator);
717 self.sections.deinit(self.base.allocator);725 self.sections.deinit(self.base.allocator);
718 self.load_commands.deinit(self.base.allocator);726 self.load_commands.deinit(self.base.allocator);
...@@ -837,7 +845,7 @@ pub fn updateDeclExports(...@@ -837,7 +845,7 @@ pub fn updateDeclExports(
837 },845 },
838 };846 };
839 const n_type = decl_sym.n_type | macho.N_EXT;847 const n_type = decl_sym.n_type | macho.N_EXT;
840 if (exp.link.sym_index) |i| {848 if (exp.link.macho.sym_index) |i| {
841 const sym = &self.global_symbols.items[i];849 const sym = &self.global_symbols.items[i];
842 sym.* = .{850 sym.* = .{
843 .n_strx = try self.updateString(sym.n_strx, exp.options.name),851 .n_strx = try self.updateString(sym.n_strx, exp.options.name),
...@@ -848,8 +856,10 @@ pub fn updateDeclExports(...@@ -848,8 +856,10 @@ pub fn updateDeclExports(
848 };856 };
849 } else {857 } else {
850 const name_str_index = try self.makeString(exp.options.name);858 const name_str_index = try self.makeString(exp.options.name);
851 _ = self.global_symbols.addOneAssumeCapacity();859 const i = if (self.global_symbol_free_list.popOrNull()) |i| i else blk: {
852 const i = self.global_symbols.items.len - 1;860 _ = self.global_symbols.addOneAssumeCapacity();
861 break :blk self.global_symbols.items.len - 1;
862 };
853 self.global_symbols.items[i] = .{863 self.global_symbols.items[i] = .{
854 .n_strx = name_str_index,864 .n_strx = name_str_index,
855 .n_type = n_type,865 .n_type = n_type,
...@@ -858,11 +868,17 @@ pub fn updateDeclExports(...@@ -858,11 +868,17 @@ pub fn updateDeclExports(
858 .n_value = decl_sym.n_value,868 .n_value = decl_sym.n_value,
859 };869 };
860870
861 exp.link.sym_index = @intCast(u32, i);871 exp.link.macho.sym_index = @intCast(u32, i);
862 }872 }
863 }873 }
864}874}
865875
876pub fn deleteExport(self: *MachO, exp: Export) void {
877 const sym_index = exp.sym_index orelse return;
878 self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {};
879 self.global_symbols.items[sym_index].n_type = 0;
880}
881
866pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}882pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
867883
868pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {884pub fn getDeclVAddr(self: *MachO, decl: *const Module.Decl) u64 {