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 {
273273 }
274274}
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
276289const NlistWithIndex = struct {
277290 nlist: macho.nlist_64,
278291 index: u32,
279292
280 fn lessThan(_: void, lhs: @This(), rhs: @This()) bool {
293 fn lessThan(_: void, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {
281294 return lhs.nlist.n_value < rhs.nlist.n_value;
282295 }
283296
284 fn filterInSection(symbols: []@This(), sect_id: u8) []@This() {
285 var start: usize = 0;
286 var end: usize = symbols.len;
297 fn filterInSection(symbols: []NlistWithIndex, sect: macho.section_64) []NlistWithIndex {
298 const Predicate = struct {
299 addr: u64,
287300
288 while (true) {
289 var change = false;
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;
301 fn predicate(self: @This(), symbol: NlistWithIndex) bool {
302 return symbol.nlist.n_value >= self.addr;
297303 }
304 };
298305
299 if (start == end) break;
300 if (!change) break;
301 }
306 const start = findFirst(NlistWithIndex, symbols, 0, Predicate{ .addr = sect.addr });
307 const end = findFirst(NlistWithIndex, symbols, start, Predicate{ .addr = sect.addr + sect.size });
302308
303309 return symbols[start..end];
304310 }
305311};
306312
307fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {
308 if (relocs.len == 0) return relocs;
309
310 var start_id: usize = 0;
311 var end_id: usize = relocs.len;
313fn filterRelocs(relocs: []macho.relocation_info, start_addr: u64, end_addr: u64) []macho.relocation_info {
314 const Predicate = struct {
315 addr: u64,
312316
313 while (true) {
314 var change = false;
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;
317 fn predicate(self: @This(), rel: macho.relocation_info) bool {
318 return rel.r_address < self.addr;
322319 }
320 };
323321
324 if (start_id == end_id) break;
325 if (!change) break;
326 }
322 const start = findFirst(macho.relocation_info, relocs, 0, Predicate{ .addr = end_addr });
323 const end = findFirst(macho.relocation_info, relocs, start, Predicate{ .addr = start_addr });
327324
328 return relocs[start_id..end_id];
325 return relocs[start..end];
329326}
330327
331328const TextBlockParser = struct {
......@@ -501,10 +498,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
501498 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
502499
503500 // Symbols within this section only.
504 const filtered_nlists = NlistWithIndex.filterInSection(
505 sorted_nlists.items,
506 sect_id + 1,
507 );
501 const filtered_nlists = NlistWithIndex.filterInSection(sorted_nlists.items, sect);
508502
509503 // Is there any padding between symbols within the section?
510504 const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;