| ... | ... | @@ -12,13 +12,10 @@ const Allocator = mem.Allocator; |
| 12 | 12 | const Arch = std.Target.Cpu.Arch; |
| 13 | 13 | const Object = @import("Object.zig"); |
| 14 | 14 | |
| 15 | | usingnamespace @import("commands.zig"); |
| 15 | file: fs.File, |
| 16 | name: []const u8, |
| 16 | 17 | |
| 17 | | allocator: *Allocator, |
| 18 | | arch: ?Arch = null, |
| 19 | | file: ?fs.File = null, |
| 20 | 18 | header: ?ar_hdr = null, |
| 21 | | name: ?[]const u8 = null, |
| 22 | 19 | |
| 23 | 20 | // The actual contents we care about linking with will be embedded at |
| 24 | 21 | // an offset within a file if we are linking against a fat lib |
| ... | ... | @@ -110,15 +107,13 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u |
| 110 | 107 | errdefer allocator.free(name); |
| 111 | 108 | |
| 112 | 109 | archive.* = .{ |
| 113 | | .allocator = allocator, |
| 114 | | .arch = arch, |
| 115 | 110 | .name = name, |
| 116 | 111 | .file = file, |
| 117 | 112 | }; |
| 118 | 113 | |
| 119 | | archive.parse() catch |err| switch (err) { |
| 114 | archive.parse(allocator, arch) catch |err| switch (err) { |
| 120 | 115 | error.EndOfStream, error.NotArchive => { |
| 121 | | archive.deinit(); |
| 116 | archive.deinit(allocator); |
| 122 | 117 | allocator.destroy(archive); |
| 123 | 118 | return null; |
| 124 | 119 | }, |
| ... | ... | @@ -128,32 +123,23 @@ pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u |
| 128 | 123 | return archive; |
| 129 | 124 | } |
| 130 | 125 | |
| 131 | | pub fn deinit(self: *Archive) void { |
| 126 | pub fn deinit(self: *Archive, allocator: *Allocator) void { |
| 132 | 127 | for (self.toc.keys()) |*key| { |
| 133 | | self.allocator.free(key.*); |
| 128 | allocator.free(key.*); |
| 134 | 129 | } |
| 135 | 130 | for (self.toc.values()) |*value| { |
| 136 | | value.deinit(self.allocator); |
| 137 | | } |
| 138 | | self.toc.deinit(self.allocator); |
| 139 | | |
| 140 | | if (self.name) |n| { |
| 141 | | self.allocator.free(n); |
| 142 | | } |
| 143 | | } |
| 144 | | |
| 145 | | pub fn closeFile(self: Archive) void { |
| 146 | | if (self.file) |f| { |
| 147 | | f.close(); |
| 131 | value.deinit(allocator); |
| 148 | 132 | } |
| 133 | self.toc.deinit(allocator); |
| 134 | allocator.free(self.name); |
| 149 | 135 | } |
| 150 | 136 | |
| 151 | | pub fn parse(self: *Archive) !void { |
| 152 | | self.library_offset = try fat.getLibraryOffset(self.file.?.reader(), self.arch.?); |
| 137 | pub fn parse(self: *Archive, allocator: *Allocator, arch: Arch) !void { |
| 138 | self.library_offset = try fat.getLibraryOffset(self.file.reader(), arch); |
| 153 | 139 | |
| 154 | | try self.file.?.seekTo(self.library_offset); |
| 140 | try self.file.seekTo(self.library_offset); |
| 155 | 141 | |
| 156 | | var reader = self.file.?.reader(); |
| 142 | var reader = self.file.reader(); |
| 157 | 143 | const magic = try reader.readBytesNoEof(SARMAG); |
| 158 | 144 | |
| 159 | 145 | if (!mem.eql(u8, &magic, ARMAG)) { |
| ... | ... | @@ -168,11 +154,11 @@ pub fn parse(self: *Archive) !void { |
| 168 | 154 | return error.NotArchive; |
| 169 | 155 | } |
| 170 | 156 | |
| 171 | | var embedded_name = try parseName(self.allocator, self.header.?, reader); |
| 172 | | log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name.? }); |
| 173 | | defer self.allocator.free(embedded_name); |
| 157 | var embedded_name = try parseName(allocator, self.header.?, reader); |
| 158 | log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name }); |
| 159 | defer allocator.free(embedded_name); |
| 174 | 160 | |
| 175 | | try self.parseTableOfContents(reader); |
| 161 | try self.parseTableOfContents(allocator, reader); |
| 176 | 162 | |
| 177 | 163 | try reader.context.seekTo(0); |
| 178 | 164 | } |
| ... | ... | @@ -195,10 +181,10 @@ fn parseName(allocator: *Allocator, header: ar_hdr, reader: anytype) ![]u8 { |
| 195 | 181 | return name; |
| 196 | 182 | } |
| 197 | 183 | |
| 198 | | fn parseTableOfContents(self: *Archive, reader: anytype) !void { |
| 184 | fn parseTableOfContents(self: *Archive, allocator: *Allocator, reader: anytype) !void { |
| 199 | 185 | const symtab_size = try reader.readIntLittle(u32); |
| 200 | | var symtab = try self.allocator.alloc(u8, symtab_size); |
| 201 | | defer self.allocator.free(symtab); |
| 186 | var symtab = try allocator.alloc(u8, symtab_size); |
| 187 | defer allocator.free(symtab); |
| 202 | 188 | |
| 203 | 189 | reader.readNoEof(symtab) catch { |
| 204 | 190 | log.err("incomplete symbol table: expected symbol table of length 0x{x}", .{symtab_size}); |
| ... | ... | @@ -206,8 +192,8 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void { |
| 206 | 192 | }; |
| 207 | 193 | |
| 208 | 194 | const strtab_size = try reader.readIntLittle(u32); |
| 209 | | var strtab = try self.allocator.alloc(u8, strtab_size); |
| 210 | | defer self.allocator.free(strtab); |
| 195 | var strtab = try allocator.alloc(u8, strtab_size); |
| 196 | defer allocator.free(strtab); |
| 211 | 197 | |
| 212 | 198 | reader.readNoEof(strtab) catch { |
| 213 | 199 | log.err("incomplete symbol table: expected string table of length 0x{x}", .{strtab_size}); |
| ... | ... | @@ -225,21 +211,21 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void { |
| 225 | 211 | const object_offset = try symtab_reader.readIntLittle(u32); |
| 226 | 212 | |
| 227 | 213 | const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + n_strx)); |
| 228 | | const owned_name = try self.allocator.dupe(u8, sym_name); |
| 229 | | const res = try self.toc.getOrPut(self.allocator, owned_name); |
| 230 | | defer if (res.found_existing) self.allocator.free(owned_name); |
| 214 | const owned_name = try allocator.dupe(u8, sym_name); |
| 215 | const res = try self.toc.getOrPut(allocator, owned_name); |
| 216 | defer if (res.found_existing) allocator.free(owned_name); |
| 231 | 217 | |
| 232 | 218 | if (!res.found_existing) { |
| 233 | 219 | res.value_ptr.* = .{}; |
| 234 | 220 | } |
| 235 | 221 | |
| 236 | | try res.value_ptr.append(self.allocator, object_offset); |
| 222 | try res.value_ptr.append(allocator, object_offset); |
| 237 | 223 | } |
| 238 | 224 | } |
| 239 | 225 | |
| 240 | 226 | /// Caller owns the Object instance. |
| 241 | | pub fn parseObject(self: Archive, offset: u32) !*Object { |
| 242 | | var reader = self.file.?.reader(); |
| 227 | pub fn parseObject(self: Archive, allocator: *Allocator, arch: Arch, offset: u32) !*Object { |
| 228 | var reader = self.file.reader(); |
| 243 | 229 | try reader.context.seekTo(offset + self.library_offset); |
| 244 | 230 | |
| 245 | 231 | const object_header = try reader.readStruct(ar_hdr); |
| ... | ... | @@ -249,27 +235,27 @@ pub fn parseObject(self: Archive, offset: u32) !*Object { |
| 249 | 235 | return error.MalformedArchive; |
| 250 | 236 | } |
| 251 | 237 | |
| 252 | | const object_name = try parseName(self.allocator, object_header, reader); |
| 253 | | defer self.allocator.free(object_name); |
| 238 | const object_name = try parseName(allocator, object_header, reader); |
| 239 | defer allocator.free(object_name); |
| 254 | 240 | |
| 255 | | log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name.? }); |
| 241 | log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name }); |
| 256 | 242 | |
| 257 | 243 | const name = name: { |
| 258 | 244 | var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; |
| 259 | | const path = try std.os.realpath(self.name.?, &buffer); |
| 260 | | break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name }); |
| 245 | const path = try std.os.realpath(self.name, &buffer); |
| 246 | break :name try std.fmt.allocPrint(allocator, "{s}({s})", .{ path, object_name }); |
| 261 | 247 | }; |
| 262 | 248 | |
| 263 | | var object = try self.allocator.create(Object); |
| 264 | | errdefer self.allocator.destroy(object); |
| 249 | var object = try allocator.create(Object); |
| 250 | errdefer allocator.destroy(object); |
| 265 | 251 | |
| 266 | 252 | object.* = .{ |
| 267 | | .file = try fs.cwd().openFile(self.name.?, .{}), |
| 253 | .file = try fs.cwd().openFile(self.name, .{}), |
| 268 | 254 | .name = name, |
| 269 | 255 | .file_offset = @intCast(u32, try reader.context.getPos()), |
| 270 | 256 | .mtime = try self.header.?.date(), |
| 271 | 257 | }; |
| 272 | | try object.parse(self.allocator, self.arch.?); |
| 258 | try object.parse(allocator, arch); |
| 273 | 259 | try reader.context.seekTo(0); |
| 274 | 260 | |
| 275 | 261 | return object; |