authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-05 16:31:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log7b4063d55899b0e35711c848f7b19de6f928282b
tree0e941076bd3d8f9f155f66f4b808682b973fb7ce
parent5649242025cd885a6a2f0607d96f54b1926b0a5a

zld: convert section in linked list of TextBlocks


3 files changed, 266 insertions(+), 247 deletions(-)

src/link/MachO/Object.zig+182-212
...@@ -28,7 +28,6 @@ name: ?[]const u8 = null,...@@ -28,7 +28,6 @@ name: ?[]const u8 = null,
28mtime: ?u64 = null,28mtime: ?u64 = null,
2929
30load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},30load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
31sections: std.ArrayListUnmanaged(Section) = .{},
3231
33segment_cmd_index: ?u16 = null,32segment_cmd_index: ?u16 = null,
34symtab_cmd_index: ?u16 = null,33symtab_cmd_index: ?u16 = null,
...@@ -49,32 +48,10 @@ dwarf_debug_ranges_index: ?u16 = null,...@@ -49,32 +48,10 @@ dwarf_debug_ranges_index: ?u16 = null,
49symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},48symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
50strtab: std.ArrayListUnmanaged(u8) = .{},49strtab: std.ArrayListUnmanaged(u8) = .{},
5150
52symbols: std.ArrayListUnmanaged(*Symbol) = .{},
53stabs: std.ArrayListUnmanaged(*Symbol) = .{},
54initializers: std.ArrayListUnmanaged(u32) = .{},51initializers: std.ArrayListUnmanaged(u32) = .{},
55data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},52data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
5653
57pub const Section = struct {54symbols: std.ArrayListUnmanaged(*Symbol) = .{},
58 inner: macho.section_64,
59 code: []u8,
60 relocs: ?[]*Relocation,
61 target_map: ?struct {
62 segment_id: u16,
63 section_id: u16,
64 offset: u32,
65 } = null,
66
67 pub fn deinit(self: *Section, allocator: *Allocator) void {
68 allocator.free(self.code);
69
70 if (self.relocs) |relocs| {
71 for (relocs) |rel| {
72 allocator.destroy(rel);
73 }
74 allocator.free(relocs);
75 }
76 }
77};
7855
79const DebugInfo = struct {56const DebugInfo = struct {
80 inner: dwarf.DwarfInfo,57 inner: dwarf.DwarfInfo,
...@@ -177,19 +154,11 @@ pub fn deinit(self: *Object) void {...@@ -177,19 +154,11 @@ pub fn deinit(self: *Object) void {
177 lc.deinit(self.allocator);154 lc.deinit(self.allocator);
178 }155 }
179 self.load_commands.deinit(self.allocator);156 self.load_commands.deinit(self.allocator);
180
181 for (self.sections.items) |*sect| {
182 sect.deinit(self.allocator);
183 }
184 self.sections.deinit(self.allocator);
185
186 self.symbols.deinit(self.allocator);
187 self.stabs.deinit(self.allocator);
188
189 self.data_in_code_entries.deinit(self.allocator);157 self.data_in_code_entries.deinit(self.allocator);
190 self.initializers.deinit(self.allocator);158 self.initializers.deinit(self.allocator);
191 self.symtab.deinit(self.allocator);159 self.symtab.deinit(self.allocator);
192 self.strtab.deinit(self.allocator);160 self.strtab.deinit(self.allocator);
161 self.symbols.deinit(self.allocator);
193162
194 if (self.name) |n| {163 if (self.name) |n| {
195 self.allocator.free(n);164 self.allocator.free(n);
...@@ -231,10 +200,8 @@ pub fn parse(self: *Object) !void {...@@ -231,10 +200,8 @@ pub fn parse(self: *Object) !void {
231 self.header = header;200 self.header = header;
232201
233 try self.readLoadCommands(reader);202 try self.readLoadCommands(reader);
234 try self.parseSections();
235 try self.parseSymtab();203 try self.parseSymtab();
236 try self.parseDataInCode();204 try self.parseDataInCode();
237 try self.parseInitializers();
238}205}
239206
240pub fn readLoadCommands(self: *Object, reader: anytype) !void {207pub fn readLoadCommands(self: *Object, reader: anytype) !void {
...@@ -305,250 +272,253 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -305,250 +272,253 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
305 }272 }
306}273}
307274
308pub fn parseSections(self: *Object) !void {275const NlistWithIndex = struct {
309 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;276 nlist: macho.nlist_64,
310277 index: u32,
311 log.debug("parsing sections in {s}", .{self.name.?});
312
313 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
314278
315 for (seg.sections.items) |sect| {279 pub fn cmp(_: void, lhs: @This(), rhs: @This()) bool {
316 log.debug("parsing section '{s},{s}'", .{ segmentName(sect), sectionName(sect) });280 return lhs.nlist.n_value < rhs.nlist.n_value;
317 // Read sections' code281 }
318 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
319 _ = try self.file.?.preadAll(code, sect.offset);
320
321 var section = Section{
322 .inner = sect,
323 .code = code,
324 .relocs = null,
325 };
326282
327 // Parse relocations283 fn filterNlistsInSection(symbols: []@This(), sect_id: u8) []@This() {
328 if (sect.nreloc > 0) {284 var start: usize = 0;
329 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);285 var end: usize = symbols.len;
330 defer self.allocator.free(raw_relocs);
331286
332 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);287 while (true) {
288 var change = false;
289 if (symbols[start].nlist.n_sect != sect_id) {
290 start += 1;
291 change = true;
292 }
293 if (symbols[end - 1].nlist.n_sect != sect_id) {
294 end -= 1;
295 change = true;
296 }
333297
334 section.relocs = try reloc.parse(298 if (start == end) break;
335 self.allocator,299 if (!change) break;
336 self.arch.?,
337 section.code,
338 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
339 );
340 }300 }
341301
342 self.sections.appendAssumeCapacity(section);302 return symbols[start..end];
343 }303 }
344}304};
345
346pub fn parseTextBlocks(self: *Object, zld: *Zld) !*TextBlock {
347 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
348305
349 log.warn("analysing {s}", .{self.name.?});306fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {
307 if (relocs.len == 0) return relocs;
350308
351 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;309 var start_id: usize = 0;
310 var end_id: usize = relocs.len;
352311
353 const SymWithIndex = struct {312 while (true) {
354 nlist: macho.nlist_64,313 var change = false;
355 index: u32,314 if (relocs[start_id].r_address > end) {
356315 start_id += 1;
357 pub fn cmp(_: void, lhs: @This(), rhs: @This()) bool {316 change = true;
358 return lhs.nlist.n_value < rhs.nlist.n_value;
359 }317 }
360318 if (relocs[end_id - 1].r_address < start) {
361 fn filterSymsInSection(symbols: []@This(), sect_id: u8) []@This() {319 end_id -= 1;
362 var start: usize = 0;320 change = true;
363 var end: usize = symbols.len;
364
365 while (true) {
366 var change = false;
367 if (symbols[start].nlist.n_sect != sect_id) {
368 start += 1;
369 change = true;
370 }
371 if (symbols[end - 1].nlist.n_sect != sect_id) {
372 end -= 1;
373 change = true;
374 }
375
376 if (start == end) break;
377 if (!change) break;
378 }
379
380 return symbols[start..end];
381 }321 }
382322
383 fn filterRelocs(relocs: []macho.relocation_info, start: u64, end: u64) []macho.relocation_info {323 if (start_id == end_id) break;
384 if (relocs.len == 0) return relocs;324 if (!change) break;
325 }
385326
386 var start_id: usize = 0;327 return relocs[start_id..end_id];
387 var end_id: usize = relocs.len;328}
388329
389 while (true) {330const SeniorityContext = struct {
390 var change = false;331 zld: *Zld,
391 if (relocs[start_id].r_address > end) {332};
392 start_id += 1;333fn cmpSymBySeniority(context: SeniorityContext, lhs: u32, rhs: u32) bool {
393 change = true;334 const lreg = context.zld.locals.items[lhs].payload.regular;
394 }335 const rreg = context.zld.locals.items[rhs].payload.regular;
395 if (relocs[end_id - 1].r_address < start) {336
396 end_id -= 1;337 return switch (rreg.linkage) {
397 change = true;338 .global => true,
398 }339 .linkage_unit => lreg.linkage == .translation_unit,
340 else => false,
341 };
342}
399343
400 if (start_id == end_id) break;344pub fn parseTextBlocks(self: *Object, zld: *Zld) !?*TextBlock {
401 if (!change) break;345 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
402 }
403346
404 return relocs[start_id..end_id];347 log.warn("analysing {s}", .{self.name.?});
405 }
406 };
407348
349 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
350 // We only care about defined symbols, so filter every other out.
408 const nlists = self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym];351 const nlists = self.symtab.items[dysymtab.ilocalsym..dysymtab.iundefsym];
409352
410 var sorted_syms = std.ArrayList(SymWithIndex).init(self.allocator);353 var sorted_nlists = std.ArrayList(NlistWithIndex).init(self.allocator);
411 defer sorted_syms.deinit();354 defer sorted_nlists.deinit();
412 try sorted_syms.ensureTotalCapacity(nlists.len);355 try sorted_nlists.ensureTotalCapacity(nlists.len);
413356
414 for (nlists) |nlist, index| {357 for (nlists) |nlist, index| {
415 sorted_syms.appendAssumeCapacity(.{358 sorted_nlists.appendAssumeCapacity(.{
416 .nlist = nlist,359 .nlist = nlist,
417 .index = @intCast(u32, index + dysymtab.ilocalsym),360 .index = @intCast(u32, index + dysymtab.ilocalsym),
418 });361 });
419 }362 }
420363
421 std.sort.sort(SymWithIndex, sorted_syms.items, {}, SymWithIndex.cmp);364 std.sort.sort(NlistWithIndex, sorted_nlists.items, {}, NlistWithIndex.cmp);
365
366 var last_block: ?*TextBlock = null;
422367
423 for (seg.sections.items) |sect, sect_id| {368 for (seg.sections.items) |sect, sect_id| {
424 log.warn("section {s},{s}", .{ segmentName(sect), sectionName(sect) });369 log.warn("putting section '{s},{s}' as a TextBlock", .{
370 segmentName(sect),
371 sectionName(sect),
372 });
425373
374 // Get matching segment/section in the final artifact.
426 const match = (try zld.getMatchingSection(sect)) orelse {375 const match = (try zld.getMatchingSection(sect)) orelse {
427 log.warn("unhandled section", .{});376 log.warn("unhandled section", .{});
428 continue;377 continue;
429 };378 };
430379
431 // Read code380 // Read section's code
432 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));381 var code = try self.allocator.alloc(u8, @intCast(usize, sect.size));
433 defer self.allocator.free(code);382 defer self.allocator.free(code);
434 _ = try self.file.?.preadAll(code, sect.offset);383 _ = try self.file.?.preadAll(code, sect.offset);
435384
436 // Read and parse relocs385 // Is there any padding between symbols within the section?
437 const raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);386 const is_padded = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;
438 defer self.allocator.free(raw_relocs);
439 _ = try self.file.?.preadAll(raw_relocs, sect.reloff);
440 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
441387
388 // Section alignment will be the assumed alignment per symbol.
442 const alignment = sect.@"align";389 const alignment = sect.@"align";
443390
444 if (self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) {391 next: {
445 const syms = SymWithIndex.filterSymsInSection(sorted_syms.items, @intCast(u8, sect_id + 1));392 if (is_padded) blocks: {
446393 const filtered_nlists = NlistWithIndex.filterNlistsInSection(
447 if (syms.len == 0) {394 sorted_nlists.items,
448 // One large text block referenced by section offsets only395 @intCast(u8, sect_id + 1),
449 log.warn("TextBlock", .{});396 );
450 log.warn(" | referenced by section offsets", .{});397
451 log.warn(" | start_addr = {}", .{sect.addr});398 if (filtered_nlists.len == 0) break :blocks;
452 log.warn(" | end_addr = {}", .{sect.size});
453 log.warn(" | size = {}", .{sect.size});
454 log.warn(" | alignment = 0x{x}", .{alignment});
455 log.warn(" | segment_id = {}", .{match.seg});
456 log.warn(" | section_id = {}", .{match.sect});
457 log.warn(" | relocs: {any}", .{relocs});
458 }
459399
460 var indices = std.ArrayList(u32).init(self.allocator);400 var nlist_indices = std.ArrayList(u32).init(self.allocator);
461 defer indices.deinit();401 defer nlist_indices.deinit();
462402
463 var i: u32 = 0;403 var i: u32 = 0;
464 while (i < syms.len) : (i += 1) {404 while (i < filtered_nlists.len) : (i += 1) {
465 const curr = syms[i];405 const curr = filtered_nlists[i];
466 try indices.append(i);406 try nlist_indices.append(curr.index);
467407
468 const next: ?SymWithIndex = if (i + 1 < syms.len)408 const next: ?NlistWithIndex = if (i + 1 < filtered_nlists.len)
469 syms[i + 1]409 filtered_nlists[i + 1]
470 else410 else
471 null;411 null;
472412
473 if (next) |n| {413 if (next) |n| {
474 if (curr.nlist.n_value == n.nlist.n_value) {414 if (curr.nlist.n_value == n.nlist.n_value) {
475 continue;415 continue;
416 }
476 }417 }
477 }
478418
479 const start_addr = curr.nlist.n_value - sect.addr;419 // Bubble-up senior symbol as the main link to the text block.
480 const end_addr = if (next) |n| n.nlist.n_value - sect.addr else sect.size;420 for (nlist_indices.items) |*index| {
421 const sym = self.symbols.items[index.*];
422 if (sym.payload != .regular) {
423 log.err("expected a regular symbol, found {s}", .{sym.payload});
424 log.err(" when remapping {s}", .{sym.name});
425 return error.SymbolIsNotRegular;
426 }
427 assert(sym.payload.regular.local_sym_index != 0); // This means the symbol has not been properly resolved.
428 index.* = sym.payload.regular.local_sym_index;
429 }
481430
482 const tb_code = code[start_addr..end_addr];431 std.sort.sort(u32, nlist_indices.items, SeniorityContext{ .zld = zld }, cmpSymBySeniority);
483 const size = tb_code.len;
484432
485 log.warn("TextBlock", .{});433 const local_sym_index = nlist_indices.pop();
486 for (indices.items) |id| {434 const sym = zld.locals.items[local_sym_index];
487 const sym = self.symbols.items[syms[id].index];435 if (sym.payload.regular.file) |file| {
488 log.warn(" | symbol = {s}", .{sym.name});436 if (file != self) {
489 }437 log.warn("deduping definition of {s} in {s}", .{ sym.name, self.name.? });
490 log.warn(" | start_addr = {}", .{start_addr});438 continue;
491 log.warn(" | end_addr = {}", .{end_addr});439 }
492 log.warn(" | size = {}", .{size});440 }
493 log.warn(" | alignment = 0x{x}", .{alignment});
494 log.warn(" | segment_id = {}", .{match.seg});
495 log.warn(" | section_id = {}", .{match.sect});
496 log.warn(" | relocs: {any}", .{SymWithIndex.filterRelocs(relocs, start_addr, end_addr)});
497
498 indices.clearRetainingCapacity();
499 }
500 } else {
501 return error.TODOOneLargeTextBlock;
502 }
503 }
504}
505441
506const SectionAsTextBlocksArgs = struct {442 const start_addr = curr.nlist.n_value - sect.addr;
507 sect: macho.section_64,443 const end_addr = if (next) |n| n.nlist.n_value - sect.addr else sect.size;
508 code: []u8,444
509 subsections_via_symbols: bool = false,445 const tb_code = code[start_addr..end_addr];
510 relocs: ?[]macho.relocation_info = null,446 const size = tb_code.len;
511 segment_id: u16 = 0,447
512 section_id: u16 = 0,448 const block = try self.allocator.create(TextBlock);
513};449 errdefer self.allocator.destroy(block);
450
451 block.* = .{
452 .local_sym_index = local_sym_index,
453 .aliases = std.ArrayList(u32).init(self.allocator),
454 .references = std.ArrayList(u32).init(self.allocator),
455 .code = tb_code,
456 .relocs = std.ArrayList(*Relocation).init(self.allocator),
457 .size = size,
458 .alignment = alignment,
459 .segment_id = match.seg,
460 .section_id = match.sect,
461 };
462 try block.aliases.appendSlice(nlist_indices.items);
463
464 // TODO parse relocs
465
466 if (last_block) |last| {
467 last.next = block;
468 block.prev = last;
469 }
470 last_block = block;
514471
515fn sectionAsTextBlocks(self: *Object, args: SectionAsTextBlocksArgs) !*TextBlock {472 nlist_indices.clearRetainingCapacity();
516 const sect = args.sect;473 }
517474
518 log.warn("putting section '{s},{s}' as a TextBlock", .{ segmentName(sect), sectionName(sect) });475 break :next;
476 }
519477
520 // Section alignment will be the assumed alignment per symbol.478 // Since there is no symbol to refer to this block, we create
521 const alignment = sect.@"align";479 // a temp one.
480 const name = try std.fmt.allocPrint(self.allocator, "l_{s}_{s}_{s}", .{
481 self.name.?,
482 segmentName(sect),
483 sectionName(sect),
484 });
485 defer self.allocator.free(name);
486 const symbol = try Symbol.new(self.allocator, name);
487 symbol.payload = .{
488 .regular = .{
489 .linkage = .translation_unit,
490 .file = self,
491 },
492 };
493 const local_sym_index = @intCast(u32, zld.locals.items.len);
494 try zld.locals.append(zld.allocator, symbol);
522495
523 const first_block: *TextBlock = blk: {
524 if (args.subsections_via_symbols) {
525 return error.TODO;
526 } else {
527 const block = try self.allocator.create(TextBlock);496 const block = try self.allocator.create(TextBlock);
528 errdefer self.allocator.destroy(block);497 errdefer self.allocator.destroy(block);
529498
530 block.* = .{499 block.* = .{
531 .ref = .{500 .local_sym_index = local_sym_index,
532 .section = undefined, // Will be populated when we allocated final sections.501 .aliases = std.ArrayList(u32).init(self.allocator),
533 },502 .references = std.ArrayList(u32).init(self.allocator),
534 .code = args.code,503 .code = code,
535 .relocs = null,504 .relocs = std.ArrayList(*Relocation).init(self.allocator),
536 .size = sect.size,505 .size = sect.size,
537 .alignment = alignment,506 .alignment = alignment,
538 .segment_id = args.segment_id,507 .segment_id = match.seg,
539 .section_id = args.section_id,508 .section_id = match.sect,
540 };509 };
541510
542 // TODO parse relocs511 // TODO parse relocs
543 if (args.relocs) |relocs| {
544 block.relocs = try reloc.parse(self.allocator, self.arch.?, args.code, relocs, symbols);
545 }
546512
547 break :blk block;513 if (last_block) |last| {
514 last.next = block;
515 block.prev = last;
516 }
517 last_block = block;
548 }518 }
549 };519 }
550520
551 return first_block;521 return last_block;
552}522}
553523
554pub fn parseInitializers(self: *Object) !void {524pub fn parseInitializers(self: *Object) !void {
src/link/MachO/Symbol.zig+8-3
...@@ -40,10 +40,13 @@ pub const Regular = struct {...@@ -40,10 +40,13 @@ pub const Regular = struct {
40 linkage: Linkage,40 linkage: Linkage,
4141
42 /// Symbol address.42 /// Symbol address.
43 address: u64,43 address: u64 = 0,
4444
45 /// Section ID where the symbol resides.45 /// Segment ID
46 section: u8,46 segment_id: u16 = 0,
47
48 /// Section ID
49 section: u16 = 0,
4750
48 /// Whether the symbol is a weak ref.51 /// Whether the symbol is a weak ref.
49 weak_ref: bool = false,52 weak_ref: bool = false,
...@@ -52,6 +55,8 @@ pub const Regular = struct {...@@ -52,6 +55,8 @@ pub const Regular = struct {
52 /// null means self-reference.55 /// null means self-reference.
53 file: ?*Object = null,56 file: ?*Object = null,
5457
58 local_sym_index: u32 = 0,
59
55 pub const Linkage = enum {60 pub const Linkage = enum {
56 translation_unit,61 translation_unit,
57 linkage_unit,62 linkage_unit,
src/link/MachO/Zld.zig+76-32
...@@ -104,6 +104,7 @@ objc_classrefs_section_index: ?u16 = null,...@@ -104,6 +104,7 @@ objc_classrefs_section_index: ?u16 = null,
104objc_data_section_index: ?u16 = null,104objc_data_section_index: ?u16 = null,
105105
106locals: std.ArrayListUnmanaged(*Symbol) = .{},106locals: std.ArrayListUnmanaged(*Symbol) = .{},
107imports: std.ArrayListUnmanaged(*Symbol) = .{},
107globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},108globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
108109
109/// Offset into __DATA,__common section.110/// Offset into __DATA,__common section.
...@@ -118,6 +119,8 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},...@@ -118,6 +119,8 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
118119
119stub_helper_stubs_start_off: ?u64 = null,120stub_helper_stubs_start_off: ?u64 = null,
120121
122last_text_block: ?*TextBlock = null,
123
121pub const Output = struct {124pub const Output = struct {
122 tag: enum { exe, dylib },125 tag: enum { exe, dylib },
123 path: []const u8,126 path: []const u8,
...@@ -135,12 +138,11 @@ const TlvOffset = struct {...@@ -135,12 +138,11 @@ const TlvOffset = struct {
135};138};
136139
137pub const TextBlock = struct {140pub const TextBlock = struct {
138 allocator: *Allocator,
139 local_sym_index: u32,141 local_sym_index: u32,
140 aliases: std.ArrayList(u32),142 aliases: std.ArrayList(u32),
141 references: std.ArrayList(u32),143 references: std.ArrayList(u32),
142 code: []u8,144 code: []u8,
143 relocs: ?std.ArrayList(*Relocation) = null,145 relocs: std.ArrayList(*Relocation),
144 size: u64,146 size: u64,
145 alignment: u32,147 alignment: u32,
146 segment_id: u16,148 segment_id: u16,
...@@ -151,14 +153,33 @@ pub const TextBlock = struct {...@@ -151,14 +153,33 @@ pub const TextBlock = struct {
151 pub fn deinit(block: *TextBlock, allocator: *Allocator) void {153 pub fn deinit(block: *TextBlock, allocator: *Allocator) void {
152 block.aliases.deinit();154 block.aliases.deinit();
153 block.references.deinit();155 block.references.deinit();
154 if (block.relocs) |relocs| {156 for (block.relocs.items) |reloc| {
155 for (relocs.items) |reloc| {157 allocator.destroy(reloc);
156 allocator.destroy(reloc);
157 }
158 relocs.deinit();
159 }158 }
159 block.relocs.deinit();
160 allocator.free(code);160 allocator.free(code);
161 }161 }
162
163 fn print(self: *const TextBlock, zld: *Zld) void {
164 if (self.prev) |prev| {
165 prev.print(zld);
166 }
167
168 log.warn("TextBlock", .{});
169 log.warn(" | {}: '{s}'", .{ self.local_sym_index, zld.locals.items[self.local_sym_index].name });
170 log.warn(" | Aliases:", .{});
171 for (self.aliases.items) |index| {
172 log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name });
173 }
174 log.warn(" | References:", .{});
175 for (self.references.items) |index| {
176 log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name });
177 }
178 log.warn(" | size = {}", .{self.size});
179 log.warn(" | align = {}", .{self.alignment});
180 log.warn(" | segment_id = {}", .{self.segment_id});
181 log.warn(" | section_id = {}", .{self.section_id});
182 }
162};183};
163184
164/// Default path to dyld185/// Default path to dyld
...@@ -200,11 +221,13 @@ pub fn deinit(self: *Zld) void {...@@ -200,11 +221,13 @@ pub fn deinit(self: *Zld) void {
200 }221 }
201 self.dylibs.deinit(self.allocator);222 self.dylibs.deinit(self.allocator);
202223
203 for (self.globals.values()) |sym| {224 self.globals.deinit(self.allocator);
225
226 for (self.imports.items) |sym| {
204 sym.deinit(self.allocator);227 sym.deinit(self.allocator);
205 self.allocator.destroy(sym);228 self.allocator.destroy(sym);
206 }229 }
207 self.globals.deinit(self.allocator);230 self.imports.deinit(self.allocator);
208231
209 for (self.locals.items) |sym| {232 for (self.locals.items) |sym| {
210 sym.deinit(self.allocator);233 sym.deinit(self.allocator);
...@@ -252,20 +275,21 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -252,20 +275,21 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
252 try self.parseLibs(args.libs, args.syslibroot);275 try self.parseLibs(args.libs, args.syslibroot);
253 try self.resolveSymbols();276 try self.resolveSymbols();
254 try self.parseTextBlocks();277 try self.parseTextBlocks();
255 try self.resolveStubsAndGotEntries();278 return error.TODO;
256 try self.updateMetadata();279 // try self.resolveStubsAndGotEntries();
257 try self.sortSections();280 // try self.updateMetadata();
258 try self.addRpaths(args.rpaths);281 // try self.sortSections();
259 try self.addDataInCodeLC();282 // try self.addRpaths(args.rpaths);
260 try self.addCodeSignatureLC();283 // try self.addDataInCodeLC();
261 try self.allocateTextSegment();284 // try self.addCodeSignatureLC();
262 try self.allocateDataConstSegment();285 // try self.allocateTextSegment();
263 try self.allocateDataSegment();286 // try self.allocateDataConstSegment();
264 self.allocateLinkeditSegment();287 // try self.allocateDataSegment();
265 try self.allocateSymbols();288 // self.allocateLinkeditSegment();
266 try self.allocateTentativeSymbols();289 // try self.allocateSymbols();
267 try self.allocateProxyBindAddresses();290 // try self.allocateTentativeSymbols();
268 try self.flush();291 // try self.allocateProxyBindAddresses();
292 // try self.flush();
269}293}
270294
271fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {295fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
...@@ -1509,13 +1533,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {...@@ -1509,13 +1533,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
1509 symbol.payload = .{1533 symbol.payload = .{
1510 .regular = .{1534 .regular = .{
1511 .linkage = .translation_unit,1535 .linkage = .translation_unit,
1512 .address = sym.n_value,
1513 .section = sym.n_sect - 1,
1514 .weak_ref = Symbol.isWeakRef(sym),1536 .weak_ref = Symbol.isWeakRef(sym),
1515 .file = object,1537 .file = object,
1538 .local_sym_index = @intCast(u32, self.locals.items.len),
1516 },1539 },
1517 };1540 };
1518 const index = @intCast(u32, self.locals.items.len);
1519 try self.locals.append(self.allocator, symbol);1541 try self.locals.append(self.allocator, symbol);
1520 try object.symbols.append(self.allocator, symbol);1542 try object.symbols.append(self.allocator, symbol);
1521 continue;1543 continue;
...@@ -1550,8 +1572,6 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {...@@ -1550,8 +1572,6 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
1550 symbol.payload = .{1572 symbol.payload = .{
1551 .regular = .{1573 .regular = .{
1552 .linkage = linkage,1574 .linkage = linkage,
1553 .address = sym.n_value,
1554 .section = sym.n_sect - 1,
1555 .weak_ref = Symbol.isWeakRef(sym),1575 .weak_ref = Symbol.isWeakRef(sym),
1556 .file = object,1576 .file = object,
1557 },1577 },
...@@ -1581,6 +1601,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {...@@ -1581,6 +1601,11 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
1581}1601}
15821602
1583fn resolveSymbols(self: *Zld) !void {1603fn resolveSymbols(self: *Zld) !void {
1604 // TODO mimicking insertion of null symbol from incremental linker.
1605 // This will need to moved.
1606 const null_sym = try Symbol.new(self.allocator, "");
1607 try self.locals.append(self.allocator, null_sym);
1608
1584 // First pass, resolve symbols in provided objects.1609 // First pass, resolve symbols in provided objects.
1585 for (self.objects.items) |object| {1610 for (self.objects.items) |object| {
1586 try self.resolveSymbolsInObject(object);1611 try self.resolveSymbolsInObject(object);
...@@ -1609,11 +1634,18 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1609,11 +1634,18 @@ fn resolveSymbols(self: *Zld) !void {
1609 }1634 }
1610 }1635 }
16111636
1637 // Put any globally defined regular symbol as local.
1612 // Mark if we need to allocate zerofill section for tentative definitions1638 // Mark if we need to allocate zerofill section for tentative definitions
1613 for (self.globals.values()) |symbol| {1639 for (self.globals.values()) |symbol| {
1614 if (symbol.payload == .tentative) {1640 switch (symbol.payload) {
1615 self.has_tentative_defs = true;1641 .regular => |*reg| {
1616 break;1642 reg.local_sym_index = @intCast(u32, self.locals.items.len);
1643 try self.locals.append(self.allocator, symbol);
1644 },
1645 .tentative => {
1646 self.has_tentative_defs = true;
1647 },
1648 else => {},
1617 }1649 }
1618 }1650 }
16191651
...@@ -1639,6 +1671,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1639,6 +1671,7 @@ fn resolveSymbols(self: *Zld) !void {
1639 .file = dylib,1671 .file = dylib,
1640 },1672 },
1641 };1673 };
1674 try self.imports.append(self.allocator, symbol);
1642 continue :loop;1675 continue :loop;
1643 }1676 }
1644 }1677 }
...@@ -1667,6 +1700,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1667,6 +1700,7 @@ fn resolveSymbols(self: *Zld) !void {
1667 symbol.payload = .{1700 symbol.payload = .{
1668 .proxy = .{},1701 .proxy = .{},
1669 };1702 };
1703 try self.imports.append(self.allocator, symbol);
1670 }1704 }
1671 }1705 }
16721706
...@@ -1686,7 +1720,17 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1686,7 +1720,17 @@ fn resolveSymbols(self: *Zld) !void {
16861720
1687fn parseTextBlocks(self: *Zld) !void {1721fn parseTextBlocks(self: *Zld) !void {
1688 for (self.objects.items) |object| {1722 for (self.objects.items) |object| {
1689 _ = try object.parseTextBlocks(self);1723 if (try object.parseTextBlocks(self)) |block| {
1724 if (self.last_text_block) |last| {
1725 last.next = block;
1726 block.prev = last;
1727 }
1728 self.last_text_block = block;
1729 }
1730 }
1731
1732 if (self.last_text_block) |block| {
1733 block.print(self);
1690 }1734 }
1691}1735}
16921736