| ... | ... | @@ -375,152 +375,6 @@ fn filterDice(dices: []macho.data_in_code_entry, start_addr: u64, end_addr: u64) |
| 375 | 375 | return dices[start..end]; |
| 376 | 376 | } |
| 377 | 377 | |
| 378 | | const Context = struct { |
| 379 | | allocator: *Allocator, |
| 380 | | object: *Object, |
| 381 | | macho_file: *MachO, |
| 382 | | match: MachO.MatchingSection, |
| 383 | | }; |
| 384 | | |
| 385 | | const AtomParser = struct { |
| 386 | | section: macho.section_64, |
| 387 | | code: []u8, |
| 388 | | relocs: []macho.relocation_info, |
| 389 | | nlists: []NlistWithIndex, |
| 390 | | index: u32 = 0, |
| 391 | | |
| 392 | | fn peek(self: AtomParser) ?NlistWithIndex { |
| 393 | | return if (self.index + 1 < self.nlists.len) self.nlists[self.index + 1] else null; |
| 394 | | } |
| 395 | | |
| 396 | | fn lessThanBySeniority(context: Context, lhs: NlistWithIndex, rhs: NlistWithIndex) bool { |
| 397 | | if (!MachO.symbolIsExt(rhs.nlist)) { |
| 398 | | return MachO.symbolIsTemp(lhs.nlist, context.object.getString(lhs.nlist.n_strx)); |
| 399 | | } else if (MachO.symbolIsPext(rhs.nlist) or MachO.symbolIsWeakDef(rhs.nlist)) { |
| 400 | | return !MachO.symbolIsExt(lhs.nlist); |
| 401 | | } else { |
| 402 | | return false; |
| 403 | | } |
| 404 | | } |
| 405 | | |
| 406 | | pub fn next(self: *AtomParser, context: Context) !?*Atom { |
| 407 | | if (self.index == self.nlists.len) return null; |
| 408 | | |
| 409 | | const tracy = trace(@src()); |
| 410 | | defer tracy.end(); |
| 411 | | |
| 412 | | var aliases = std.ArrayList(NlistWithIndex).init(context.allocator); |
| 413 | | defer aliases.deinit(); |
| 414 | | |
| 415 | | const next_nlist: ?NlistWithIndex = blk: while (true) { |
| 416 | | const curr_nlist = self.nlists[self.index]; |
| 417 | | try aliases.append(curr_nlist); |
| 418 | | |
| 419 | | if (self.peek()) |next_nlist| { |
| 420 | | if (curr_nlist.nlist.n_value == next_nlist.nlist.n_value) { |
| 421 | | self.index += 1; |
| 422 | | continue; |
| 423 | | } |
| 424 | | break :blk next_nlist; |
| 425 | | } |
| 426 | | break :blk null; |
| 427 | | } else null; |
| 428 | | |
| 429 | | for (aliases.items) |*nlist_with_index| { |
| 430 | | nlist_with_index.index = context.object.symbol_mapping.get(nlist_with_index.index) orelse unreachable; |
| 431 | | } |
| 432 | | |
| 433 | | if (aliases.items.len > 1) { |
| 434 | | // Bubble-up senior symbol as the main link to the atom. |
| 435 | | sort.sort( |
| 436 | | NlistWithIndex, |
| 437 | | aliases.items, |
| 438 | | context, |
| 439 | | AtomParser.lessThanBySeniority, |
| 440 | | ); |
| 441 | | } |
| 442 | | |
| 443 | | const senior_nlist = aliases.pop(); |
| 444 | | const senior_sym = &context.macho_file.locals.items[senior_nlist.index]; |
| 445 | | senior_sym.n_sect = @intCast(u8, context.macho_file.section_ordinals.getIndex(context.match).? + 1); |
| 446 | | |
| 447 | | const start_addr = senior_nlist.nlist.n_value - self.section.addr; |
| 448 | | const end_addr = if (next_nlist) |n| n.nlist.n_value - self.section.addr else self.section.size; |
| 449 | | |
| 450 | | const code = self.code[start_addr..end_addr]; |
| 451 | | const size = code.len; |
| 452 | | |
| 453 | | const max_align = self.section.@"align"; |
| 454 | | const actual_align = if (senior_nlist.nlist.n_value > 0) |
| 455 | | math.min(@ctz(u64, senior_nlist.nlist.n_value), max_align) |
| 456 | | else |
| 457 | | max_align; |
| 458 | | |
| 459 | | const stab: ?Atom.Stab = if (context.object.debug_info) |di| blk: { |
| 460 | | // TODO there has to be a better to handle this. |
| 461 | | for (di.inner.func_list.items) |func| { |
| 462 | | if (func.pc_range) |range| { |
| 463 | | if (senior_nlist.nlist.n_value >= range.start and senior_nlist.nlist.n_value < range.end) { |
| 464 | | break :blk Atom.Stab{ |
| 465 | | .function = range.end - range.start, |
| 466 | | }; |
| 467 | | } |
| 468 | | } |
| 469 | | } |
| 470 | | // TODO |
| 471 | | // if (self.macho_file.globals.contains(self.macho_file.getString(senior_sym.strx))) break :blk .global; |
| 472 | | break :blk .static; |
| 473 | | } else null; |
| 474 | | |
| 475 | | const atom = try context.macho_file.createEmptyAtom(senior_nlist.index, size, actual_align); |
| 476 | | atom.stab = stab; |
| 477 | | |
| 478 | | const is_zerofill = blk: { |
| 479 | | const section_type = commands.sectionType(self.section); |
| 480 | | break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; |
| 481 | | }; |
| 482 | | if (!is_zerofill) { |
| 483 | | mem.copy(u8, atom.code.items, code); |
| 484 | | } |
| 485 | | |
| 486 | | try atom.aliases.ensureTotalCapacity(context.allocator, aliases.items.len); |
| 487 | | for (aliases.items) |alias| { |
| 488 | | atom.aliases.appendAssumeCapacity(alias.index); |
| 489 | | const sym = &context.macho_file.locals.items[alias.index]; |
| 490 | | sym.n_sect = @intCast(u8, context.macho_file.section_ordinals.getIndex(context.match).? + 1); |
| 491 | | } |
| 492 | | |
| 493 | | try atom.parseRelocs(self.relocs, .{ |
| 494 | | .base_addr = self.section.addr, |
| 495 | | .base_offset = start_addr, |
| 496 | | .allocator = context.allocator, |
| 497 | | .object = context.object, |
| 498 | | .macho_file = context.macho_file, |
| 499 | | }); |
| 500 | | |
| 501 | | if (context.macho_file.has_dices) { |
| 502 | | const dices = filterDice( |
| 503 | | context.object.data_in_code_entries.items, |
| 504 | | senior_nlist.nlist.n_value, |
| 505 | | senior_nlist.nlist.n_value + size, |
| 506 | | ); |
| 507 | | try atom.dices.ensureTotalCapacity(context.allocator, dices.len); |
| 508 | | |
| 509 | | for (dices) |dice| { |
| 510 | | atom.dices.appendAssumeCapacity(.{ |
| 511 | | .offset = dice.offset - try math.cast(u32, senior_nlist.nlist.n_value), |
| 512 | | .length = dice.length, |
| 513 | | .kind = dice.kind, |
| 514 | | }); |
| 515 | | } |
| 516 | | } |
| 517 | | |
| 518 | | self.index += 1; |
| 519 | | |
| 520 | | return atom; |
| 521 | | } |
| 522 | | }; |
| 523 | | |
| 524 | 378 | pub fn parseIntoAtoms(self: *Object, allocator: *Allocator, macho_file: *MachO) !void { |
| 525 | 379 | const tracy = trace(@src()); |
| 526 | 380 | defer tracy.end(); |
| ... | ... | @@ -603,17 +457,10 @@ pub fn parseIntoAtoms(self: *Object, allocator: *Allocator, macho_file: *MachO) |
| 603 | 457 | // Since there is no symbol to refer to this atom, we create |
| 604 | 458 | // a temp one, unless we already did that when working out the relocations |
| 605 | 459 | // of other atoms. |
| 606 | | const sym_name = try std.fmt.allocPrint(allocator, "l_{s}_{s}_{s}", .{ |
| 607 | | self.name, |
| 608 | | segmentName(sect), |
| 609 | | sectionName(sect), |
| 610 | | }); |
| 611 | | defer allocator.free(sym_name); |
| 612 | | |
| 613 | 460 | const atom_local_sym_index = self.sections_as_symbols.get(sect_id) orelse blk: { |
| 614 | 461 | const atom_local_sym_index = @intCast(u32, macho_file.locals.items.len); |
| 615 | 462 | try macho_file.locals.append(allocator, .{ |
| 616 | | .n_strx = try macho_file.makeString(sym_name), |
| 463 | .n_strx = 0, |
| 617 | 464 | .n_type = macho.N_SECT, |
| 618 | 465 | .n_sect = @intCast(u8, macho_file.section_ordinals.getIndex(match).? + 1), |
| 619 | 466 | .n_desc = 0, |