authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-01 00:16:01+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-17 19:59:13+01:00
logb0ee480177c5f146cc2a5540745572436e8ca510
treef429bd9deee46b5dfe0e1a5d803f61480cca06d3
parent44ebf4863131fbf822caf6548a347abc52e5ce3b

zld: merge and sort sections


3 files changed, 593 insertions(+), 265 deletions(-)

lib/std/macho.zig+18
......@@ -1227,6 +1227,24 @@ pub const S_ATTR_EXT_RELOC = 0x200;
12271227/// section has local relocation entries
12281228pub const S_ATTR_LOC_RELOC = 0x100;
12291229
1230/// template of initial values for TLVs
1231pub const S_THREAD_LOCAL_REGULAR = 0x11;
1232
1233/// template of initial values for TLVs
1234pub const S_THREAD_LOCAL_ZEROFILL = 0x12;
1235
1236/// TLV descriptors
1237pub const S_THREAD_LOCAL_VARIABLES = 0x13;
1238
1239/// pointers to TLV descriptors
1240pub const S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14;
1241
1242/// functions to call to initialize TLV values
1243pub const S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15;
1244
1245/// 32-bit offsets to initializers
1246pub const S_INIT_FUNC_OFFSETS = 0x16;
1247
12301248pub const cpu_type_t = integer_t;
12311249pub const cpu_subtype_t = integer_t;
12321250pub const integer_t = c_int;
src/link/MachO/Object.zig+1-14
......@@ -24,9 +24,9 @@ segment_cmd_index: ?u16 = null,
2424symtab_cmd_index: ?u16 = null,
2525dysymtab_cmd_index: ?u16 = null,
2626build_version_cmd_index: ?u16 = null,
27
2827text_section_index: ?u16 = null,
2928
29// __DWARF segment sections
3030dwarf_debug_info_index: ?u16 = null,
3131dwarf_debug_abbrev_index: ?u16 = null,
3232dwarf_debug_str_index: ?u16 = null,
......@@ -36,13 +36,6 @@ dwarf_debug_ranges_index: ?u16 = null,
3636symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
3737strtab: std.ArrayListUnmanaged(u8) = .{},
3838
39directory: std.AutoHashMapUnmanaged(DirectoryKey, u16) = .{},
40
41pub const DirectoryKey = struct {
42 segname: [16]u8,
43 sectname: [16]u8,
44};
45
4639pub fn deinit(self: *Object) void {
4740 for (self.load_commands.items) |*lc| {
4841 lc.deinit(self.allocator);
......@@ -50,7 +43,6 @@ pub fn deinit(self: *Object) void {
5043 self.load_commands.deinit(self.allocator);
5144 self.symtab.deinit(self.allocator);
5245 self.strtab.deinit(self.allocator);
53 self.directory.deinit(self.allocator);
5446 self.allocator.free(self.name);
5547 self.file.close();
5648}
......@@ -138,11 +130,6 @@ pub fn readLoadCommands(self: *Object, reader: anytype, offset: ReadOffset) !voi
138130 }
139131 }
140132
141 try self.directory.putNoClobber(self.allocator, .{
142 .segname = sect.segname,
143 .sectname = sect.sectname,
144 }, index);
145
146133 sect.offset += offset_mod;
147134 if (sect.reloff > 0)
148135 sect.reloff += offset_mod;
src/link/MachO/Zld.zig+574-251
......@@ -52,13 +52,22 @@ source_version_cmd_index: ?u16 = null,
5252uuid_cmd_index: ?u16 = null,
5353code_signature_cmd_index: ?u16 = null,
5454
55// __TEXT segment sections
5556text_section_index: ?u16 = null,
5657stubs_section_index: ?u16 = null,
5758stub_helper_section_index: ?u16 = null,
59text_const_section_index: ?u16 = null,
60cstring_section_index: ?u16 = null,
61
62// __DATA segment sections
5863got_section_index: ?u16 = null,
5964tlv_section_index: ?u16 = null,
65tlv_data_section_index: ?u16 = null,
66tlv_bss_section_index: ?u16 = null,
6067la_symbol_ptr_section_index: ?u16 = null,
68data_const_section_index: ?u16 = null,
6169data_section_index: ?u16 = null,
70bss_section_index: ?u16 = null,
6271
6372locals: std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(Symbol)) = .{},
6473exports: std.StringArrayHashMapUnmanaged(macho.nlist_64) = .{},
......@@ -71,13 +80,25 @@ strtab: std.ArrayListUnmanaged(u8) = .{},
7180
7281stub_helper_stubs_start_off: ?u64 = null,
7382
74segments_directory: std.AutoHashMapUnmanaged([16]u8, u16) = .{},
75directory: std.AutoHashMapUnmanaged(DirectoryKey, DirectoryEntry) = .{},
83mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
84unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
85
86const MappingKey = struct {
87 object_id: u16,
88 source_sect_id: u16,
89};
90
91const SectionMapping = struct {
92 source_sect_id: u16,
93 target_seg_id: u16,
94 target_sect_id: u16,
95 offset: u32,
96};
7697
7798const Symbol = struct {
7899 inner: macho.nlist_64,
79100 tt: Type,
80 object: *Object,
101 object_id: u16,
81102
82103 const Type = enum {
83104 Local,
......@@ -86,16 +107,6 @@ const Symbol = struct {
86107 };
87108};
88109
89const DirectoryKey = struct {
90 segname: [16]u8,
91 sectname: [16]u8,
92};
93
94const DirectoryEntry = struct {
95 seg_index: u16,
96 sect_index: u16,
97};
98
99110const DebugInfo = struct {
100111 inner: dwarf.DwarfInfo,
101112 debug_info: []u8,
......@@ -221,8 +232,8 @@ pub fn deinit(self: *Zld) void {
221232 lc.deinit(self.allocator);
222233 }
223234 self.load_commands.deinit(self.allocator);
224 self.segments_directory.deinit(self.allocator);
225 self.directory.deinit(self.allocator);
235 self.mappings.deinit(self.allocator);
236 self.unhandled_sections.deinit(self.allocator);
226237 if (self.file) |*f| f.close();
227238}
228239
......@@ -263,6 +274,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
263274
264275 try self.populateMetadata();
265276 try self.parseInputFiles(files);
277 try self.sortSections();
266278 try self.resolveImports();
267279 try self.allocateTextSegment();
268280 try self.allocateDataSegment();
......@@ -282,10 +294,9 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
282294 error.NotObject => break :try_object,
283295 else => |e| return e,
284296 };
285 const index = self.objects.items.len;
297 const index = @intCast(u16, self.objects.items.len);
286298 try self.objects.append(self.allocator, object);
287 const p_object = &self.objects.items[index];
288 try self.parseObjectFile(p_object);
299 try self.updateMetadata(index);
289300 continue;
290301 }
291302
......@@ -296,10 +307,9 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
296307 };
297308 defer archive.deinit();
298309 while (archive.objects.popOrNull()) |object| {
299 const index = self.objects.items.len;
310 const index = @intCast(u16, self.objects.items.len);
300311 try self.objects.append(self.allocator, object);
301 const p_object = &self.objects.items[index];
302 try self.parseObjectFile(p_object);
312 try self.updateMetadata(index);
303313 }
304314 continue;
305315 }
......@@ -309,49 +319,425 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
309319 }
310320}
311321
312fn parseObjectFile(self: *Zld, object: *const Object) !void {
313 const seg_cmd = object.load_commands.items[object.segment_cmd_index.?].Segment;
314 for (seg_cmd.sections.items) |sect| {
315 const segname = parseName(&sect.segname);
316 const sectname = parseName(&sect.sectname);
322fn mapAndUpdateSections(
323 self: *Zld,
324 object_id: u16,
325 source_sect_id: u16,
326 target_seg_id: u16,
327 target_sect_id: u16,
328) !void {
329 const object = self.objects.items[object_id];
330 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
331 const source_sect = source_seg.sections.items[source_sect_id];
332 const target_seg = &self.load_commands.items[target_seg_id].Segment;
333 const target_sect = &target_seg.sections.items[target_sect_id];
334 log.warn("{}", .{target_sect});
335
336 const alignment = try math.powi(u32, 2, source_sect.@"align");
337 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
338 const size = mem.alignForwardGeneric(u64, source_sect.size, alignment);
339 const key = MappingKey{
340 .object_id = object_id,
341 .source_sect_id = source_sect_id,
342 };
343 try self.mappings.putNoClobber(self.allocator, key, .{
344 .source_sect_id = source_sect_id,
345 .target_seg_id = target_seg_id,
346 .target_sect_id = target_sect_id,
347 .offset = @intCast(u32, offset),
348 });
349 log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{
350 object.name,
351 parseName(&source_sect.segname),
352 parseName(&source_sect.sectname),
353 parseName(&target_sect.segname),
354 parseName(&target_sect.sectname),
355 offset,
356 offset + size,
357 });
317358
318 const seg_index = self.segments_directory.get(sect.segname) orelse {
319 log.info("segname {s} not found in the output artifact", .{sect.segname});
320 continue;
321 };
322 const seg = &self.load_commands.items[seg_index].Segment;
323 const res = try self.directory.getOrPut(self.allocator, .{
324 .segname = sect.segname,
325 .sectname = sect.sectname,
326 });
327 if (!res.found_existing) {
328 const sect_index = @intCast(u16, seg.sections.items.len);
329 if (mem.eql(u8, sectname, "__thread_vars")) {
330 self.tlv_section_index = sect_index;
331 }
332 try seg.append(self.allocator, .{
333 .sectname = makeStaticString(&sect.sectname),
334 .segname = makeStaticString(&sect.segname),
335 .addr = 0,
336 .size = 0,
337 .offset = 0,
338 .@"align" = sect.@"align",
339 .reloff = 0,
340 .nreloc = 0,
341 .flags = sect.flags,
342 .reserved1 = 0,
343 .reserved2 = 0,
344 .reserved3 = 0,
345 });
346 res.entry.value = .{
347 .seg_index = seg_index,
348 .sect_index = sect_index,
349 };
359 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
360 target_sect.size = offset + size;
361}
362
363fn updateMetadata(self: *Zld, object_id: u16) !void {
364 const object = self.objects.items[object_id];
365 const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
366 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
367 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
368
369 // Create missing metadata
370 for (object_seg.sections.items) |source_sect, id| {
371 if (id == object.text_section_index.?) continue;
372 const segname = parseName(&source_sect.segname);
373 const sectname = parseName(&source_sect.sectname);
374 const flags = source_sect.flags;
375
376 switch (flags) {
377 macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
378 if (mem.eql(u8, segname, "__TEXT")) {
379 if (self.text_const_section_index != null) continue;
380
381 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
382 try text_seg.append(self.allocator, .{
383 .sectname = makeStaticString("__const"),
384 .segname = makeStaticString("__TEXT"),
385 .addr = 0,
386 .size = 0,
387 .offset = 0,
388 .@"align" = 0,
389 .reloff = 0,
390 .nreloc = 0,
391 .flags = macho.S_REGULAR,
392 .reserved1 = 0,
393 .reserved2 = 0,
394 .reserved3 = 0,
395 });
396 } else if (mem.eql(u8, segname, "__DATA")) {
397 if (!mem.eql(u8, sectname, "__const")) continue;
398 if (self.data_const_section_index != null) continue;
399
400 self.data_const_section_index = @intCast(u16, data_seg.sections.items.len);
401 try data_seg.append(self.allocator, .{
402 .sectname = makeStaticString("__const"),
403 .segname = makeStaticString("__DATA"),
404 .addr = 0,
405 .size = 0,
406 .offset = 0,
407 .@"align" = 0,
408 .reloff = 0,
409 .nreloc = 0,
410 .flags = macho.S_REGULAR,
411 .reserved1 = 0,
412 .reserved2 = 0,
413 .reserved3 = 0,
414 });
415 }
416 },
417 macho.S_CSTRING_LITERALS => {
418 if (!mem.eql(u8, segname, "__TEXT")) continue;
419 if (self.cstring_section_index != null) continue;
420
421 self.cstring_section_index = @intCast(u16, text_seg.sections.items.len);
422 try text_seg.append(self.allocator, .{
423 .sectname = makeStaticString("__cstring"),
424 .segname = makeStaticString("__TEXT"),
425 .addr = 0,
426 .size = 0,
427 .offset = 0,
428 .@"align" = 0,
429 .reloff = 0,
430 .nreloc = 0,
431 .flags = macho.S_CSTRING_LITERALS,
432 .reserved1 = 0,
433 .reserved2 = 0,
434 .reserved3 = 0,
435 });
436 },
437 macho.S_ZEROFILL => {
438 if (!mem.eql(u8, segname, "__DATA")) continue;
439 if (self.bss_section_index != null) continue;
440
441 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
442 try data_seg.append(self.allocator, .{
443 .sectname = makeStaticString("__bss"),
444 .segname = makeStaticString("__DATA"),
445 .addr = 0,
446 .size = 0,
447 .offset = 0,
448 .@"align" = 0,
449 .reloff = 0,
450 .nreloc = 0,
451 .flags = macho.S_ZEROFILL,
452 .reserved1 = 0,
453 .reserved2 = 0,
454 .reserved3 = 0,
455 });
456 },
457 macho.S_THREAD_LOCAL_VARIABLES => {
458 if (!mem.eql(u8, segname, "__DATA")) continue;
459 if (self.tlv_section_index != null) continue;
460
461 self.tlv_section_index = @intCast(u16, data_seg.sections.items.len);
462 try data_seg.append(self.allocator, .{
463 .sectname = makeStaticString("__thread_vars"),
464 .segname = makeStaticString("__DATA"),
465 .addr = 0,
466 .size = 0,
467 .offset = 0,
468 .@"align" = 0,
469 .reloff = 0,
470 .nreloc = 0,
471 .flags = macho.S_THREAD_LOCAL_VARIABLES,
472 .reserved1 = 0,
473 .reserved2 = 0,
474 .reserved3 = 0,
475 });
476 },
477 macho.S_THREAD_LOCAL_REGULAR => {
478 if (!mem.eql(u8, segname, "__DATA")) continue;
479 if (self.tlv_data_section_index != null) continue;
480
481 self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len);
482 try data_seg.append(self.allocator, .{
483 .sectname = makeStaticString("__thread_data"),
484 .segname = makeStaticString("__DATA"),
485 .addr = 0,
486 .size = 0,
487 .offset = 0,
488 .@"align" = 0,
489 .reloff = 0,
490 .nreloc = 0,
491 .flags = macho.S_THREAD_LOCAL_REGULAR,
492 .reserved1 = 0,
493 .reserved2 = 0,
494 .reserved3 = 0,
495 });
496 },
497 macho.S_THREAD_LOCAL_ZEROFILL => {
498 if (!mem.eql(u8, segname, "__DATA")) continue;
499 if (self.tlv_bss_section_index != null) continue;
500
501 self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len);
502 try data_seg.append(self.allocator, .{
503 .sectname = makeStaticString("__thread_bss"),
504 .segname = makeStaticString("__DATA"),
505 .addr = 0,
506 .size = 0,
507 .offset = 0,
508 .@"align" = 0,
509 .reloff = 0,
510 .nreloc = 0,
511 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
512 .reserved1 = 0,
513 .reserved2 = 0,
514 .reserved3 = 0,
515 });
516 },
517 else => {
518 log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });
519 },
350520 }
351 const dest_sect = &seg.sections.items[res.entry.value.sect_index];
352 dest_sect.@"align" = math.max(dest_sect.@"align", sect.@"align");
353 dest_sect.size += sect.size;
354 seg.inner.filesize += sect.size;
521 }
522
523 // Update section mappings
524 // __TEXT,__text has to be always defined!
525 try self.mapAndUpdateSections(
526 object_id,
527 object.text_section_index.?,
528 self.text_segment_cmd_index.?,
529 self.text_section_index.?,
530 );
531
532 for (object_seg.sections.items) |source_sect, id| {
533 const source_sect_id = @intCast(u16, id);
534 if (id == object.text_section_index.?) continue;
535
536 const segname = parseName(&source_sect.segname);
537 const sectname = parseName(&source_sect.sectname);
538 const flags = source_sect.flags;
539
540 switch (flags) {
541 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
542 try self.mapAndUpdateSections(
543 object_id,
544 source_sect_id,
545 self.text_segment_cmd_index.?,
546 self.text_const_section_index.?,
547 );
548 },
549 macho.S_CSTRING_LITERALS => {
550 try self.mapAndUpdateSections(
551 object_id,
552 source_sect_id,
553 self.text_segment_cmd_index.?,
554 self.cstring_section_index.?,
555 );
556 },
557 macho.S_ZEROFILL => {
558 try self.mapAndUpdateSections(
559 object_id,
560 source_sect_id,
561 self.data_segment_cmd_index.?,
562 self.bss_section_index.?,
563 );
564 },
565 macho.S_THREAD_LOCAL_VARIABLES => {
566 try self.mapAndUpdateSections(
567 object_id,
568 source_sect_id,
569 self.data_segment_cmd_index.?,
570 self.tlv_section_index.?,
571 );
572 },
573 macho.S_THREAD_LOCAL_REGULAR => {
574 try self.mapAndUpdateSections(
575 object_id,
576 source_sect_id,
577 self.data_segment_cmd_index.?,
578 self.tlv_data_section_index.?,
579 );
580 },
581 macho.S_THREAD_LOCAL_ZEROFILL => {
582 try self.mapAndUpdateSections(
583 object_id,
584 source_sect_id,
585 self.data_segment_cmd_index.?,
586 self.tlv_bss_section_index.?,
587 );
588 },
589 macho.S_REGULAR => {
590 if (mem.eql(u8, segname, "__TEXT")) {
591 try self.mapAndUpdateSections(
592 object_id,
593 source_sect_id,
594 self.text_segment_cmd_index.?,
595 self.text_const_section_index.?,
596 );
597 continue;
598 } else if (mem.eql(u8, segname, "__DATA")) {
599 if (mem.eql(u8, sectname, "__data")) {
600 try self.mapAndUpdateSections(
601 object_id,
602 source_sect_id,
603 self.data_segment_cmd_index.?,
604 self.data_section_index.?,
605 );
606 continue;
607 } else if (mem.eql(u8, sectname, "__const")) {
608 try self.mapAndUpdateSections(
609 object_id,
610 source_sect_id,
611 self.data_segment_cmd_index.?,
612 self.data_const_section_index.?,
613 );
614 continue;
615 }
616 }
617 log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname });
618 try self.unhandled_sections.putNoClobber(self.allocator, .{
619 .object_id = object_id,
620 .source_sect_id = source_sect_id,
621 }, 0);
622 },
623 else => {
624 log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname });
625 try self.unhandled_sections.putNoClobber(self.allocator, .{
626 .object_id = object_id,
627 .source_sect_id = source_sect_id,
628 }, 0);
629 },
630 }
631 }
632}
633
634fn sortSections(self: *Zld) !void {
635 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
636 var text_sections = text_seg.sections.toOwnedSlice(self.allocator);
637 defer self.allocator.free(text_sections);
638 try text_seg.sections.ensureCapacity(self.allocator, text_sections.len);
639
640 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
641 var data_sections = data_seg.sections.toOwnedSlice(self.allocator);
642 defer self.allocator.free(data_sections);
643 try data_seg.sections.ensureCapacity(self.allocator, data_sections.len);
644
645 var text_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);
646 defer text_index_mapping.deinit();
647
648 var data_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);
649 defer data_index_mapping.deinit();
650
651 if (self.text_section_index) |index| {
652 const new_index = @intCast(u16, text_seg.sections.items.len);
653 self.text_section_index = new_index;
654 text_seg.sections.appendAssumeCapacity(text_sections[index]);
655 try text_index_mapping.putNoClobber(index, new_index);
656 }
657 if (self.stubs_section_index) |index| {
658 const new_index = @intCast(u16, text_seg.sections.items.len);
659 self.stubs_section_index = new_index;
660 text_seg.sections.appendAssumeCapacity(text_sections[index]);
661 try text_index_mapping.putNoClobber(index, new_index);
662 }
663 if (self.stub_helper_section_index) |index| {
664 const new_index = @intCast(u16, text_seg.sections.items.len);
665 self.stub_helper_section_index = new_index;
666 text_seg.sections.appendAssumeCapacity(text_sections[index]);
667 try text_index_mapping.putNoClobber(index, new_index);
668 }
669 if (self.text_const_section_index) |index| {
670 const new_index = @intCast(u16, text_seg.sections.items.len);
671 self.text_const_section_index = new_index;
672 text_seg.sections.appendAssumeCapacity(text_sections[index]);
673 try text_index_mapping.putNoClobber(index, new_index);
674 }
675 if (self.cstring_section_index) |index| {
676 const new_index = @intCast(u16, text_seg.sections.items.len);
677 self.cstring_section_index = new_index;
678 text_seg.sections.appendAssumeCapacity(text_sections[index]);
679 try text_index_mapping.putNoClobber(index, new_index);
680 }
681
682 if (self.got_section_index) |index| {
683 const new_index = @intCast(u16, data_seg.sections.items.len);
684 self.got_section_index = new_index;
685 data_seg.sections.appendAssumeCapacity(data_sections[index]);
686 try data_index_mapping.putNoClobber(index, new_index);
687 }
688 if (self.data_const_section_index) |index| {
689 const new_index = @intCast(u16, data_seg.sections.items.len);
690 self.data_const_section_index = new_index;
691 data_seg.sections.appendAssumeCapacity(data_sections[index]);
692 try data_index_mapping.putNoClobber(index, new_index);
693 }
694 if (self.la_symbol_ptr_section_index) |index| {
695 const new_index = @intCast(u16, data_seg.sections.items.len);
696 self.la_symbol_ptr_section_index = new_index;
697 data_seg.sections.appendAssumeCapacity(data_sections[index]);
698 try data_index_mapping.putNoClobber(index, new_index);
699 }
700 if (self.tlv_section_index) |index| {
701 const new_index = @intCast(u16, data_seg.sections.items.len);
702 self.tlv_section_index = new_index;
703 data_seg.sections.appendAssumeCapacity(data_sections[index]);
704 try data_index_mapping.putNoClobber(index, new_index);
705 }
706 if (self.data_section_index) |index| {
707 const new_index = @intCast(u16, data_seg.sections.items.len);
708 self.data_section_index = new_index;
709 data_seg.sections.appendAssumeCapacity(data_sections[index]);
710 try data_index_mapping.putNoClobber(index, new_index);
711 }
712 if (self.tlv_data_section_index) |index| {
713 const new_index = @intCast(u16, data_seg.sections.items.len);
714 self.tlv_data_section_index = new_index;
715 data_seg.sections.appendAssumeCapacity(data_sections[index]);
716 try data_index_mapping.putNoClobber(index, new_index);
717 }
718 if (self.tlv_bss_section_index) |index| {
719 const new_index = @intCast(u16, data_seg.sections.items.len);
720 self.tlv_bss_section_index = new_index;
721 data_seg.sections.appendAssumeCapacity(data_sections[index]);
722 try data_index_mapping.putNoClobber(index, new_index);
723 }
724 if (self.bss_section_index) |index| {
725 const new_index = @intCast(u16, data_seg.sections.items.len);
726 self.bss_section_index = new_index;
727 data_seg.sections.appendAssumeCapacity(data_sections[index]);
728 try data_index_mapping.putNoClobber(index, new_index);
729 }
730
731 var it = self.mappings.iterator();
732 while (it.next()) |entry| {
733 const mapping = &entry.value;
734 if (self.text_segment_cmd_index.? == mapping.target_seg_id) {
735 const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable;
736 mapping.target_sect_id = new_index;
737 } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) {
738 const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable;
739 mapping.target_sect_id = new_index;
740 } else unreachable;
355741 }
356742}
357743
......@@ -790,35 +1176,9 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
7901176}
7911177
7921178fn resolveSymbols(self: *Zld) !void {
793 const Address = struct {
794 addr: u64,
795 size: u64,
796 };
797 var next_address = std.AutoHashMap(DirectoryKey, Address).init(self.allocator);
798 defer next_address.deinit();
799
800 for (self.objects.items) |*object| {
1179 for (self.objects.items) |object, object_id| {
8011180 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
8021181
803 for (seg.sections.items) |sect| {
804 const key: DirectoryKey = .{
805 .segname = sect.segname,
806 .sectname = sect.sectname,
807 };
808 const indices = self.directory.get(key) orelse continue;
809 const out_seg = self.load_commands.items[indices.seg_index].Segment;
810 const out_sect = out_seg.sections.items[indices.sect_index];
811
812 const res = try next_address.getOrPut(key);
813 const next = &res.entry.value;
814 if (res.found_existing) {
815 next.addr += next.size;
816 } else {
817 next.addr = out_sect.addr;
818 }
819 next.size = sect.size;
820 }
821
8221182 for (object.symtab.items) |sym| {
8231183 if (isImport(&sym)) continue;
8241184
......@@ -851,24 +1211,36 @@ fn resolveSymbols(self: *Zld) !void {
8511211 }
8521212 }
8531213
854 const sect = seg.sections.items[sym.n_sect - 1];
855 const key: DirectoryKey = .{
856 .segname = sect.segname,
857 .sectname = sect.sectname,
1214 const source_sect_id = sym.n_sect - 1;
1215 const target_mapping = self.mappings.get(.{
1216 .object_id = @intCast(u16, object_id),
1217 .source_sect_id = source_sect_id,
1218 }) orelse {
1219 if (self.unhandled_sections.get(.{
1220 .object_id = @intCast(u16, object_id),
1221 .source_sect_id = source_sect_id,
1222 }) != null) continue;
1223
1224 log.err("section not mapped for symbol '{s}': {}", .{ sym_name, sym });
1225 return error.SectionNotMappedForSymbol;
8581226 };
859 const res = self.directory.get(key) orelse continue;
860
861 const n_value = sym.n_value - sect.addr + next_address.get(key).?.addr;
1227 const source_sect = seg.sections.items[source_sect_id];
1228 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1229 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1230 const target_addr = target_sect.addr + target_mapping.offset;
1231 const n_value = sym.n_value - source_sect.addr + target_addr;
8621232
8631233 log.warn("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value });
8641234
865 var n_sect = res.sect_index + 1;
866 for (self.load_commands.items) |sseg, i| {
867 if (i == res.seg_index) {
868 break;
1235 // TODO this assumes only two symbol-filled segments. Also, there might be a more
1236 // generic way of doing this.
1237 const n_sect = blk: {
1238 if (self.text_segment_cmd_index.? == target_mapping.target_seg_id) {
1239 break :blk target_mapping.target_sect_id + 1;
8691240 }
870 n_sect += @intCast(u16, sseg.Segment.sections.items.len);
871 }
1241 const prev_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1242 break :blk @intCast(u16, prev_seg.sections.items.len + target_mapping.target_sect_id + 1);
1243 };
8721244
8731245 const n_strx = try self.makeString(sym_name);
8741246 try locs.entry.value.append(self.allocator, .{
......@@ -880,64 +1252,26 @@ fn resolveSymbols(self: *Zld) !void {
8801252 .n_sect = @intCast(u8, n_sect),
8811253 },
8821254 .tt = tt,
883 .object = object,
1255 .object_id = @intCast(u16, object_id),
8841256 });
8851257 }
8861258 }
8871259}
8881260
8891261fn doRelocs(self: *Zld) !void {
890 const Space = struct {
891 address: u64,
892 offset: u64,
893 size: u64,
894 };
895 var next_space = std.AutoHashMap(DirectoryKey, Space).init(self.allocator);
896 defer next_space.deinit();
897
898 for (self.objects.items) |object| {
1262 for (self.objects.items) |object, object_id| {
8991263 log.warn("\n\n", .{});
9001264 log.warn("relocating object {s}", .{object.name});
9011265
9021266 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
9031267
904 for (seg.sections.items) |sect| {
905 const key: DirectoryKey = .{
906 .segname = sect.segname,
907 .sectname = sect.sectname,
908 };
909 const indices = self.directory.get(key) orelse continue;
910 const out_seg = self.load_commands.items[indices.seg_index].Segment;
911 const out_sect = out_seg.sections.items[indices.sect_index];
912
913 const res = try next_space.getOrPut(key);
914 const next = &res.entry.value;
915 if (res.found_existing) {
916 next.offset += next.size;
917 next.address += next.size;
918 } else {
919 next.offset = out_sect.offset;
920 next.address = out_sect.addr;
921 }
922 next.size = sect.size;
923 }
924
925 for (seg.sections.items) |sect| {
1268 for (seg.sections.items) |sect, source_sect_id| {
9261269 const segname = parseName(&sect.segname);
9271270 const sectname = parseName(&sect.sectname);
9281271
929 const key: DirectoryKey = .{
930 .segname = sect.segname,
931 .sectname = sect.sectname,
932 };
933 const next = next_space.get(key) orelse continue;
934
935 var code = blk: {
936 var buf = try self.allocator.alloc(u8, sect.size);
937 _ = try object.file.preadAll(buf, sect.offset);
938 break :blk std.ArrayList(u8).fromOwnedSlice(self.allocator, buf);
939 };
940 defer code.deinit();
1272 var code = try self.allocator.alloc(u8, sect.size);
1273 _ = try object.file.preadAll(code, sect.offset);
1274 defer self.allocator.free(code);
9411275
9421276 // Parse relocs (if any)
9431277 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
......@@ -945,12 +1279,25 @@ fn doRelocs(self: *Zld) !void {
9451279 _ = try object.file.preadAll(raw_relocs, sect.reloff);
9461280 const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
9471281
1282 // Get mapping
1283 const target_mapping = self.mappings.get(.{
1284 .object_id = @intCast(u16, object_id),
1285 .source_sect_id = @intCast(u16, source_sect_id),
1286 }) orelse {
1287 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
1288 continue;
1289 };
1290 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1291 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1292 const target_sect_addr = target_sect.addr + target_mapping.offset;
1293 const target_sect_off = target_sect.offset + target_mapping.offset;
1294
9481295 var addend: ?u64 = null;
9491296 var sub: ?i64 = null;
9501297
9511298 for (relocs) |rel| {
9521299 const off = @intCast(u32, rel.r_address);
953 const this_addr = next.address + off;
1300 const this_addr = target_sect_addr + off;
9541301
9551302 switch (self.arch.?) {
9561303 .aarch64 => {
......@@ -975,7 +1322,7 @@ fn doRelocs(self: *Zld) !void {
9751322 else => {},
9761323 }
9771324
978 const target_addr = try self.relocTargetAddr(object, rel, next_space);
1325 const target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel);
9791326 log.warn(" | target address 0x{x}", .{target_addr});
9801327 if (rel.r_extern == 1) {
9811328 const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx);
......@@ -995,16 +1342,16 @@ fn doRelocs(self: *Zld) !void {
9951342 .X86_64_RELOC_GOT,
9961343 => {
9971344 assert(rel.r_length == 2);
998 const inst = code.items[off..][0..4];
1345 const inst = code[off..][0..4];
9991346 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));
10001347 mem.writeIntLittle(u32, inst, displacement);
10011348 },
10021349 .X86_64_RELOC_TLV => {
10031350 assert(rel.r_length == 2);
10041351 // We need to rewrite the opcode from movq to leaq.
1005 code.items[off - 2] = 0x8d;
1352 code[off - 2] = 0x8d;
10061353 // Add displacement.
1007 const inst = code.items[off..][0..4];
1354 const inst = code[off..][0..4];
10081355 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));
10091356 mem.writeIntLittle(u32, inst, displacement);
10101357 },
......@@ -1014,7 +1361,7 @@ fn doRelocs(self: *Zld) !void {
10141361 .X86_64_RELOC_SIGNED_4,
10151362 => {
10161363 assert(rel.r_length == 2);
1017 const inst = code.items[off..][0..4];
1364 const inst = code[off..][0..4];
10181365 const offset: i32 = blk: {
10191366 if (rel.r_extern == 1) {
10201367 break :blk mem.readIntLittle(i32, inst);
......@@ -1043,7 +1390,7 @@ fn doRelocs(self: *Zld) !void {
10431390 .X86_64_RELOC_UNSIGNED => {
10441391 switch (rel.r_length) {
10451392 3 => {
1046 const inst = code.items[off..][0..8];
1393 const inst = code[off..][0..8];
10471394 const offset = mem.readIntLittle(i64, inst);
10481395 log.warn(" | calculated addend 0x{x}", .{offset});
10491396 const result = if (sub) |s|
......@@ -1054,12 +1401,19 @@ fn doRelocs(self: *Zld) !void {
10541401 sub = null;
10551402
10561403 // TODO should handle this better.
1057 if (mem.eql(u8, segname, "__DATA")) outer: {
1058 if (!mem.eql(u8, sectname, "__data") and
1059 !mem.eql(u8, sectname, "__const") and
1060 !mem.eql(u8, sectname, "__mod_init_func")) break :outer;
1404 outer: {
1405 var hit: bool = false;
1406 if (self.data_section_index) |index| inner: {
1407 if (index != target_mapping.target_sect_id) break :inner;
1408 hit = true;
1409 }
1410 if (self.data_const_section_index) |index| inner: {
1411 if (index != target_mapping.target_sect_id) break :inner;
1412 hit = true;
1413 }
1414 if (!hit) break :outer;
10611415 const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1062 const this_offset = next.address + off - this_seg.inner.vmaddr;
1416 const this_offset = target_sect_addr + off - this_seg.inner.vmaddr;
10631417 try self.local_rebases.append(self.allocator, .{
10641418 .offset = this_offset,
10651419 .segment_id = @intCast(u16, self.data_segment_cmd_index.?),
......@@ -1067,7 +1421,7 @@ fn doRelocs(self: *Zld) !void {
10671421 }
10681422 },
10691423 2 => {
1070 const inst = code.items[off..][0..4];
1424 const inst = code[off..][0..4];
10711425 const offset = mem.readIntLittle(i32, inst);
10721426 log.warn(" | calculated addend 0x{x}", .{offset});
10731427 const result = if (sub) |s|
......@@ -1091,7 +1445,7 @@ fn doRelocs(self: *Zld) !void {
10911445 switch (rel_type) {
10921446 .ARM64_RELOC_BRANCH26 => {
10931447 assert(rel.r_length == 2);
1094 const inst = code.items[off..][0..4];
1448 const inst = code[off..][0..4];
10951449 const displacement = @intCast(i28, @intCast(i64, target_addr) - @intCast(i64, this_addr));
10961450 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Branch), inst);
10971451 parsed.disp = @truncate(u26, @bitCast(u28, displacement) >> 2);
......@@ -1101,7 +1455,7 @@ fn doRelocs(self: *Zld) !void {
11011455 .ARM64_RELOC_TLVP_LOAD_PAGE21,
11021456 => {
11031457 assert(rel.r_length == 2);
1104 const inst = code.items[off..][0..4];
1458 const inst = code[off..][0..4];
11051459 const ta = if (addend) |a| target_addr + a else target_addr;
11061460 const this_page = @intCast(i32, this_addr >> 12);
11071461 const target_page = @intCast(i32, ta >> 12);
......@@ -1115,7 +1469,7 @@ fn doRelocs(self: *Zld) !void {
11151469 .ARM64_RELOC_PAGEOFF12,
11161470 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
11171471 => {
1118 const inst = code.items[off..][0..4];
1472 const inst = code[off..][0..4];
11191473 if (Arm64.isArithmetic(inst)) {
11201474 log.warn(" | detected ADD opcode", .{});
11211475 // add
......@@ -1153,7 +1507,7 @@ fn doRelocs(self: *Zld) !void {
11531507 rn: u5,
11541508 size: u1,
11551509 };
1156 const inst = code.items[off..][0..4];
1510 const inst = code[off..][0..4];
11571511 const parsed: RegInfo = blk: {
11581512 if (Arm64.isArithmetic(inst)) {
11591513 const curr = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
......@@ -1175,7 +1529,7 @@ fn doRelocs(self: *Zld) !void {
11751529 .ARM64_RELOC_UNSIGNED => {
11761530 switch (rel.r_length) {
11771531 3 => {
1178 const inst = code.items[off..][0..8];
1532 const inst = code[off..][0..8];
11791533 const offset = mem.readIntLittle(i64, inst);
11801534 log.warn(" | calculated addend 0x{x}", .{offset});
11811535 const result = if (sub) |s|
......@@ -1186,12 +1540,19 @@ fn doRelocs(self: *Zld) !void {
11861540 sub = null;
11871541
11881542 // TODO should handle this better.
1189 if (mem.eql(u8, segname, "__DATA")) outer: {
1190 if (!mem.eql(u8, sectname, "__data") and
1191 !mem.eql(u8, sectname, "__const") and
1192 !mem.eql(u8, sectname, "__mod_init_func")) break :outer;
1543 outer: {
1544 var hit: bool = false;
1545 if (self.data_section_index) |index| inner: {
1546 if (index != target_mapping.target_sect_id) break :inner;
1547 hit = true;
1548 }
1549 if (self.data_const_section_index) |index| inner: {
1550 if (index != target_mapping.target_sect_id) break :inner;
1551 hit = true;
1552 }
1553 if (!hit) break :outer;
11931554 const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1194 const this_offset = next.address + off - this_seg.inner.vmaddr;
1555 const this_offset = target_sect_addr + off - this_seg.inner.vmaddr;
11951556 try self.local_rebases.append(self.allocator, .{
11961557 .offset = this_offset,
11971558 .segment_id = @intCast(u16, self.data_segment_cmd_index.?),
......@@ -1199,7 +1560,7 @@ fn doRelocs(self: *Zld) !void {
11991560 }
12001561 },
12011562 2 => {
1202 const inst = code.items[off..][0..4];
1563 const inst = code[off..][0..4];
12031564 const offset = mem.readIntLittle(i32, inst);
12041565 log.warn(" | calculated addend 0x{x}", .{offset});
12051566 const result = if (sub) |s|
......@@ -1227,40 +1588,50 @@ fn doRelocs(self: *Zld) !void {
12271588 segname,
12281589 sectname,
12291590 object.name,
1230 next.offset,
1231 next.offset + next.size,
1591 target_sect_off,
1592 target_sect_off + code.len,
12321593 });
12331594
1234 if (mem.eql(u8, sectname, "__bss") or
1235 mem.eql(u8, sectname, "__thread_bss") or
1236 mem.eql(u8, sectname, "__thread_vars"))
1595 if (target_sect.flags == macho.S_ZEROFILL or
1596 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
1597 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
12371598 {
1599 log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1600 parseName(&target_sect.segname),
1601 parseName(&target_sect.sectname),
1602 target_sect_off,
1603 target_sect_off + code.len,
1604 });
12381605 // Zero-out the space
1239 var zeroes = try self.allocator.alloc(u8, next.size);
1606 var zeroes = try self.allocator.alloc(u8, code.len);
12401607 defer self.allocator.free(zeroes);
12411608 mem.set(u8, zeroes, 0);
1242 try self.file.?.pwriteAll(zeroes, next.offset);
1609 try self.file.?.pwriteAll(zeroes, target_sect_off);
12431610 } else {
1244 try self.file.?.pwriteAll(code.items, next.offset);
1611 try self.file.?.pwriteAll(code, target_sect_off);
12451612 }
12461613 }
12471614 }
12481615}
12491616
1250fn relocTargetAddr(self: *Zld, object: Object, rel: macho.relocation_info, next_space: anytype) !u64 {
1617fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 {
1618 const object = self.objects.items[object_id];
12511619 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
12521620 const target_addr = blk: {
12531621 if (rel.r_extern == 1) {
12541622 const sym = object.symtab.items[rel.r_symbolnum];
12551623 if (isLocal(&sym) or isExport(&sym)) {
12561624 // Relocate using section offsets only.
1257 const source_sect = seg.sections.items[sym.n_sect - 1];
1258 const target_space = next_space.get(.{
1259 .segname = source_sect.segname,
1260 .sectname = source_sect.sectname,
1261 }).?;
1625 const target_mapping = self.mappings.get(.{
1626 .object_id = object_id,
1627 .source_sect_id = sym.n_sect - 1,
1628 }) orelse unreachable;
1629 const source_sect = seg.sections.items[target_mapping.source_sect_id];
1630 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1631 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1632 const target_sect_addr = target_sect.addr + target_mapping.offset;
12621633 log.warn(" | symbol local to object", .{});
1263 break :blk target_space.address + sym.n_value - source_sect.addr;
1634 break :blk target_sect_addr + sym.n_value - source_sect.addr;
12641635 } else if (isImport(&sym)) {
12651636 // Relocate to either the artifact's local symbol, or an import from
12661637 // shared library.
......@@ -1309,12 +1680,13 @@ fn relocTargetAddr(self: *Zld, object: Object, rel: macho.relocation_info, next_
13091680 // here to get the actual section plus offset into that section of the relocated
13101681 // symbol. Unless the fine-grained location is encoded within the cell in the code
13111682 // buffer?
1312 const source_sectname = seg.sections.items[rel.r_symbolnum - 1];
1313 const target_space = next_space.get(.{
1314 .segname = source_sectname.segname,
1315 .sectname = source_sectname.sectname,
1316 }).?;
1317 break :blk target_space.address;
1683 const target_mapping = self.mappings.get(.{
1684 .object_id = object_id,
1685 .source_sect_id = @intCast(u16, rel.r_symbolnum - 1),
1686 }) orelse unreachable;
1687 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1688 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1689 break :blk target_sect.addr + target_mapping.offset;
13181690 }
13191691 };
13201692 return target_addr;
......@@ -1338,7 +1710,6 @@ fn populateMetadata(self: *Zld) !void {
13381710 .flags = 0,
13391711 }),
13401712 });
1341 try self.addSegmentToDir(0);
13421713 }
13431714
13441715 if (self.text_segment_cmd_index == null) {
......@@ -1358,7 +1729,6 @@ fn populateMetadata(self: *Zld) !void {
13581729 .flags = 0,
13591730 }),
13601731 });
1361 try self.addSegmentToDir(self.text_segment_cmd_index.?);
13621732 }
13631733
13641734 if (self.text_section_index == null) {
......@@ -1383,10 +1753,6 @@ fn populateMetadata(self: *Zld) !void {
13831753 .reserved2 = 0,
13841754 .reserved3 = 0,
13851755 });
1386 try self.addSectionToDir(.{
1387 .seg_index = self.text_segment_cmd_index.?,
1388 .sect_index = self.text_section_index.?,
1389 });
13901756 }
13911757
13921758 if (self.stubs_section_index == null) {
......@@ -1416,10 +1782,6 @@ fn populateMetadata(self: *Zld) !void {
14161782 .reserved2 = stub_size,
14171783 .reserved3 = 0,
14181784 });
1419 try self.addSectionToDir(.{
1420 .seg_index = self.text_segment_cmd_index.?,
1421 .sect_index = self.stubs_section_index.?,
1422 });
14231785 }
14241786
14251787 if (self.stub_helper_section_index == null) {
......@@ -1449,10 +1811,6 @@ fn populateMetadata(self: *Zld) !void {
14491811 .reserved2 = 0,
14501812 .reserved3 = 0,
14511813 });
1452 try self.addSectionToDir(.{
1453 .seg_index = self.text_segment_cmd_index.?,
1454 .sect_index = self.stub_helper_section_index.?,
1455 });
14561814 }
14571815
14581816 if (self.data_segment_cmd_index == null) {
......@@ -1472,7 +1830,6 @@ fn populateMetadata(self: *Zld) !void {
14721830 .flags = 0,
14731831 }),
14741832 });
1475 try self.addSegmentToDir(self.data_segment_cmd_index.?);
14761833 }
14771834
14781835 if (self.got_section_index == null) {
......@@ -1492,10 +1849,6 @@ fn populateMetadata(self: *Zld) !void {
14921849 .reserved2 = 0,
14931850 .reserved3 = 0,
14941851 });
1495 try self.addSectionToDir(.{
1496 .seg_index = self.data_segment_cmd_index.?,
1497 .sect_index = self.got_section_index.?,
1498 });
14991852 }
15001853
15011854 if (self.la_symbol_ptr_section_index == null) {
......@@ -1515,10 +1868,6 @@ fn populateMetadata(self: *Zld) !void {
15151868 .reserved2 = 0,
15161869 .reserved3 = 0,
15171870 });
1518 try self.addSectionToDir(.{
1519 .seg_index = self.data_segment_cmd_index.?,
1520 .sect_index = self.la_symbol_ptr_section_index.?,
1521 });
15221871 }
15231872
15241873 if (self.data_section_index == null) {
......@@ -1538,10 +1887,6 @@ fn populateMetadata(self: *Zld) !void {
15381887 .reserved2 = 0,
15391888 .reserved3 = 0,
15401889 });
1541 try self.addSectionToDir(.{
1542 .seg_index = self.data_segment_cmd_index.?,
1543 .sect_index = self.data_section_index.?,
1544 });
15451890 }
15461891
15471892 if (self.linkedit_segment_cmd_index == null) {
......@@ -1561,7 +1906,6 @@ fn populateMetadata(self: *Zld) !void {
15611906 .flags = 0,
15621907 }),
15631908 });
1564 try self.addSegmentToDir(self.linkedit_segment_cmd_index.?);
15651909 }
15661910
15671911 if (self.dyld_info_cmd_index == null) {
......@@ -1719,22 +2063,15 @@ fn populateMetadata(self: *Zld) !void {
17192063}
17202064
17212065fn flush(self: *Zld) !void {
1722 {
2066 if (self.bss_section_index) |index| {
17232067 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1724 for (seg.sections.items) |*sect| {
1725 const sectname = parseName(&sect.sectname);
1726 if (mem.eql(u8, sectname, "__bss") or mem.eql(u8, sectname, "__thread_bss")) {
1727 sect.offset = 0;
1728 }
1729 }
2068 const sect = &seg.sections.items[index];
2069 sect.offset = 0;
17302070 }
1731 {
1732 const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1733 for (seg.sections.items) |*sect| {
1734 if (mem.eql(u8, parseName(&sect.sectname), "__eh_frame")) {
1735 sect.flags = 0;
1736 }
1737 }
2071 if (self.tlv_bss_section_index) |index| {
2072 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2073 const sect = &seg.sections.items[index];
2074 sect.offset = 0;
17382075 }
17392076 try self.setEntryPoint();
17402077 try self.writeRebaseInfoTable();
......@@ -2056,9 +2393,9 @@ fn writeDebugInfo(self: *Zld) !void {
20562393 var stabs = std.ArrayList(macho.nlist_64).init(self.allocator);
20572394 defer stabs.deinit();
20582395
2059 for (self.objects.items) |*object| {
2396 for (self.objects.items) |object, object_id| {
20602397 var debug_info = blk: {
2061 var di = try DebugInfo.parseFromObject(self.allocator, object.*);
2398 var di = try DebugInfo.parseFromObject(self.allocator, object);
20622399 break :blk di orelse continue;
20632400 };
20642401 defer debug_info.deinit(self.allocator);
......@@ -2108,7 +2445,7 @@ fn writeDebugInfo(self: *Zld) !void {
21082445 const target_syms = self.locals.get(symname) orelse continue;
21092446 const target_sym: Symbol = blk: {
21102447 for (target_syms.items) |ts| {
2111 if (ts.object == object) break :blk ts;
2448 if (ts.object_id == @intCast(u16, object_id)) break :blk ts;
21122449 } else continue;
21132450 };
21142451
......@@ -2204,7 +2541,7 @@ fn writeSymbolTable(self: *Zld) !void {
22042541 for (entries.value.items) |entry| {
22052542 log.warn(" | {}", .{entry.inner});
22062543 log.warn(" | {}", .{entry.tt});
2207 log.warn(" | {s}", .{entry.object.name});
2544 log.warn(" | {s}", .{self.objects.items[entry.object_id].name});
22082545 // switch (entry.tt) {
22092546 // .Global => {
22102547 // symbol = entry.inner;
......@@ -2468,20 +2805,6 @@ pub fn parseName(name: *const [16]u8) []const u8 {
24682805 return name[0..len];
24692806}
24702807
2471fn addSegmentToDir(self: *Zld, idx: u16) !void {
2472 const segment_cmd = self.load_commands.items[idx].Segment;
2473 return self.segments_directory.putNoClobber(self.allocator, segment_cmd.inner.segname, idx);
2474}
2475
2476fn addSectionToDir(self: *Zld, value: DirectoryEntry) !void {
2477 const seg = self.load_commands.items[value.seg_index].Segment;
2478 const sect = seg.sections.items[value.sect_index];
2479 return self.directory.putNoClobber(self.allocator, .{
2480 .segname = sect.segname,
2481 .sectname = sect.sectname,
2482 }, value);
2483}
2484
24852808fn isLocal(sym: *const macho.nlist_64) callconv(.Inline) bool {
24862809 if (isExtern(sym)) return false;
24872810 const tt = macho.N_TYPE & sym.n_type;