authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-16 17:18:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-16 17:18:53+02:00
log54a403d4ff9e20daf1843725012ae44ec828a833
tree1c1679ee843c9caeb1986062a400cc42a645d560
parent5a2bea29315158bc05fb4b09842bbb9ae0ddfada

zld: replace parsed reloc with a simple wrapper around macho.relocation_info


6 files changed, 340 insertions(+), 617 deletions(-)

CMakeLists.txt-1
...@@ -581,7 +581,6 @@ set(ZIG_STAGE2_SOURCES...@@ -581,7 +581,6 @@ set(ZIG_STAGE2_SOURCES
581 "${CMAKE_SOURCE_DIR}/src/link/MachO/DebugSymbols.zig"581 "${CMAKE_SOURCE_DIR}/src/link/MachO/DebugSymbols.zig"
582 "${CMAKE_SOURCE_DIR}/src/link/MachO/Dylib.zig"582 "${CMAKE_SOURCE_DIR}/src/link/MachO/Dylib.zig"
583 "${CMAKE_SOURCE_DIR}/src/link/MachO/Object.zig"583 "${CMAKE_SOURCE_DIR}/src/link/MachO/Object.zig"
584 "${CMAKE_SOURCE_DIR}/src/link/MachO/Symbol.zig"
585 "${CMAKE_SOURCE_DIR}/src/link/MachO/TextBlock.zig"584 "${CMAKE_SOURCE_DIR}/src/link/MachO/TextBlock.zig"
586 "${CMAKE_SOURCE_DIR}/src/link/MachO/Trie.zig"585 "${CMAKE_SOURCE_DIR}/src/link/MachO/Trie.zig"
587 "${CMAKE_SOURCE_DIR}/src/link/MachO/Zld.zig"586 "${CMAKE_SOURCE_DIR}/src/link/MachO/Zld.zig"
src/link/MachO/Dylib.zig+2-2
...@@ -12,8 +12,8 @@ const fat = @import("fat.zig");...@@ -12,8 +12,8 @@ const fat = @import("fat.zig");
1212
13const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
14const Arch = std.Target.Cpu.Arch;14const Arch = std.Target.Cpu.Arch;
15const Symbol = @import("Symbol.zig");
16const LibStub = @import("../tapi.zig").LibStub;15const LibStub = @import("../tapi.zig").LibStub;
16const Zld = @import("Zld.zig");
1717
18usingnamespace @import("commands.zig");18usingnamespace @import("commands.zig");
1919
...@@ -324,7 +324,7 @@ fn parseSymbols(self: *Dylib) !void {...@@ -324,7 +324,7 @@ fn parseSymbols(self: *Dylib) !void {
324 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff + self.library_offset);324 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff + self.library_offset);
325325
326 for (slice) |sym| {326 for (slice) |sym| {
327 const add_to_symtab = Symbol.isExt(sym) and (Symbol.isSect(sym) or Symbol.isIndr(sym));327 const add_to_symtab = Zld.symbolIsExt(sym) and (Zld.symbolIsSect(sym) or Zld.symbolIsIndr(sym));
328328
329 if (!add_to_symtab) continue;329 if (!add_to_symtab) continue;
330330
src/link/MachO/Object.zig+277-252
...@@ -9,13 +9,10 @@ const log = std.log.scoped(.object);...@@ -9,13 +9,10 @@ const log = std.log.scoped(.object);
9const macho = std.macho;9const macho = std.macho;
10const math = std.math;10const math = std.math;
11const mem = std.mem;11const mem = std.mem;
12const reloc = @import("reloc.zig");
13const sort = std.sort;12const sort = std.sort;
1413
15const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
16const Arch = std.Target.Cpu.Arch;15const Arch = std.Target.Cpu.Arch;
17const Relocation = reloc.Relocation;
18const Symbol = @import("Symbol.zig");
19const TextBlock = @import("TextBlock.zig");16const TextBlock = @import("TextBlock.zig");
20const Zld = @import("Zld.zig");17const Zld = @import("Zld.zig");
2118
...@@ -57,6 +54,8 @@ tu_comp_dir: ?[]const u8 = null,...@@ -57,6 +54,8 @@ tu_comp_dir: ?[]const u8 = null,
57mtime: ?u64 = null,54mtime: ?u64 = null,
5855
59text_blocks: std.ArrayListUnmanaged(*TextBlock) = .{},56text_blocks: std.ArrayListUnmanaged(*TextBlock) = .{},
57sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},
58symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},
6059
61const DebugInfo = struct {60const DebugInfo = struct {
62 inner: dwarf.DwarfInfo,61 inner: dwarf.DwarfInfo,
...@@ -163,6 +162,8 @@ pub fn deinit(self: *Object) void {...@@ -163,6 +162,8 @@ pub fn deinit(self: *Object) void {
163 self.symtab.deinit(self.allocator);162 self.symtab.deinit(self.allocator);
164 self.strtab.deinit(self.allocator);163 self.strtab.deinit(self.allocator);
165 self.text_blocks.deinit(self.allocator);164 self.text_blocks.deinit(self.allocator);
165 self.sections_as_symbols.deinit(self.allocator);
166 self.symbol_mapping.deinit(self.allocator);
166167
167 if (self.debug_info) |*db| {168 if (self.debug_info) |*db| {
168 db.deinit(self.allocator);169 db.deinit(self.allocator);
...@@ -372,20 +373,17 @@ const TextBlockParser = struct {...@@ -372,20 +373,17 @@ const TextBlockParser = struct {
372 }373 }
373374
374 const SeniorityContext = struct {375 const SeniorityContext = struct {
375 zld: *Zld,376 object: *Object,
376 };377 };
377378
378 fn lessThanBySeniority(context: SeniorityContext, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {379 fn lessThanBySeniority(context: SeniorityContext, lhs: NlistWithIndex, rhs: NlistWithIndex) bool {
379 const lsym = context.zld.locals.items[lhs.index];380 if (!Zld.symbolIsExt(rhs.nlist)) {
380 const rsym = context.zld.locals.items[rhs.index];381 return Zld.symbolIsTemp(lhs.nlist, context.object.getString(lhs.nlist.n_strx));
381 const lreg = lsym.payload.regular;382 } else if (Zld.symbolIsPext(rhs.nlist) or Zld.symbolIsWeakDef(rhs.nlist)) {
382 const rreg = rsym.payload.regular;383 return !Zld.symbolIsExt(lhs.nlist);
383384 } else {
384 return switch (rreg.linkage) {385 return true;
385 .global => true,386 }
386 .linkage_unit => lreg.linkage == .translation_unit,
387 else => lsym.isTemp(context.zld),
388 };
389 }387 }
390388
391 pub fn next(self: *TextBlockParser) !?*TextBlock {389 pub fn next(self: *TextBlockParser) !?*TextBlock {
...@@ -409,6 +407,7 @@ const TextBlockParser = struct {...@@ -409,6 +407,7 @@ const TextBlockParser = struct {
409 } else null;407 } else null;
410408
411 for (aliases.items) |*nlist_with_index| {409 for (aliases.items) |*nlist_with_index| {
410 nlist_with_index.index = self.symbol_mapping.get(nlist_with_index.index);
412 const sym = self.object.symbols.items[nlist_with_index.index];411 const sym = self.object.symbols.items[nlist_with_index.index];
413 if (sym.payload != .regular) {412 if (sym.payload != .regular) {
414 log.err("expected a regular symbol, found {s}", .{sym.payload});413 log.err("expected a regular symbol, found {s}", .{sym.payload});
...@@ -424,7 +423,7 @@ const TextBlockParser = struct {...@@ -424,7 +423,7 @@ const TextBlockParser = struct {
424 sort.sort(423 sort.sort(
425 NlistWithIndex,424 NlistWithIndex,
426 aliases.items,425 aliases.items,
427 SeniorityContext{ .zld = self.zld },426 SeniorityContext{ .object = self.object },
428 @This().lessThanBySeniority,427 @This().lessThanBySeniority,
429 );428 );
430 }429 }
...@@ -515,7 +514,7 @@ const TextBlockParser = struct {...@@ -515,7 +514,7 @@ const TextBlockParser = struct {
515pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {514pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
516 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;515 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
517516
518 log.debug("analysing {s}", .{self.name.?});517 log.warn("analysing {s}", .{self.name.?});
519518
520 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;519 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
521 // We only care about defined symbols, so filter every other out.520 // We only care about defined symbols, so filter every other out.
...@@ -536,14 +535,14 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -536,14 +535,14 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
536535
537 for (seg.sections.items) |sect, id| {536 for (seg.sections.items) |sect, id| {
538 const sect_id = @intCast(u8, id);537 const sect_id = @intCast(u8, id);
539 log.debug("putting section '{s},{s}' as a TextBlock", .{538 log.warn("putting section '{s},{s}' as a TextBlock", .{
540 segmentName(sect),539 segmentName(sect),
541 sectionName(sect),540 sectionName(sect),
542 });541 });
543542
544 // Get matching segment/section in the final artifact.543 // Get matching segment/section in the final artifact.
545 const match = (try zld.getMatchingSection(sect)) orelse {544 const match = (try zld.getMatchingSection(sect)) orelse {
546 log.debug("unhandled section", .{});545 log.warn("unhandled section", .{});
547 continue;546 continue;
548 };547 };
549548
...@@ -577,200 +576,249 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -577,200 +576,249 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
577 };576 };
578 zld.has_stabs = zld.has_stabs or self.debug_info != null;577 zld.has_stabs = zld.has_stabs or self.debug_info != null;
579578
580 next: {579 {
581 if (is_splittable) blocks: {580 // next: {
582 if (filtered_nlists.len == 0) break :blocks;581 // if (is_splittable) blocks: {
583582 // if (filtered_nlists.len == 0) break :blocks;
584 // If the first nlist does not match the start of the section,583
585 // then we need encapsulate the memory range [section start, first symbol)584 // // If the first nlist does not match the start of the section,
586 // as a temporary symbol and insert the matching TextBlock.585 // // then we need encapsulate the memory range [section start, first symbol)
587 const first_nlist = filtered_nlists[0].nlist;586 // // as a temporary symbol and insert the matching TextBlock.
588 if (first_nlist.n_value > sect.addr) {587 // const first_nlist = filtered_nlists[0].nlist;
589 const symbol = self.sections_as_symbols.get(sect_id) orelse symbol: {588 // if (first_nlist.n_value > sect.addr) {
590 const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{589 // const symbol = self.sections_as_symbols.get(sect_id) orelse symbol: {
591 self.name.?,590 // const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
592 segmentName(sect),591 // self.name.?,
593 sectionName(sect),592 // segmentName(sect),
594 });593 // sectionName(sect),
595 defer self.allocator.free(name);594 // });
596 const symbol = try zld.allocator.create(Symbol);595 // defer self.allocator.free(name);
597 symbol.* = .{596 // const symbol = try zld.allocator.create(Symbol);
598 .strx = try zld.makeString(name),597 // symbol.* = .{
599 .payload = .{ .undef = .{} },598 // .strx = try zld.makeString(name),
600 };599 // .payload = .{ .undef = .{} },
601 try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol);600 // };
602 break :symbol symbol;601 // try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol);
603 };602 // break :symbol symbol;
604603 // };
605 const local_sym_index = @intCast(u32, zld.locals.items.len);604
606 symbol.payload = .{605 // const local_sym_index = @intCast(u32, zld.locals.items.len);
607 .regular = .{606 // symbol.payload = .{
608 .linkage = .translation_unit,607 // .regular = .{
609 .address = sect.addr,608 // .linkage = .translation_unit,
610 .segment_id = match.seg,609 // .address = sect.addr,
611 .section_id = match.sect,610 // .segment_id = match.seg,
612 .file = self,611 // .section_id = match.sect,
613 .local_sym_index = local_sym_index,612 // .file = self,
614 },613 // .local_sym_index = local_sym_index,
615 };614 // },
616 try zld.locals.append(zld.allocator, symbol);615 // };
617616 // try zld.locals.append(zld.allocator, symbol);
618 const block_code = code[0 .. first_nlist.n_value - sect.addr];617
619 const block_size = block_code.len;618 // const block_code = code[0 .. first_nlist.n_value - sect.addr];
620619 // const block_size = block_code.len;
621 const block = try self.allocator.create(TextBlock);620
622 errdefer self.allocator.destroy(block);621 // const block = try self.allocator.create(TextBlock);
623622 // errdefer self.allocator.destroy(block);
624 block.* = TextBlock.init(self.allocator);623
625 block.local_sym_index = local_sym_index;624 // block.* = TextBlock.init(self.allocator);
626 block.code = try self.allocator.dupe(u8, block_code);625 // block.local_sym_index = local_sym_index;
627 block.size = block_size;626 // block.code = try self.allocator.dupe(u8, block_code);
628 block.alignment = sect.@"align";627 // block.size = block_size;
629628 // block.alignment = sect.@"align";
630 const block_relocs = filterRelocs(relocs, 0, block_size);629
631 if (block_relocs.len > 0) {630 // const block_relocs = filterRelocs(relocs, 0, block_size);
632 try self.parseRelocs(zld, block_relocs, block, 0);631 // if (block_relocs.len > 0) {
633 }632 // try self.parseRelocs(zld, block_relocs, block, 0);
634633 // }
635 if (zld.has_dices) {634
636 const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size);635 // if (zld.has_dices) {
637 try block.dices.ensureTotalCapacity(dices.len);636 // const dices = filterDice(self.data_in_code_entries.items, sect.addr, sect.addr + block_size);
638637 // try block.dices.ensureTotalCapacity(dices.len);
639 for (dices) |dice| {638
640 block.dices.appendAssumeCapacity(.{639 // for (dices) |dice| {
641 .offset = dice.offset - try math.cast(u32, sect.addr),640 // block.dices.appendAssumeCapacity(.{
642 .length = dice.length,641 // .offset = dice.offset - try math.cast(u32, sect.addr),
643 .kind = dice.kind,642 // .length = dice.length,
644 });643 // .kind = dice.kind,
645 }644 // });
646 }645 // }
647646 // }
648 // Update target section's metadata647
649 // TODO should we update segment's size here too?648 // // Update target section's metadata
650 // How does it tie with incremental space allocs?649 // // TODO should we update segment's size here too?
651 const tseg = &zld.load_commands.items[match.seg].Segment;650 // // How does it tie with incremental space allocs?
652 const tsect = &tseg.sections.items[match.sect];651 // const tseg = &zld.load_commands.items[match.seg].Segment;
653 const new_alignment = math.max(tsect.@"align", block.alignment);652 // const tsect = &tseg.sections.items[match.sect];
654 const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);653 // const new_alignment = math.max(tsect.@"align", block.alignment);
655 const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;654 // const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
656 tsect.size = new_size;655 // const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
657 tsect.@"align" = new_alignment;656 // tsect.size = new_size;
658657 // tsect.@"align" = new_alignment;
659 if (zld.blocks.getPtr(match)) |last| {658
660 last.*.next = block;659 // if (zld.blocks.getPtr(match)) |last| {
661 block.prev = last.*;660 // last.*.next = block;
662 last.* = block;661 // block.prev = last.*;
663 } else {662 // last.* = block;
664 try zld.blocks.putNoClobber(zld.allocator, match, block);663 // } else {
665 }664 // try zld.blocks.putNoClobber(zld.allocator, match, block);
666665 // }
667 try self.text_blocks.append(self.allocator, block);666
668 }667 // try self.text_blocks.append(self.allocator, block);
669668 // }
670 var parser = TextBlockParser{669
671 .allocator = self.allocator,670 // var parser = TextBlockParser{
672 .section = sect,671 // .allocator = self.allocator,
673 .code = code,672 // .section = sect,
674 .relocs = relocs,673 // .code = code,
675 .object = self,674 // .relocs = relocs,
676 .zld = zld,675 // .object = self,
677 .nlists = filtered_nlists,676 // .zld = zld,
678 .match = match,677 // .nlists = filtered_nlists,
679 };678 // .match = match,
680679 // };
681 while (try parser.next()) |block| {680
682 const sym = zld.locals.items[block.local_sym_index];681 // while (try parser.next()) |block| {
683 const reg = &sym.payload.regular;682 // const sym = zld.locals.items[block.local_sym_index];
684 if (reg.file) |file| {683 // const reg = &sym.payload.regular;
685 if (file != self) {684 // if (reg.file) |file| {
686 log.debug("deduping definition of {s} in {s}", .{ zld.getString(sym.strx), self.name.? });685 // if (file != self) {
687 block.deinit();686 // log.debug("deduping definition of {s} in {s}", .{ zld.getString(sym.strx), self.name.? });
688 self.allocator.destroy(block);687 // block.deinit();
689 continue;688 // self.allocator.destroy(block);
690 }689 // continue;
691 }690 // }
692691 // }
693 if (reg.address == sect.addr) {692
694 if (self.sections_as_symbols.get(sect_id)) |alias| {693 // if (reg.address == sect.addr) {
695 // Add alias.694 // if (self.sections_as_symbols.get(sect_id)) |alias| {
696 const local_sym_index = @intCast(u32, zld.locals.items.len);695 // // Add alias.
697 const reg_alias = &alias.payload.regular;696 // const local_sym_index = @intCast(u32, zld.locals.items.len);
698 reg_alias.segment_id = match.seg;697 // const reg_alias = &alias.payload.regular;
699 reg_alias.section_id = match.sect;698 // reg_alias.segment_id = match.seg;
700 reg_alias.local_sym_index = local_sym_index;699 // reg_alias.section_id = match.sect;
701 try block.aliases.append(local_sym_index);700 // reg_alias.local_sym_index = local_sym_index;
702 try zld.locals.append(zld.allocator, alias);701 // try block.aliases.append(local_sym_index);
703 }702 // try zld.locals.append(zld.allocator, alias);
704 }703 // }
705704 // }
706 // Update target section's metadata705
707 // TODO should we update segment's size here too?706 // // Update target section's metadata
708 // How does it tie with incremental space allocs?707 // // TODO should we update segment's size here too?
709 const tseg = &zld.load_commands.items[match.seg].Segment;708 // // How does it tie with incremental space allocs?
710 const tsect = &tseg.sections.items[match.sect];709 // const tseg = &zld.load_commands.items[match.seg].Segment;
711 const new_alignment = math.max(tsect.@"align", block.alignment);710 // const tsect = &tseg.sections.items[match.sect];
712 const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);711 // const new_alignment = math.max(tsect.@"align", block.alignment);
713 const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;712 // const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
714 tsect.size = new_size;713 // const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
715 tsect.@"align" = new_alignment;714 // tsect.size = new_size;
716715 // tsect.@"align" = new_alignment;
717 if (zld.blocks.getPtr(match)) |last| {716
718 last.*.next = block;717 // if (zld.blocks.getPtr(match)) |last| {
719 block.prev = last.*;718 // last.*.next = block;
720 last.* = block;719 // block.prev = last.*;
721 } else {720 // last.* = block;
722 try zld.blocks.putNoClobber(zld.allocator, match, block);721 // } else {
723 }722 // try zld.blocks.putNoClobber(zld.allocator, match, block);
724723 // }
725 try self.text_blocks.append(self.allocator, block);724
726 }725 // try self.text_blocks.append(self.allocator, block);
727726 // }
728 break :next;727
729 }728 // break :next;
729 // }
730730
731 // Since there is no symbol to refer to this block, we create731 // Since there is no symbol to refer to this block, we create
732 // a temp one, unless we already did that when working out the relocations732 // a temp one, unless we already did that when working out the relocations
733 // of other text blocks.733 // of other text blocks.
734 const symbol = self.sections_as_symbols.get(sect_id) orelse symbol: {734 const block_local_sym_index = @intCast(u32, zld.locals.items.len);
735 const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{735 const sym_name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
736 self.name.?,736 self.name.?,
737 segmentName(sect),737 segmentName(sect),
738 sectionName(sect),738 sectionName(sect),
739 });739 });
740 defer self.allocator.free(name);740 defer self.allocator.free(sym_name);
741 const symbol = try zld.allocator.create(Symbol);741 try zld.locals.append(zld.allocator, .{
742 symbol.* = .{742 .n_strx = try zld.makeString(sym_name),
743 .strx = try zld.makeString(name),743 .n_type = macho.N_SECT,
744 .payload = .{ .undef = .{} },744 .n_sect = zld.sectionId(match),
745 };745 .n_desc = 0,
746 try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol);746 .n_value = sect.addr,
747 break :symbol symbol;747 });
748 };748 const block_local = &zld.locals.items[block_local_sym_index];
749749 block_local.n_sect = zld.sectionId(match);
750 const local_sym_index = @intCast(u32, zld.locals.items.len);
751 symbol.payload = .{
752 .regular = .{
753 .linkage = .translation_unit,
754 .address = sect.addr,
755 .segment_id = match.seg,
756 .section_id = match.sect,
757 .file = self,
758 .local_sym_index = local_sym_index,
759 },
760 };
761 try zld.locals.append(zld.allocator, symbol);
762750
763 const block = try self.allocator.create(TextBlock);751 const block = try self.allocator.create(TextBlock);
764 errdefer self.allocator.destroy(block);752 errdefer self.allocator.destroy(block);
765753
766 block.* = TextBlock.init(self.allocator);754 block.* = TextBlock.init(self.allocator);
767 block.local_sym_index = local_sym_index;755 block.local_sym_index = block_local_sym_index;
768 block.code = try self.allocator.dupe(u8, code);756 block.code = try self.allocator.dupe(u8, code);
769 block.size = sect.size;757 block.size = sect.size;
770 block.alignment = sect.@"align";758 block.alignment = sect.@"align";
771759
772 if (relocs.len > 0) {760 try block.relocs.ensureTotalCapacity(relocs.len);
773 try self.parseRelocs(zld, relocs, block, 0);761 for (relocs) |rel| {
762 const out_rel: TextBlock.Relocation = outer: {
763 if (rel.r_extern == 0) {
764 const rel_sect_id = @intCast(u16, rel.r_symbolnum - 1);
765 const sect_sym_index = self.sections_as_symbols.get(rel_sect_id) orelse blk: {
766 const sect_sym_index = @intCast(u32, zld.locals.items.len);
767 const sect_sym_name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
768 self.name.?,
769 segmentName(sect),
770 sectionName(sect),
771 });
772 defer self.allocator.free(sect_sym_name);
773 try zld.locals.append(zld.allocator, .{
774 .n_strx = try zld.makeString(sect_sym_name),
775 .n_type = macho.N_SECT,
776 .n_sect = 0,
777 .n_desc = 0,
778 .n_value = 0,
779 });
780 try self.sections_as_symbols.putNoClobber(self.allocator, rel_sect_id, sect_sym_index);
781 break :blk sect_sym_index;
782 };
783 break :outer .{
784 .inner = rel,
785 .where = .local,
786 .where_index = sect_sym_index,
787 };
788 }
789
790 const rel_sym = self.symtab.items[rel.r_symbolnum];
791 const rel_sym_name = self.getString(rel_sym.n_strx);
792
793 if (Zld.symbolIsSect(rel_sym) and !Zld.symbolIsExt(rel_sym)) {
794 const where_index = self.symbol_mapping.get(rel.r_symbolnum) orelse unreachable;
795 break :outer .{
796 .inner = rel,
797 .where = .local,
798 .where_index = where_index,
799 };
800 }
801
802 const resolv = zld.symbol_resolver.get(rel_sym_name) orelse unreachable;
803 switch (resolv.where) {
804 .global => {
805 break :outer .{
806 .inner = rel,
807 .where = .local,
808 .where_index = resolv.local_sym_index,
809 };
810 },
811 .import => {
812 break :outer .{
813 .inner = rel,
814 .where = .import,
815 .where_index = resolv.where_index,
816 };
817 },
818 else => unreachable,
819 }
820 };
821 block.relocs.appendAssumeCapacity(out_rel);
774 }822 }
775823
776 if (zld.has_dices) {824 if (zld.has_dices) {
...@@ -791,44 +839,41 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -791,44 +839,41 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
791 // the filtered symbols and note which symbol is contained within so that839 // the filtered symbols and note which symbol is contained within so that
792 // we can properly allocate addresses down the line.840 // we can properly allocate addresses down the line.
793 // While we're at it, we need to update segment,section mapping of each symbol too.841 // While we're at it, we need to update segment,section mapping of each symbol too.
794 if (filtered_nlists.len > 0) {842 var contained = std.ArrayList(TextBlock.SymbolAtOffset).init(self.allocator);
795 var contained = std.ArrayList(TextBlock.SymbolAtOffset).init(self.allocator);843 defer contained.deinit();
796 defer contained.deinit();844 try contained.ensureTotalCapacity(filtered_nlists.len);
797 try contained.ensureTotalCapacity(filtered_nlists.len);845
798846 for (filtered_nlists) |nlist_with_index| {
799 for (filtered_nlists) |nlist_with_index| {847 const nlist = nlist_with_index.nlist;
800 const sym = self.symbols.items[nlist_with_index.index];848 const local_sym_index = self.symbol_mapping.get(nlist_with_index.index) orelse unreachable;
801 assert(sym.payload == .regular);849 const local = &zld.locals.items[local_sym_index];
802 const reg = &sym.payload.regular;850 local.n_sect = zld.sectionId(match);
803851
804 reg.segment_id = match.seg;852 const stab: ?TextBlock.Stab = if (self.debug_info) |di| blk: {
805 reg.section_id = match.sect;853 // TODO there has to be a better to handle this.
806854 for (di.inner.func_list.items) |func| {
807 const stab: ?TextBlock.Stab = if (self.debug_info) |di| blk: {855 if (func.pc_range) |range| {
808 // TODO there has to be a better to handle this.856 if (nlist.n_value >= range.start and nlist.n_value < range.end) {
809 for (di.inner.func_list.items) |func| {857 break :blk TextBlock.Stab{
810 if (func.pc_range) |range| {858 .function = range.end - range.start,
811 if (reg.address >= range.start and reg.address < range.end) {859 };
812 break :blk TextBlock.Stab{
813 .function = range.end - range.start,
814 };
815 }
816 }860 }
817 }861 }
818 if (zld.globals.contains(zld.getString(sym.strx))) break :blk .global;862 }
819 break :blk .static;863 // TODO
820 } else null;864 // if (zld.globals.contains(zld.getString(sym.strx))) break :blk .global;
821865 break :blk .static;
822 contained.appendAssumeCapacity(.{866 } else null;
823 .local_sym_index = reg.local_sym_index,
824 .offset = nlist_with_index.nlist.n_value - sect.addr,
825 .stab = stab,
826 });
827 }
828867
829 block.contained = contained.toOwnedSlice();868 contained.appendAssumeCapacity(.{
869 .local_sym_index = local_sym_index,
870 .offset = nlist.n_value - sect.addr,
871 .stab = stab,
872 });
830 }873 }
831874
875 block.contained = contained.toOwnedSlice();
876
832 // Update target section's metadata877 // Update target section's metadata
833 // TODO should we update segment's size here too?878 // TODO should we update segment's size here too?
834 // How does it tie with incremental space allocs?879 // How does it tie with incremental space allocs?
...@@ -853,26 +898,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {...@@ -853,26 +898,6 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
853 }898 }
854}899}
855900
856fn parseRelocs(
857 self: *Object,
858 zld: *Zld,
859 relocs: []const macho.relocation_info,
860 block: *TextBlock,
861 base_addr: u64,
862) !void {
863 var it = reloc.RelocIterator{
864 .buffer = relocs,
865 };
866 var parser = reloc.Parser{
867 .object = self,
868 .zld = zld,
869 .it = &it,
870 .block = block,
871 .base_addr = base_addr,
872 };
873 try parser.parse();
874}
875
876pub fn symbolFromReloc(self: *Object, zld: *Zld, rel: macho.relocation_info) !*Symbol {901pub fn symbolFromReloc(self: *Object, zld: *Zld, rel: macho.relocation_info) !*Symbol {
877 const symbol = blk: {902 const symbol = blk: {
878 if (rel.r_extern == 1) {903 if (rel.r_extern == 1) {
src/link/MachO/Symbol.zig deleted-285
...@@ -1,285 +0,0 @@
1const Symbol = @This();
2
3const std = @import("std");
4const assert = std.debug.assert;
5const commands = @import("commands.zig");
6const macho = std.macho;
7const mem = std.mem;
8
9const Allocator = mem.Allocator;
10const Dylib = @import("Dylib.zig");
11const Object = @import("Object.zig");
12const Zld = @import("Zld.zig");
13
14/// Offset into the string table.
15strx: u32,
16
17/// Index in GOT table for indirection.
18got_index: ?u32 = null,
19
20/// Index in stubs table for late binding.
21stubs_index: ?u32 = null,
22
23payload: union(enum) {
24 regular: Regular,
25 tentative: Tentative,
26 proxy: Proxy,
27 undef: Undefined,
28
29 pub fn format(self: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
30 return switch (self) {
31 .regular => |p| p.format(fmt, options, writer),
32 .tentative => |p| p.format(fmt, options, writer),
33 .proxy => |p| p.format(fmt, options, writer),
34 .undef => |p| p.format(fmt, options, writer),
35 };
36 }
37},
38
39pub const Regular = struct {
40 /// Linkage type.
41 linkage: Linkage,
42
43 /// Symbol address.
44 address: u64 = 0,
45
46 /// Segment ID
47 segment_id: u16 = 0,
48
49 /// Section ID
50 section_id: u16 = 0,
51
52 /// Whether the symbol is a weak ref.
53 weak_ref: bool = false,
54
55 /// Object file where to locate this symbol.
56 /// null means self-reference.
57 file: ?*Object = null,
58
59 local_sym_index: u32 = 0,
60
61 pub const Linkage = enum {
62 translation_unit,
63 linkage_unit,
64 global,
65 };
66
67 pub fn format(self: Regular, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
68 _ = fmt;
69 _ = options;
70 try std.fmt.format(writer, "Regular {{ ", .{});
71 try std.fmt.format(writer, ".linkage = {s}, ", .{self.linkage});
72 try std.fmt.format(writer, ".address = 0x{x}, ", .{self.address});
73 try std.fmt.format(writer, ".segment_id = {}, ", .{self.segment_id});
74 try std.fmt.format(writer, ".section_id = {}, ", .{self.section_id});
75 if (self.weak_ref) {
76 try std.fmt.format(writer, ".weak_ref, ", .{});
77 }
78 if (self.file) |file| {
79 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
80 }
81 try std.fmt.format(writer, ".local_sym_index = {}, ", .{self.local_sym_index});
82 try std.fmt.format(writer, "}}", .{});
83 }
84
85 pub fn sectionId(self: Regular, zld: *Zld) u8 {
86 // TODO there might be a more generic way of doing this.
87 var section: u8 = 0;
88 for (zld.load_commands.items) |cmd, cmd_id| {
89 if (cmd != .Segment) break;
90 if (cmd_id == self.segment_id) {
91 section += @intCast(u8, self.section_id) + 1;
92 break;
93 }
94 section += @intCast(u8, cmd.Segment.sections.items.len);
95 }
96 return section;
97 }
98};
99
100pub const Tentative = struct {
101 /// Symbol size.
102 size: u64,
103
104 /// Symbol alignment as power of two.
105 alignment: u16,
106
107 /// File where this symbol was referenced.
108 file: ?*Object = null,
109
110 pub fn format(self: Tentative, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
111 _ = fmt;
112 _ = options;
113 try std.fmt.format(writer, "Tentative {{ ", .{});
114 try std.fmt.format(writer, ".size = 0x{x}, ", .{self.size});
115 try std.fmt.format(writer, ".alignment = 0x{x}, ", .{self.alignment});
116 if (self.file) |file| {
117 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
118 }
119 try std.fmt.format(writer, "}}", .{});
120 }
121};
122
123pub const Proxy = struct {
124 /// Dylib where to locate this symbol.
125 /// null means self-reference.
126 file: ?*Dylib = null,
127
128 local_sym_index: u32 = 0,
129
130 pub fn dylibOrdinal(proxy: Proxy) u16 {
131 const dylib = proxy.file orelse return 0;
132 return dylib.ordinal.?;
133 }
134
135 pub fn format(self: Proxy, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
136 _ = fmt;
137 _ = options;
138 try std.fmt.format(writer, "Proxy {{ ", .{});
139 if (self.file) |file| {
140 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
141 }
142 try std.fmt.format(writer, ".local_sym_index = {d}, ", .{self.local_sym_index});
143 try std.fmt.format(writer, "}}", .{});
144 }
145};
146
147pub const Undefined = struct {
148 /// File where this symbol was referenced.
149 /// null means synthetic, e.g., dyld_stub_binder.
150 file: ?*Object = null,
151
152 pub fn format(self: Undefined, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
153 _ = fmt;
154 _ = options;
155 try std.fmt.format(writer, "Undefined {{ ", .{});
156 if (self.file) |file| {
157 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
158 }
159 try std.fmt.format(writer, "}}", .{});
160 }
161};
162
163pub fn format(self: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
164 _ = fmt;
165 _ = options;
166 try std.fmt.format(writer, "Symbol {{", .{});
167 try std.fmt.format(writer, ".strx = {d}, ", .{self.strx});
168 if (self.got_index) |got_index| {
169 try std.fmt.format(writer, ".got_index = {}, ", .{got_index});
170 }
171 if (self.stubs_index) |stubs_index| {
172 try std.fmt.format(writer, ".stubs_index = {}, ", .{stubs_index});
173 }
174 try std.fmt.format(writer, "{}, ", .{self.payload});
175 try std.fmt.format(writer, "}}", .{});
176}
177
178pub fn isTemp(symbol: Symbol, zld: *Zld) bool {
179 const sym_name = zld.getString(symbol.strx);
180 switch (symbol.payload) {
181 .regular => |regular| {
182 if (regular.linkage == .translation_unit) {
183 return mem.startsWith(u8, sym_name, "l") or mem.startsWith(u8, sym_name, "L");
184 }
185 },
186 else => {},
187 }
188 return false;
189}
190
191pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 {
192 const nlist = nlist: {
193 switch (symbol.payload) {
194 .regular => |regular| {
195 var nlist = macho.nlist_64{
196 .n_strx = symbol.strx,
197 .n_type = macho.N_SECT,
198 .n_sect = regular.sectionId(zld),
199 .n_desc = 0,
200 .n_value = regular.address,
201 };
202
203 if (regular.linkage != .translation_unit) {
204 nlist.n_type |= macho.N_EXT;
205 }
206 if (regular.linkage == .linkage_unit) {
207 nlist.n_type |= macho.N_PEXT;
208 nlist.n_desc |= macho.N_WEAK_DEF;
209 }
210
211 break :nlist nlist;
212 },
213 .tentative => {
214 // TODO
215 break :nlist macho.nlist_64{
216 .n_strx = symbol.strx,
217 .n_type = macho.N_UNDF,
218 .n_sect = 0,
219 .n_desc = 0,
220 .n_value = 0,
221 };
222 },
223 .proxy => |proxy| {
224 break :nlist macho.nlist_64{
225 .n_strx = symbol.strx,
226 .n_type = macho.N_UNDF | macho.N_EXT,
227 .n_sect = 0,
228 .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
229 .n_value = 0,
230 };
231 },
232 .undef => {
233 // TODO
234 break :nlist macho.nlist_64{
235 .n_strx = symbol.strx,
236 .n_type = macho.N_UNDF,
237 .n_sect = 0,
238 .n_desc = 0,
239 .n_value = 0,
240 };
241 },
242 }
243 };
244 return nlist;
245}
246
247pub fn isStab(sym: macho.nlist_64) bool {
248 return (macho.N_STAB & sym.n_type) != 0;
249}
250
251pub fn isPext(sym: macho.nlist_64) bool {
252 return (macho.N_PEXT & sym.n_type) != 0;
253}
254
255pub fn isExt(sym: macho.nlist_64) bool {
256 return (macho.N_EXT & sym.n_type) != 0;
257}
258
259pub fn isSect(sym: macho.nlist_64) bool {
260 const type_ = macho.N_TYPE & sym.n_type;
261 return type_ == macho.N_SECT;
262}
263
264pub fn isUndf(sym: macho.nlist_64) bool {
265 const type_ = macho.N_TYPE & sym.n_type;
266 return type_ == macho.N_UNDF;
267}
268
269pub fn isIndr(sym: macho.nlist_64) bool {
270 const type_ = macho.N_TYPE & sym.n_type;
271 return type_ == macho.N_INDR;
272}
273
274pub fn isAbs(sym: macho.nlist_64) bool {
275 const type_ = macho.N_TYPE & sym.n_type;
276 return type_ == macho.N_ABS;
277}
278
279pub fn isWeakDef(sym: macho.nlist_64) bool {
280 return (sym.n_desc & macho.N_WEAK_DEF) != 0;
281}
282
283pub fn isWeakRef(sym: macho.nlist_64) bool {
284 return (sym.n_desc & macho.N_WEAK_REF) != 0;
285}
src/link/MachO/TextBlock.zig+35-29
...@@ -5,10 +5,9 @@ const commands = @import("commands.zig");...@@ -5,10 +5,9 @@ const commands = @import("commands.zig");
5const log = std.log.scoped(.text_block);5const log = std.log.scoped(.text_block);
6const macho = std.macho;6const macho = std.macho;
7const mem = std.mem;7const mem = std.mem;
8const reloc = @import("reloc.zig");
98
10const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
11const Relocation = reloc.Relocation;10const Arch = std.Target.Cpu.Arch;
12const Zld = @import("Zld.zig");11const Zld = @import("Zld.zig");
1312
14allocator: *Allocator,13allocator: *Allocator,
...@@ -102,6 +101,15 @@ pub const Stab = union(enum) {...@@ -102,6 +101,15 @@ pub const Stab = union(enum) {
102 }101 }
103};102};
104103
104pub const Relocation = struct {
105 inner: macho.relocation_info,
106 where: enum {
107 local,
108 import,
109 },
110 where_index: u32,
111};
112
105pub fn init(allocator: *Allocator) TextBlock {113pub fn init(allocator: *Allocator) TextBlock {
106 return .{114 return .{
107 .allocator = allocator,115 .allocator = allocator,
...@@ -137,18 +145,10 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {...@@ -137,18 +145,10 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
137145
138 const source_addr = blk: {146 const source_addr = blk: {
139 const sym = zld.locals.items[self.local_sym_index];147 const sym = zld.locals.items[self.local_sym_index];
140 break :blk sym.payload.regular.address + rel.offset;148 break :blk sym.n_value + rel.offset;
141 };149 };
142 const target_addr = blk: {150 const target_addr = blk: {
143 const is_via_got = switch (rel.payload) {151 if (isGotIndirection(rel, zld.target.?.cpu.arch)) {
144 .pointer_to_got => true,
145 .page => |page| page.kind == .got,
146 .page_off => |page_off| page_off.kind == .got,
147 .load => |load| load.kind == .got,
148 else => false,
149 };
150
151 if (is_via_got) {
152 const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment;152 const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment;
153 const got = dc_seg.sections.items[zld.got_section_index.?];153 const got = dc_seg.sections.items[zld.got_section_index.?];
154 const got_index = rel.target.got_index orelse {154 const got_index = rel.target.got_index orelse {
...@@ -228,31 +228,18 @@ pub fn print_this(self: *const TextBlock, zld: *Zld) void {...@@ -228,31 +228,18 @@ pub fn print_this(self: *const TextBlock, zld: *Zld) void {
228 log.warn(" stab: {}", .{stab});228 log.warn(" stab: {}", .{stab});
229 }229 }
230 if (self.aliases.items.len > 0) {230 if (self.aliases.items.len > 0) {
231 log.warn(" aliases:", .{});231 log.warn(" aliases: {any}", .{self.aliases.items});
232 for (self.aliases.items) |index| {
233 log.warn(" {}: {}", .{ index, zld.locals.items[index] });
234 }
235 }232 }
236 if (self.references.count() > 0) {233 if (self.references.count() > 0) {
237 log.warn(" references:", .{});234 log.warn(" references: {any}", .{self.references.keys()});
238 for (self.references.keys()) |index| {
239 log.warn(" {}: {}", .{ index, zld.locals.items[index] });
240 }
241 }235 }
242 if (self.contained) |contained| {236 if (self.contained) |contained| {
243 log.warn(" contained symbols:", .{});237 log.warn(" contained symbols:", .{});
244 for (contained) |sym_at_off| {238 for (contained) |sym_at_off| {
245 if (sym_at_off.stab) |stab| {239 if (sym_at_off.stab) |stab| {
246 log.warn(" {}: {}, stab: {}\n", .{240 log.warn(" {}: {}, stab: {}", .{ sym_at_off.offset, sym_at_off.local_sym_index, stab });
247 sym_at_off.offset,
248 zld.locals.items[sym_at_off.local_sym_index],
249 stab,
250 });
251 } else {241 } else {
252 log.warn(" {}: {}\n", .{242 log.warn(" {}: {}", .{ sym_at_off.offset, sym_at_off.local_sym_index });
253 sym_at_off.offset,
254 zld.locals.items[sym_at_off.local_sym_index],
255 });
256 }243 }
257 }244 }
258 }245 }
...@@ -282,3 +269,22 @@ pub fn print(self: *const TextBlock, zld: *Zld) void {...@@ -282,3 +269,22 @@ pub fn print(self: *const TextBlock, zld: *Zld) void {
282 }269 }
283 self.print_this(zld);270 self.print_this(zld);
284}271}
272
273fn isGotIndirection(rel: macho.relocation_info, arch: Arch) bool {
274 return switch (arch) {
275 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, rel.r_type)) {
276 .ARM64_RELOC_POINTER_TO_GOT,
277 .ARM64_RELOC_GOT_LOAD_PAGE21,
278 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
279 => true,
280 else => false,
281 },
282 .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, rel.r_type)) {
283 .X86_64_RELOC_GOT,
284 .X86_64_RELOC_GOT_LOAD,
285 => true,
286 else => false,
287 },
288 else => unreachable,
289 };
290}
src/link/MachO/Zld.zig+26-48
...@@ -105,7 +105,6 @@ imports: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -105,7 +105,6 @@ imports: std.ArrayListUnmanaged(macho.nlist_64) = .{},
105undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},105undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
106tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{},106tentatives: std.ArrayListUnmanaged(macho.nlist_64) = .{},
107symbol_resolver: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},107symbol_resolver: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
108object_mapping: std.AutoHashMapUnmanaged(u16, []u32) = .{},
109108
110strtab: std.ArrayListUnmanaged(u8) = .{},109strtab: std.ArrayListUnmanaged(u8) = .{},
111110
...@@ -199,14 +198,6 @@ pub fn deinit(self: *Zld) void {...@@ -199,14 +198,6 @@ pub fn deinit(self: *Zld) void {
199 }198 }
200 self.symbol_resolver.deinit(self.allocator);199 self.symbol_resolver.deinit(self.allocator);
201200
202 {
203 var it = self.object_mapping.valueIterator();
204 while (it.next()) |value_ptr| {
205 self.allocator.free(value_ptr.*);
206 }
207 }
208 self.object_mapping.deinit(self.allocator);
209
210 self.strtab.deinit(self.allocator);201 self.strtab.deinit(self.allocator);
211202
212 // TODO dealloc all blocks203 // TODO dealloc all blocks
...@@ -251,33 +242,33 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -251,33 +242,33 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
251 try self.resolveSymbols();242 try self.resolveSymbols();
252243
253 log.warn("locals", .{});244 log.warn("locals", .{});
254 for (self.locals.items) |sym| {245 for (self.locals.items) |sym, id| {
255 log.warn(" | {s}: {}", .{ self.getString(sym.n_strx), sym });246 log.warn(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
256 }247 }
257248
258 log.warn("globals", .{});249 log.warn("globals", .{});
259 for (self.globals.items) |sym| {250 for (self.globals.items) |sym, id| {
260 log.warn(" | {s}: {}", .{ self.getString(sym.n_strx), sym });251 log.warn(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
261 }252 }
262253
263 log.warn("tentatives", .{});254 log.warn("tentatives", .{});
264 for (self.tentatives.items) |sym| {255 for (self.tentatives.items) |sym, id| {
265 log.warn(" | {s}: {}", .{ self.getString(sym.n_strx), sym });256 log.warn(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
266 }257 }
267258
268 log.warn("undefines", .{});259 log.warn("undefines", .{});
269 for (self.undefs.items) |sym| {260 for (self.undefs.items) |sym, id| {
270 log.warn(" | {s}: {}", .{ self.getString(sym.n_strx), sym });261 log.warn(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
271 }262 }
272263
273 log.warn("imports", .{});264 log.warn("imports", .{});
274 for (self.imports.items) |sym| {265 for (self.imports.items) |sym, id| {
275 log.warn(" | {s}: {}", .{ self.getString(sym.n_strx), sym });266 log.warn(" {d}: {s}, {}", .{ id, self.getString(sym.n_strx), sym });
276 }267 }
277268
278 log.warn("symbol resolver", .{});269 log.warn("symbol resolver", .{});
279 for (self.symbol_resolver.keys()) |key| {270 for (self.symbol_resolver.keys()) |key| {
280 log.warn(" | {s} => {}", .{ key, self.symbol_resolver.get(key).? });271 log.warn(" {s} => {}", .{ key, self.symbol_resolver.get(key).? });
281 }272 }
282273
283 log.warn("mappings", .{});274 log.warn("mappings", .{});
...@@ -285,7 +276,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -285,7 +276,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
285 const object_id = @intCast(u16, id);276 const object_id = @intCast(u16, id);
286 log.warn(" in object {s}", .{object.name.?});277 log.warn(" in object {s}", .{object.name.?});
287 for (object.symtab.items) |sym, sym_id| {278 for (object.symtab.items) |sym, sym_id| {
288 if (self.localSymIndex(object_id, @intCast(u32, sym_id))) |local_id| {279 if (object.symbol_mapping.get(@intCast(u32, sym_id))) |local_id| {
289 log.warn(" | {d} => {d}", .{ sym_id, local_id });280 log.warn(" | {d} => {d}", .{ sym_id, local_id });
290 } else {281 } else {
291 log.warn(" | {d} no local mapping for {s}", .{ sym_id, object.getString(sym.n_strx) });282 log.warn(" | {d} no local mapping for {s}", .{ sym_id, object.getString(sym.n_strx) });
...@@ -293,8 +284,19 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -293,8 +284,19 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
293 }284 }
294 }285 }
295286
287 try self.parseTextBlocks();
288
289 var it = self.blocks.iterator();
290 while (it.next()) |entry| {
291 const seg = self.load_commands.items[entry.key_ptr.seg].Segment;
292 const sect = seg.sections.items[entry.key_ptr.sect];
293
294 log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });
295 log.warn(" {}", .{sect});
296 entry.value_ptr.*.print(self);
297 }
298
296 return error.TODO;299 return error.TODO;
297 // try self.parseTextBlocks();
298 // try self.sortSections();300 // try self.sortSections();
299 // try self.addRpaths(args.rpaths);301 // try self.addRpaths(args.rpaths);
300 // try self.addDataInCodeLC();302 // try self.addDataInCodeLC();
...@@ -305,16 +307,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -305,16 +307,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
305 // self.allocateLinkeditSegment();307 // self.allocateLinkeditSegment();
306 // try self.allocateTextBlocks();308 // try self.allocateTextBlocks();
307309
308 // // var it = self.blocks.iterator();
309 // // while (it.next()) |entry| {
310 // // const seg = self.load_commands.items[entry.key_ptr.seg].Segment;
311 // // const sect = seg.sections.items[entry.key_ptr.sect];
312
313 // // log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) });
314 // // log.warn(" {}", .{sect});
315 // // entry.value_ptr.*.print(self);
316 // // }
317
318 // try self.flush();310 // try self.flush();
319}311}
320312
...@@ -1414,10 +1406,6 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {...@@ -1414,10 +1406,6 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
14141406
1415 log.warn("resolving symbols in '{s}'", .{object.name});1407 log.warn("resolving symbols in '{s}'", .{object.name});
14161408
1417 const mapping = try self.allocator.alloc(u32, object.symtab.items.len);
1418 mem.set(u32, mapping, 0);
1419 try self.object_mapping.putNoClobber(self.allocator, object_id, mapping);
1420
1421 for (object.symtab.items) |sym, id| {1409 for (object.symtab.items) |sym, id| {
1422 const sym_id = @intCast(u32, id);1410 const sym_id = @intCast(u32, id);
1423 const sym_name = object.getString(sym.n_strx);1411 const sym_name = object.getString(sym.n_strx);
...@@ -1464,7 +1452,7 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {...@@ -1464,7 +1452,7 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
1464 .n_desc = 0,1452 .n_desc = 0,
1465 .n_value = sym.n_value,1453 .n_value = sym.n_value,
1466 });1454 });
1467 mapping[sym_id] = local_sym_index;1455 try object.symbol_mapping.putNoClobber(self.allocator, sym_id, local_sym_index);
14681456
1469 // If the symbol's scope is not local aka translation unit, then we need work out1457 // If the symbol's scope is not local aka translation unit, then we need work out
1470 // if we should save the symbol as a global, or potentially flag the error.1458 // if we should save the symbol as a global, or potentially flag the error.
...@@ -2987,15 +2975,6 @@ pub fn getString(self: *Zld, off: u32) []const u8 {...@@ -2987,15 +2975,6 @@ pub fn getString(self: *Zld, off: u32) []const u8 {
2987 return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + off));2975 return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + off));
2988}2976}
29892977
2990fn localSymIndex(self: Zld, object_id: u16, orig_id: u32) ?u32 {
2991 const mapping = self.object_mapping.get(object_id) orelse return null;
2992 const local_sym_index = mapping[orig_id];
2993 if (local_sym_index == 0) {
2994 return null;
2995 }
2996 return local_sym_index;
2997}
2998
2999pub fn symbolIsStab(sym: macho.nlist_64) bool {2978pub fn symbolIsStab(sym: macho.nlist_64) bool {
3000 return (macho.N_STAB & sym.n_type) != 0;2979 return (macho.N_STAB & sym.n_type) != 0;
3001}2980}
...@@ -3045,10 +3024,9 @@ pub fn symbolIsNull(sym: macho.nlist_64) bool {...@@ -3045,10 +3024,9 @@ pub fn symbolIsNull(sym: macho.nlist_64) bool {
3045 return sym.n_value == 0 and sym.n_desc == 0 and sym.n_type == 0 and sym.n_strx == 0 and sym.n_sect == 0;3024 return sym.n_value == 0 and sym.n_desc == 0 and sym.n_type == 0 and sym.n_strx == 0 and sym.n_sect == 0;
3046}3025}
30473026
3048pub fn symbolIsTemp(self: Zld, sym: macho.nlist_64) bool {3027pub fn symbolIsTemp(sym: macho.nlist_64, sym_name: []const u8) bool {
3049 if (!symbolIsSect(sym)) return false;3028 if (!symbolIsSect(sym)) return false;
3050 if (symbolIsExt(sym)) return false;3029 if (symbolIsExt(sym)) return false;
3051 const sym_name = self.getString(sym.n_strx);
3052 return mem.startsWith(u8, sym_name, "l") or mem.startsWith(u8, sym_name, "L");3030 return mem.startsWith(u8, sym_name, "l") or mem.startsWith(u8, sym_name, "L");
3053}3031}
30543032