| ... | ... | @@ -308,7 +308,7 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void { |
| 308 | 308 | } else nlists.len; |
| 309 | 309 | |
| 310 | 310 | if (nlist_start == nlist_end or nlists[nlist_start].nlist.n_value > sect.addr) { |
| 311 | | const name = try std.fmt.allocPrintZ(allocator, "{s}${s}", .{ sect.segName(), sect.sectName() }); |
| 311 | const name = try std.fmt.allocPrintZ(allocator, "{s}${s}$begin", .{ sect.segName(), sect.sectName() }); |
| 312 | 312 | defer allocator.free(name); |
| 313 | 313 | const size = if (nlist_start == nlist_end) sect.size else nlists[nlist_start].nlist.n_value - sect.addr; |
| 314 | 314 | const atom_index = try self.addAtom(allocator, .{ |
| ... | ... | @@ -359,6 +359,25 @@ fn initSubsections(self: *Object, allocator: Allocator, nlists: anytype) !void { |
| 359 | 359 | self.symtab.items(.size)[nlists[i].idx] = size; |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | |
| 363 | // Some compilers such as Go reference the end of a section (addr + size) |
| 364 | // which cannot be contained in any non-zero atom (since then this atom |
| 365 | // would exceed section boundaries). In order to facilitate this behaviour, |
| 366 | // we create a dummy zero-sized atom at section end (addr + size). |
| 367 | const name = try std.fmt.allocPrintZ(allocator, "{s}${s}$end", .{ sect.segName(), sect.sectName() }); |
| 368 | defer allocator.free(name); |
| 369 | const atom_index = try self.addAtom(allocator, .{ |
| 370 | .name = try self.addString(allocator, name), |
| 371 | .n_sect = @intCast(n_sect), |
| 372 | .off = sect.size, |
| 373 | .size = 0, |
| 374 | .alignment = sect.@"align", |
| 375 | }); |
| 376 | try self.atoms_indexes.append(allocator, atom_index); |
| 377 | try subsections.append(allocator, .{ |
| 378 | .atom = atom_index, |
| 379 | .off = sect.size, |
| 380 | }); |
| 362 | 381 | } |
| 363 | 382 | } |
| 364 | 383 | |
| ... | ... | @@ -743,7 +762,7 @@ pub fn findAtom(self: Object, addr: u64) ?Atom.Index { |
| 743 | 762 | const slice = self.sections.slice(); |
| 744 | 763 | for (slice.items(.header), slice.items(.subsections), 0..) |sect, subs, n_sect| { |
| 745 | 764 | if (subs.items.len == 0) continue; |
| 746 | | if (sect.addr == addr) return subs.items[0].atom; |
| 765 | if (addr == sect.addr) return subs.items[0].atom; |
| 747 | 766 | if (sect.addr < addr and addr < sect.addr + sect.size) { |
| 748 | 767 | return self.findAtomInSection(addr, @intCast(n_sect)); |
| 749 | 768 | } |
| ... | ... | @@ -794,7 +813,19 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void { |
| 794 | 813 | defer tracy.end(); |
| 795 | 814 | for (self.symtab.items(.nlist), self.symtab.items(.atom)) |nlist, *atom| { |
| 796 | 815 | if (!nlist.stab() and nlist.sect()) { |
| 797 | | if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| { |
| 816 | const sect = self.sections.items(.header)[nlist.n_sect - 1]; |
| 817 | const subs = self.sections.items(.subsections)[nlist.n_sect - 1].items; |
| 818 | if (nlist.n_value == sect.addr) { |
| 819 | // If the nlist address is the start of the section, return the first atom |
| 820 | // since it is guaranteed to always start at section's start address. |
| 821 | atom.* = subs[0].atom; |
| 822 | } else if (nlist.n_value == sect.addr + sect.size) { |
| 823 | // If the nlist address matches section's boundary (address + size), |
| 824 | // return the last atom since it is guaranteed to always point |
| 825 | // at the section's end boundary. |
| 826 | atom.* = subs[subs.len - 1].atom; |
| 827 | } else if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| { |
| 828 | // In all other cases, do a binary search to find a matching atom for the symbol. |
| 798 | 829 | atom.* = atom_index; |
| 799 | 830 | } else { |
| 800 | 831 | try macho_file.reportParseError2(self.index, "symbol {s} not attached to any (sub)section", .{ |