| author | |
| committer | |
| log | efa1c6124d167b3144c4d4b15ebf384130d35abd |
| tree | eb0c4757fa06819b748249b2fee5d598212ddf06 |
| parent | 897a554109baa3288d575cac0833e10edd1a316c |
6 files changed, 118 insertions(+), 41 deletions(-)
src/link/MachO.zig+2-2| ... | ... | @@ -380,7 +380,7 @@ pub fn deinit(self: *MachO) void { |
| 380 | 380 | |
| 381 | 381 | pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 382 | 382 | // TODO: I think this is just a temp and can be removed once we can emit static archives |
| 383 | if (self.base.isStaticLib() and build_options.have_llvm) { | |
| 383 | if (self.base.isStaticLib() and build_options.have_llvm and self.base.comp.config.use_llvm) { | |
| 384 | 384 | return self.base.linkAsArchive(arena, prog_node); |
| 385 | 385 | } |
| 386 | 386 | try self.flushModule(arena, prog_node); |
| ... | ... | @@ -396,7 +396,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 396 | 396 | if (self.llvm_object) |llvm_object| { |
| 397 | 397 | try self.base.emitLlvmObject(arena, llvm_object, prog_node); |
| 398 | 398 | // TODO: I think this is just a temp and can be removed once we can emit static archives |
| 399 | if (self.base.isStaticLib() and build_options.have_llvm) return; | |
| 399 | if (self.base.isStaticLib() and build_options.have_llvm and self.base.comp.config.use_llvm) return; | |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | var sub_prog_node = prog_node.start("MachO Flush", 0); |
src/link/MachO/Archive.zig+30-31| ... | ... | @@ -90,7 +90,7 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index: |
| 90 | 90 | |
| 91 | 91 | pub fn writeHeader( |
| 92 | 92 | object_name: []const u8, |
| 93 | object_size: u32, | |
| 93 | object_size: usize, | |
| 94 | 94 | format: Format, |
| 95 | 95 | writer: anytype, |
| 96 | 96 | ) !void { |
| ... | ... | @@ -110,7 +110,7 @@ pub fn writeHeader( |
| 110 | 110 | } |
| 111 | 111 | @memcpy(&hdr.ar_fmag, ARFMAG); |
| 112 | 112 | |
| 113 | const object_name_len = mem.alignForward(u32, object_name.len + 1, format.ptrWidth()); | |
| 113 | const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format)); | |
| 114 | 114 | const total_object_size = object_size + object_name_len; |
| 115 | 115 | |
| 116 | 116 | { |
| ... | ... | @@ -142,12 +142,12 @@ pub const SARMAG: u4 = 8; |
| 142 | 142 | /// String in ar_fmag at the end of each header. |
| 143 | 143 | const ARFMAG: *const [2:0]u8 = "`\n"; |
| 144 | 144 | |
| 145 | const SYMDEF = "__.SYMDEF"; | |
| 146 | const SYMDEF64 = "__.SYMDEF_64"; | |
| 147 | const SYMDEF_SORTED = "__.SYMDEF SORTED"; | |
| 148 | const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; | |
| 145 | pub const SYMDEF = "__.SYMDEF"; | |
| 146 | pub const SYMDEF64 = "__.SYMDEF_64"; | |
| 147 | pub const SYMDEF_SORTED = "__.SYMDEF SORTED"; | |
| 148 | pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; | |
| 149 | 149 | |
| 150 | const ar_hdr = extern struct { | |
| 150 | pub const ar_hdr = extern struct { | |
| 151 | 151 | /// Member file name, sometimes / terminated. |
| 152 | 152 | ar_name: [16]u8, |
| 153 | 153 | |
| ... | ... | @@ -197,7 +197,6 @@ const ar_hdr = extern struct { |
| 197 | 197 | pub const ArSymtab = struct { |
| 198 | 198 | entries: std.ArrayListUnmanaged(Entry) = .{}, |
| 199 | 199 | strtab: StringTable = .{}, |
| 200 | format: Format = .p32, | |
| 201 | 200 | |
| 202 | 201 | pub fn deinit(ar: *ArSymtab, allocator: Allocator) void { |
| 203 | 202 | ar.entries.deinit(allocator); |
| ... | ... | @@ -208,16 +207,16 @@ pub const ArSymtab = struct { |
| 208 | 207 | mem.sort(Entry, ar.entries.items, {}, Entry.lessThan); |
| 209 | 208 | } |
| 210 | 209 | |
| 211 | pub fn size(ar: ArSymtab) usize { | |
| 212 | const ptr_width = ar.format.ptrWidth(); | |
| 210 | pub fn size(ar: ArSymtab, format: Format) usize { | |
| 211 | const ptr_width = ptrWidth(format); | |
| 213 | 212 | return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width); |
| 214 | 213 | } |
| 215 | 214 | |
| 216 | pub fn write(ar: ArSymtab, macho_file: *MachO, writer: anytype) !void { | |
| 215 | pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: anytype) !void { | |
| 217 | 216 | // Header |
| 218 | try writeHeader(SYMDEF, ar.size()); | |
| 217 | try writeHeader(SYMDEF, ar.size(format), format, writer); | |
| 219 | 218 | // Symtab size |
| 220 | try ar.writeInt(ar.entries.items.len * 2); | |
| 219 | try writeInt(format, ar.entries.items.len * 2, writer); | |
| 221 | 220 | // Symtab entries |
| 222 | 221 | for (ar.entries.items) |entry| { |
| 223 | 222 | const file_off = switch (macho_file.getFile(entry.file).?) { |
| ... | ... | @@ -226,14 +225,14 @@ pub const ArSymtab = struct { |
| 226 | 225 | else => unreachable, |
| 227 | 226 | }; |
| 228 | 227 | // Name offset |
| 229 | try ar.writeInt(entry.off); | |
| 228 | try writeInt(format, entry.off, writer); | |
| 230 | 229 | // File offset |
| 231 | try ar.writeInt(file_off); | |
| 230 | try writeInt(format, file_off, writer); | |
| 232 | 231 | } |
| 233 | 232 | // Strtab size |
| 234 | const strtab_size = mem.alignForward(u64, ar.strtab.buffer.items.len, ar.format.ptrWidth()); | |
| 233 | const strtab_size = mem.alignForward(u64, ar.strtab.buffer.items.len, ptrWidth(format)); | |
| 235 | 234 | const padding = strtab_size - ar.strtab.buffer.items.len; |
| 236 | try ar.writeInt(strtab_size); | |
| 235 | try writeInt(format, strtab_size, writer); | |
| 237 | 236 | // Strtab |
| 238 | 237 | try writer.writeAll(ar.strtab.buffer.items); |
| 239 | 238 | if (padding > 0) { |
| ... | ... | @@ -241,13 +240,6 @@ pub const ArSymtab = struct { |
| 241 | 240 | } |
| 242 | 241 | } |
| 243 | 242 | |
| 244 | fn writeInt(ar: ArSymtab, value: u64, writer: anytype) !void { | |
| 245 | switch (ar.format) { | |
| 246 | .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), | |
| 247 | .p64 => try writer.writeInt(u64, value, .little), | |
| 248 | } | |
| 249 | } | |
| 250 | ||
| 251 | 243 | const FormatContext = struct { |
| 252 | 244 | ar: ArSymtab, |
| 253 | 245 | macho_file: *MachO, |
| ... | ... | @@ -288,17 +280,24 @@ pub const ArSymtab = struct { |
| 288 | 280 | }; |
| 289 | 281 | }; |
| 290 | 282 | |
| 291 | const Format = enum { | |
| 283 | pub const Format = enum { | |
| 292 | 284 | p32, |
| 293 | 285 | p64, |
| 286 | }; | |
| 294 | 287 | |
| 295 | fn ptrWidth(self: Format) usize { | |
| 296 | return switch (self) { | |
| 297 | .p32 => @as(usize, 4), | |
| 298 | .p64 => 8, | |
| 299 | }; | |
| 288 | pub fn ptrWidth(format: Format) usize { | |
| 289 | return switch (format) { | |
| 290 | .p32 => @as(usize, 4), | |
| 291 | .p64 => 8, | |
| 292 | }; | |
| 293 | } | |
| 294 | ||
| 295 | pub fn writeInt(format: Format, value: u64, writer: anytype) !void { | |
| 296 | switch (format) { | |
| 297 | .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), | |
| 298 | .p64 => try writer.writeInt(u64, value, .little), | |
| 300 | 299 | } |
| 301 | }; | |
| 300 | } | |
| 302 | 301 | |
| 303 | 302 | pub const ArState = struct { |
| 304 | 303 | /// File offset of the ar_hdr describing the contributing |
src/link/MachO/Object.zig+4-3| ... | ... | @@ -1248,14 +1248,15 @@ pub fn updateArSize(self: *Object, macho_file: *MachO) !void { |
| 1248 | 1248 | self.output_ar_state.size = size; |
| 1249 | 1249 | } |
| 1250 | 1250 | |
| 1251 | pub fn writeAr(self: Object, macho_file: *MachO, writer: anytype) !void { | |
| 1251 | pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { | |
| 1252 | 1252 | // Header |
| 1253 | try Archive.writeHeader(self.path, self.output_ar_state.size, writer); | |
| 1253 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; | |
| 1254 | try Archive.writeHeader(self.path, size, ar_format, writer); | |
| 1254 | 1255 | // Data |
| 1255 | 1256 | const file = macho_file.getFileHandle(self.file_handle); |
| 1256 | 1257 | // TODO try using copyRangeAll |
| 1257 | 1258 | const gpa = macho_file.base.comp.gpa; |
| 1258 | const data = try file.readToEndAlloc(gpa, self.output_ar_state.size); | |
| 1259 | const data = try file.readToEndAlloc(gpa, size); | |
| 1259 | 1260 | defer gpa.free(data); |
| 1260 | 1261 | try writer.writeAll(data); |
| 1261 | 1262 | } |
src/link/MachO/ZigObject.zig+3-2| ... | ... | @@ -314,9 +314,10 @@ pub fn updateArSize(self: *ZigObject) void { |
| 314 | 314 | self.output_ar_state.size = self.data.items.len; |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | pub fn writeAr(self: ZigObject, writer: anytype) !void { | |
| 317 | pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !void { | |
| 318 | 318 | // Header |
| 319 | try Archive.writeHeader(self.path, self.output_ar_state.size, writer); | |
| 319 | const size = std.math.cast(usize, self.output_ar_state.size) orelse return error.Overflow; | |
| 320 | try Archive.writeHeader(self.path, size, ar_format, writer); | |
| 320 | 321 | // Data |
| 321 | 322 | try writer.writeAll(self.data.items); |
| 322 | 323 | } |
src/link/MachO/file.zig+16| ... | ... | @@ -182,6 +182,22 @@ pub const File = union(enum) { |
| 182 | 182 | }; |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | pub fn updateArSize(file: File, macho_file: *MachO) !void { | |
| 186 | return switch (file) { | |
| 187 | .dylib, .internal => unreachable, | |
| 188 | .zig_object => |x| x.updateArSize(), | |
| 189 | .object => |x| x.updateArSize(macho_file), | |
| 190 | }; | |
| 191 | } | |
| 192 | ||
| 193 | pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { | |
| 194 | return switch (file) { | |
| 195 | .dylib, .internal => unreachable, | |
| 196 | .zig_object => |x| x.writeAr(ar_format, writer), | |
| 197 | .object => |x| x.writeAr(ar_format, macho_file, writer), | |
| 198 | }; | |
| 199 | } | |
| 200 | ||
| 185 | 201 | pub fn calcSymtabSize(file: File, macho_file: *MachO) !void { |
| 186 | 202 | return switch (file) { |
| 187 | 203 | inline else => |x| x.calcSymtabSize(macho_file), |
src/link/MachO/relocatable.zig+63-3| ... | ... | @@ -161,6 +161,9 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 161 | 161 | if (macho_file.getZigObject()) |zo| files.appendAssumeCapacity(zo.index); |
| 162 | 162 | for (macho_file.objects.items) |index| files.appendAssumeCapacity(index); |
| 163 | 163 | |
| 164 | const format: Archive.Format = .p32; | |
| 165 | const ptr_width = Archive.ptrWidth(format); | |
| 166 | ||
| 164 | 167 | // Update ar symtab from parsed objects |
| 165 | 168 | var ar_symtab: Archive.ArSymtab = .{}; |
| 166 | 169 | defer ar_symtab.deinit(gpa); |
| ... | ... | @@ -171,14 +174,71 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 171 | 174 | |
| 172 | 175 | ar_symtab.sort(); |
| 173 | 176 | |
| 177 | // Update sizes of contributing objects | |
| 178 | for (files.items) |index| { | |
| 179 | try macho_file.getFile(index).?.updateArSize(macho_file); | |
| 180 | } | |
| 181 | ||
| 182 | // Update file offsets of contributing objects | |
| 183 | const total_size: usize = blk: { | |
| 184 | var pos: usize = Archive.SARMAG; | |
| 185 | pos += @sizeOf(Archive.ar_hdr) + Archive.SYMDEF.len + 1; | |
| 186 | pos = mem.alignForward(usize, pos, ptr_width); | |
| 187 | pos += ar_symtab.size(format); | |
| 188 | ||
| 189 | for (files.items) |index| { | |
| 190 | const file = macho_file.getFile(index).?; | |
| 191 | const state = switch (file) { | |
| 192 | .zig_object => |x| &x.output_ar_state, | |
| 193 | .object => |x| &x.output_ar_state, | |
| 194 | else => unreachable, | |
| 195 | }; | |
| 196 | const path = switch (file) { | |
| 197 | .zig_object => |x| x.path, | |
| 198 | .object => |x| x.path, | |
| 199 | else => unreachable, | |
| 200 | }; | |
| 201 | pos = mem.alignForward(usize, pos, ptr_width); | |
| 202 | state.file_off = pos; | |
| 203 | pos += @sizeOf(Archive.ar_hdr) + path.len + 1; | |
| 204 | pos = mem.alignForward(usize, pos, ptr_width); | |
| 205 | pos += math.cast(usize, state.size) orelse return error.Overflow; | |
| 206 | } | |
| 207 | ||
| 208 | break :blk pos; | |
| 209 | }; | |
| 210 | ||
| 174 | 211 | if (build_options.enable_logging) { |
| 175 | 212 | state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(macho_file)}); |
| 176 | 213 | } |
| 177 | 214 | |
| 178 | var err = try macho_file.addErrorWithNotes(0); | |
| 179 | try err.addMsg(macho_file, "TODO implement flushStaticLib", .{}); | |
| 215 | var buffer = std.ArrayList(u8).init(gpa); | |
| 216 | defer buffer.deinit(); | |
| 217 | try buffer.ensureTotalCapacityPrecise(total_size); | |
| 218 | const writer = buffer.writer(); | |
| 219 | ||
| 220 | // Write magic | |
| 221 | try writer.writeAll(Archive.ARMAG); | |
| 180 | 222 | |
| 181 | return error.FlushFailure; | |
| 223 | // Write symtab | |
| 224 | try ar_symtab.write(format, macho_file, writer); | |
| 225 | ||
| 226 | // Write object files | |
| 227 | for (files.items) |index| { | |
| 228 | const aligned = mem.alignForward(usize, buffer.items.len, ptr_width); | |
| 229 | const padding = aligned - buffer.items.len; | |
| 230 | if (padding > 0) { | |
| 231 | try writer.writeByteNTimes(0, padding); | |
| 232 | } | |
| 233 | try macho_file.getFile(index).?.writeAr(format, macho_file, writer); | |
| 234 | } | |
| 235 | ||
| 236 | assert(buffer.items.len == total_size); | |
| 237 | ||
| 238 | try macho_file.base.file.?.setEndPos(total_size); | |
| 239 | try macho_file.base.file.?.pwriteAll(buffer.items, 0); | |
| 240 | ||
| 241 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | |
| 182 | 242 | } |
| 183 | 243 | |
| 184 | 244 | fn markExports(macho_file: *MachO) void { |