authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-11 21:25:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
logb8fce705ad793aab62507d90c44a3fb7a548b90b
tree6d305bec3d7f6a051ece69ee8c15e4dc2d5f9958
parent2a880897b0f7466604058422a7e2fc9f401a4284

zld: refactor nlist and reloc filtering logic


1 files changed, 32 insertions(+), 38 deletions(-)

src/link/MachO/Object.zig+32-38
...@@ -273,59 +273,56 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -273,59 +273,56 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
273 }273 }
274}274}
275275
276fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anytype) usize {
277 if (!@hasDecl(@TypeOf(predicate), "predicate"))
278 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
279
280 if (start == haystack.len) return start;
281
282 var i = start;
283 while (i < haystack.len) : (i += 1) {
284 if (predicate.predicate(haystack[i])) break;
285 }
286 return i;
287}
288
276const NlistWithIndex = struct {289const NlistWithIndex = struct {
277 nlist: macho.nlist_64,290 nlist: macho.nlist_64,
278 index: u32,291 index: u32,
279292
280 fn lessThan(_: void, lhs: @This(), rhs: @This()) bool {293 fn lessThan(_: void, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {
281 return lhs.nlist.n_value < rhs.nlist.n_value;294 return lhs.nlist.n_value < rhs.nlist.n_value;
282 }295 }
283296
284 fn filterInSection(symbols: []@This(), sect_id: u8) []@This() {297 fn filterInSection(symbols: []NlistWithIndex, sect: macho.section_64) []NlistWithIndex {
285 var start: usize = 0;298 const Predicate = struct {
286 var end: usize = symbols.len;299 addr: u64,
287300
288 while (true) {301 fn predicate(self: @This(), symbol: NlistWithIndex) bool {
289 var change = false;302 return symbol.nlist.n_value >= self.addr;
290 if (symbols[start].nlist.n_sect != sect_id) {
291 start += 1;
292 change = true;
293 }
294 if (symbols[end - 1].nlist.n_sect != sect_id) {
295 end -= 1;
296 change = true;
297 }303 }
304 };
298305
299 if (start == end) break;306 const start = findFirst(NlistWithIndex, symbols, 0, Predicate{ .addr = sect.addr });
300 if (!change) break;307 const end = findFirst(NlistWithIndex, symbols, start, Predicate{ .addr = sect.addr + sect.size });
301 }
302308
303 return symbols[start..end];309 return symbols[start..end];
304 }310 }
305};311};
306312
307fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {313fn filterRelocs(relocs: []macho.relocation_info, start_addr: u64, end_addr: u64) []macho.relocation_info {
308 if (relocs.len == 0) return relocs;314 const Predicate = struct {
309315 addr: u64,
310 var start_id: usize = 0;
311 var end_id: usize = relocs.len;
312316
313 while (true) {317 fn predicate(self: @This(), rel: macho.relocation_info) bool {
314 var change = false;318 return rel.r_address < self.addr;
315 if (relocs[start_id].r_address >= end) {
316 start_id += 1;
317 change = true;
318 }
319 if (relocs[end_id - 1].r_address < start) {
320 end_id -= 1;
321 change = true;
322 }319 }
320 };
323321
324 if (start_id == end_id) break;322 const start = findFirst(macho.relocation_info, relocs, 0, Predicate{ .addr = end_addr });
325 if (!change) break;323 const end = findFirst(macho.relocation_info, relocs, start, Predicate{ .addr = start_addr });
326 }
327324
328 return relocs[start_id..end_id];325 return relocs[start..end];
329}326}
330327
331const TextBlockParser = struct {328const TextBlockParser = struct {
...@@ -501,10 +498,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -501,10 +498,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
501 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);498 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
502499
503 // Symbols within this section only.500 // Symbols within this section only.
504 const filtered_nlists = NlistWithIndex.filterInSection(501 const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists.items, sect);
505 sorted_nlists.items,
506 sect_id + 1,
507 );
508502
509 // Is there any padding between symbols within the section?503 // Is there any padding between symbols within the section?
510 const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;504 const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;