| ... | @@ -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 | } |
| 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 | const NlistWithIndex = struct { | 289 | const NlistWithIndex = struct { |
| 277 | nlist: macho.nlist_64, | 290 | nlist: macho.nlist_64, |
| 278 | index: u32, | 291 | index: u32, |
| 279 | | 292 | |
| 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 | } |
| 283 | | 296 | |
| 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, |
| 287 | | 300 | |
| 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 | }; |
| 298 | | 305 | |
| 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 | } | | |
| 302 | | 308 | |
| 303 | return symbols[start..end]; | 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 { | 313 | fn 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 { |
| 309 | | 315 | addr: u64, |
| 310 | var start_id: usize = 0; | | |
| 311 | var end_id: usize = relocs.len; | | |
| 312 | | 316 | |
| 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 | }; |
| 323 | | 321 | |
| 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 | } | | |
| 327 | | 324 | |
| 328 | return relocs[start_id..end_id]; | 325 | return relocs[start..end]; |
| 329 | } | 326 | } |
| 330 | | 327 | |
| 331 | const TextBlockParser = struct { | 328 | const 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); |
| 502 | | 499 | |
| 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 | ); | | |
| 508 | | 502 | |
| 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; |