| ... | ... | @@ -273,59 +273,56 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void { |
| 273 | 273 | } |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | fn 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 | |
| 276 | 289 | const NlistWithIndex = struct { |
| 277 | 290 | nlist: macho.nlist_64, |
| 278 | 291 | index: u32, |
| 279 | 292 | |
| 280 | | fn lessThan(_: void, lhs: @This(), rhs: @This()) bool { |
| 293 | fn lessThan(_: void, lhs: NlistWithIndex, rhs: NlistWithIndex) bool { |
| 281 | 294 | return lhs.nlist.n_value < rhs.nlist.n_value; |
| 282 | 295 | } |
| 283 | 296 | |
| 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, |
| 287 | 300 | |
| 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; |
| 297 | 303 | } |
| 304 | }; |
| 298 | 305 | |
| 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 }); |
| 302 | 308 | |
| 303 | 309 | return symbols[start..end]; |
| 304 | 310 | } |
| 305 | 311 | }; |
| 306 | 312 | |
| 307 | | fn 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; |
| 313 | fn filterRelocs(relocs: []macho.relocation_info, start_addr: u64, end_addr: u64) []macho.relocation_info { |
| 314 | const Predicate = struct { |
| 315 | addr: u64, |
| 312 | 316 | |
| 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; |
| 322 | 319 | } |
| 320 | }; |
| 323 | 321 | |
| 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 }); |
| 327 | 324 | |
| 328 | | return relocs[start_id..end_id]; |
| 325 | return relocs[start..end]; |
| 329 | 326 | } |
| 330 | 327 | |
| 331 | 328 | const TextBlockParser = struct { |
| ... | ... | @@ -501,10 +498,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 501 | 498 | const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs); |
| 502 | 499 | |
| 503 | 500 | // 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); |
| 508 | 502 | |
| 509 | 503 | // Is there any padding between symbols within the section? |
| 510 | 504 | const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0; |