| ... | @@ -20,6 +20,11 @@ name: []u8, | ... | @@ -20,6 +20,11 @@ name: []u8, |
| 20 | | 20 | |
| 21 | objects: std.ArrayListUnmanaged(Object) = .{}, | 21 | objects: std.ArrayListUnmanaged(Object) = .{}, |
| 22 | | 22 | |
| | 23 | /// Parsed table of contents. |
| | 24 | /// Each symbol name points to a list of all definition |
| | 25 | /// sites within the current static archive. |
| | 26 | toc: std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(u32)) = .{}, |
| | 27 | |
| 23 | // Archive files start with the ARMAG identifying string. Then follows a | 28 | // Archive files start with the ARMAG identifying string. Then follows a |
| 24 | // `struct ar_hdr', and as many bytes of member file data as its `ar_size' | 29 | // `struct ar_hdr', and as many bytes of member file data as its `ar_size' |
| 25 | // member indicates, for each member file. | 30 | // member indicates, for each member file. |
| ... | @@ -88,6 +93,11 @@ pub fn deinit(self: *Archive) void { | ... | @@ -88,6 +93,11 @@ pub fn deinit(self: *Archive) void { |
| 88 | object.deinit(); | 93 | object.deinit(); |
| 89 | } | 94 | } |
| 90 | self.objects.deinit(self.allocator); | 95 | self.objects.deinit(self.allocator); |
| | 96 | for (self.toc.items()) |*entry| { |
| | 97 | self.allocator.free(entry.key); |
| | 98 | entry.value.deinit(self.allocator); |
| | 99 | } |
| | 100 | self.toc.deinit(self.allocator); |
| 91 | self.file.close(); | 101 | self.file.close(); |
| 92 | } | 102 | } |
| 93 | | 103 | |
| ... | @@ -159,8 +169,20 @@ fn readTableOfContents(self: *Archive, reader: anytype) ![]u32 { | ... | @@ -159,8 +169,20 @@ fn readTableOfContents(self: *Archive, reader: anytype) ![]u32 { |
| 159 | }; | 169 | }; |
| 160 | const object_offset = try symtab_reader.readIntLittle(u32); | 170 | const object_offset = try symtab_reader.readIntLittle(u32); |
| 161 | | 171 | |
| 162 | // TODO Store the table of contents for later reuse. | 172 | const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + n_strx)); |
| | 173 | const owned_name = try self.allocator.dupe(u8, sym_name); |
| | 174 | const res = try self.toc.getOrPut(self.allocator, owned_name); |
| | 175 | defer if (res.found_existing) self.allocator.free(owned_name); |
| | 176 | |
| | 177 | if (!res.found_existing) { |
| | 178 | res.entry.value = .{}; |
| | 179 | } |
| | 180 | |
| | 181 | try res.entry.value.append(self.allocator, object_offset); |
| 163 | | 182 | |
| | 183 | // TODO This will go once we properly use archive's TOC to pick |
| | 184 | // an object which defines a missing symbol rather than pasting in |
| | 185 | // all of the objects always. |
| 164 | // Here, we assume that symbols are NOT sorted in any way, and | 186 | // Here, we assume that symbols are NOT sorted in any way, and |
| 165 | // they point to objects in sequence. | 187 | // they point to objects in sequence. |
| 166 | if (object_offsets.items[last] != object_offset) { | 188 | if (object_offsets.items[last] != object_offset) { |