Commit f9f792ab70

Jakub Konka <kubkon@jakubkonka.com>
2022-01-12 16:14:27
zld: fix num nlist calc when there's no dynsymtab
Handle `__DATA,.rustc` section containing `rustc` metadata - this is required to get crates like `serde_derive` link properly. Note to self: this special section has to be copied __verbatim__ from the relocatable object file - this includes preserving its size even though unpadded according the section's required alignment.
1 parent c5ee73f
Changed files (2)
src
src/link/MachO/Object.zig
@@ -409,7 +409,7 @@ pub fn parseIntoAtoms(self: *Object, allocator: Allocator, macho_file: *MachO) !
     } else blk: {
         var iundefsym: usize = sorted_all_nlists.items.len;
         while (iundefsym > 0) : (iundefsym -= 1) {
-            const nlist = sorted_all_nlists.items[iundefsym];
+            const nlist = sorted_all_nlists.items[iundefsym - 1];
             if (nlist.nlist.sect()) break;
         }
         break :blk iundefsym;
src/link/MachO.zig
@@ -141,6 +141,9 @@ objc_selrefs_section_index: ?u16 = null,
 objc_classrefs_section_index: ?u16 = null,
 objc_data_section_index: ?u16 = null,
 
+rustc_section_index: ?u16 = null,
+rustc_section_size: u64 = 0,
+
 bss_file_offset: u32 = 0,
 tlv_bss_file_offset: u32 = 0,
 
@@ -993,6 +996,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
             try self.writeAtoms();
         }
 
+        if (self.rustc_section_index) |id| {
+            const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;
+            const sect = &seg.sections.items[id];
+            sect.size = self.rustc_section_size;
+        }
         if (self.bss_section_index) |idx| {
             const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment;
             const sect = &seg.sections.items[idx];
@@ -1886,6 +1894,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
                             .seg = self.data_segment_cmd_index.?,
                             .sect = self.objc_data_section_index.?,
                         };
+                    } else if (mem.eql(u8, sectname, ".rustc")) {
+                        if (self.rustc_section_index == null) {
+                            self.rustc_section_index = try self.initSection(
+                                self.data_segment_cmd_index.?,
+                                ".rustc",
+                                sect.size,
+                                sect.@"align",
+                                .{},
+                            );
+                            // We need to preserve the section size for rustc to properly
+                            // decompress the metadata.
+                            self.rustc_section_size = sect.size;
+                        }
+
+                        break :blk .{
+                            .seg = self.data_segment_cmd_index.?,
+                            .sect = self.rustc_section_index.?,
+                        };
                     } else {
                         if (self.data_section_index == null) {
                             self.data_section_index = try self.initSection(
@@ -5212,6 +5238,7 @@ fn sortSections(self: *MachO) !void {
 
         // __DATA segment
         const indices = &[_]*?u16{
+            &self.rustc_section_index,
             &self.la_symbol_ptr_section_index,
             &self.objc_const_section_index,
             &self.objc_selrefs_section_index,