authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-18 12:56:27+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:41+01:00
loga6ed54ea2243bd9053333c09da6de5324c799b47
tree82a03e0e828f0575e028821a847c5754716f159f
parent8c578ba02ccff63a64093b5acdefcf7b95cc8c46

macho: init metadata for incremental linking


2 files changed, 115 insertions(+), 22 deletions(-)

src/link/MachO.zig+113-20
...@@ -85,15 +85,17 @@ unwind_info: UnwindInfo = .{},...@@ -85,15 +85,17 @@ unwind_info: UnwindInfo = .{},
8585
86/// Tracked loadable segments during incremental linking.86/// Tracked loadable segments during incremental linking.
87zig_text_seg_index: ?u8 = null,87zig_text_seg_index: ?u8 = null,
88zig_data_const_seg_index: ?u8 = null,88zig_got_seg_index: ?u8 = null,
89zig_const_seg_index: ?u8 = null,
89zig_data_seg_index: ?u8 = null,90zig_data_seg_index: ?u8 = null,
91zig_bss_seg_index: ?u8 = null,
9092
91/// Tracked section headers with incremental updates to Zig object.93/// Tracked section headers with incremental updates to Zig object.
92zig_text_section_index: ?u8 = null,94zig_text_section_index: ?u8 = null,
93zig_data_const_section_index: ?u8 = null,95zig_got_section_index: ?u8 = null,
96zig_const_section_index: ?u8 = null,
94zig_data_section_index: ?u8 = null,97zig_data_section_index: ?u8 = null,
95zig_bss_section_index: ?u8 = null,98zig_bss_section_index: ?u8 = null,
96zig_got_section_index: ?u8 = null,
9799
98has_tlv: bool = false,100has_tlv: bool = false,
99binds_to_weak: bool = false,101binds_to_weak: bool = false,
...@@ -252,6 +254,8 @@ pub fn createEmpty(...@@ -252,6 +254,8 @@ pub fn createEmpty(
252 .program_code_size_hint = options.program_code_size_hint,254 .program_code_size_hint = options.program_code_size_hint,
253 });255 });
254256
257 std.debug.print("{}", .{self.dumpState()});
258
255 // TODO init dwarf259 // TODO init dwarf
256260
257 // if (comp.config.debug_format != .strip) {261 // if (comp.config.debug_format != .strip) {
...@@ -3082,33 +3086,45 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {...@@ -3082,33 +3086,45 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
3082}3086}
30833087
3084fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {3088fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
3085 // TODO: header and load commands have to be part of the __TEXT segment3089 // Conservatively commit one page size as reserved space for the headers as we
3086 const header_size = self.segments.items[self.header_segment_cmd_index.?].filesize;3090 // expect it to grow and everything else be moved in flush anyhow.
3091 const header_size = self.getPageSize();
3087 if (start < header_size)3092 if (start < header_size)
3088 return header_size;3093 return header_size;
30893094
3090 const end = start + padToIdeal(size);3095 const end = start + padToIdeal(size);
30913096
3092 for (self.sections.items(.header)) |header| {3097 for (self.sections.items(.header)) |header| {
3093 const tight_size = header.size;3098 if (header.isZerofill()) continue;
3094 const increased_size = padToIdeal(tight_size);3099 const increased_size = padToIdeal(header.size);
3095 const test_end = header.offset + increased_size;3100 const test_end = header.offset + increased_size;
3096 if (end > header.offset and start < test_end) {3101 if (end > header.offset and start < test_end) {
3097 return test_end;3102 return test_end;
3098 }3103 }
3099 }3104 }
31003105
3106 for (self.segments.items) |seg| {
3107 const increased_size = padToIdeal(seg.filesize);
3108 const test_end = seg.fileoff +| increased_size;
3109 if (end > seg.fileoff and start < test_end) {
3110 return test_end;
3111 }
3112 }
3113
3101 return null;3114 return null;
3102}3115}
31033116
3104fn allocatedSize(self: *MachO, start: u64) u64 {3117fn allocatedSize(self: *MachO, start: u64) u64 {
3105 if (start == 0)3118 if (start == 0) return 0;
3106 return 0;
3107 var min_pos: u64 = std.math.maxInt(u64);3119 var min_pos: u64 = std.math.maxInt(u64);
3108 for (self.sections.items(.header)) |header| {3120 for (self.sections.items(.header)) |header| {
3109 if (header.offset <= start) continue;3121 if (header.offset <= start) continue;
3110 if (header.offset < min_pos) min_pos = header.offset;3122 if (header.offset < min_pos) min_pos = header.offset;
3111 }3123 }
3124 for (self.segments.items) |seg| {
3125 if (seg.fileoff <= start) continue;
3126 if (seg.fileoff < min_pos) min_pos = seg.fileoff;
3127 }
3112 return min_pos - start;3128 return min_pos - start;
3113}3129}
31143130
...@@ -3126,36 +3142,113 @@ const InitMetadataOptions = struct {...@@ -3126,36 +3142,113 @@ const InitMetadataOptions = struct {
3126};3142};
31273143
3128// TODO: move to ZigObject3144// TODO: move to ZigObject
3129// TODO: bring back pre-alloc of segments/sections
3130fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {3145fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3131 _ = options;
3132
3133 if (!self.base.isRelocatable()) {3146 if (!self.base.isRelocatable()) {
3134 // TODO: If we are not emitting a relocatable object file, init segments.3147 const base_vmaddr = blk: {
3135 }3148 const pagezero_size = self.pagezero_size orelse default_pagezero_size;
3149 break :blk mem.alignBackward(u64, pagezero_size, self.getPageSize());
3150 };
3151
3152 {
3153 const filesize = options.program_code_size_hint;
3154 const off = self.findFreeSpace(filesize, self.getPageSize());
3155 self.zig_text_seg_index = try self.addSegment("__TEXT_ZIG", .{
3156 .fileoff = off,
3157 .filesize = filesize,
3158 .vmaddr = base_vmaddr + 0x8000000,
3159 .vmsize = filesize,
3160 .prot = macho.PROT.READ | macho.PROT.EXEC,
3161 });
3162 }
3163
3164 {
3165 const filesize = options.symbol_count_hint * @sizeOf(u64);
3166 const off = self.findFreeSpace(filesize, self.getPageSize());
3167 self.zig_got_seg_index = try self.addSegment("__GOT_ZIG", .{
3168 .fileoff = off,
3169 .filesize = filesize,
3170 .vmaddr = base_vmaddr + 0x4000000,
3171 .vmsize = filesize,
3172 .prot = macho.PROT.READ | macho.PROT.WRITE,
3173 });
3174 }
3175
3176 {
3177 const filesize: u64 = 1024;
3178 const off = self.findFreeSpace(filesize, self.getPageSize());
3179 self.zig_const_seg_index = try self.addSegment("__CONST_ZIG", .{
3180 .fileoff = off,
3181 .filesize = filesize,
3182 .vmaddr = base_vmaddr + 0xc000000,
3183 .vmsize = filesize,
3184 .prot = macho.PROT.READ | macho.PROT.WRITE,
3185 });
3186 }
3187
3188 {
3189 const filesize: u64 = 1024;
3190 const off = self.findFreeSpace(filesize, self.getPageSize());
3191 self.zig_data_seg_index = try self.addSegment("__DATA_ZIG", .{
3192 .fileoff = off,
3193 .filesize = filesize,
3194 .vmaddr = base_vmaddr + 0x10000000,
3195 .vmsize = filesize,
3196 .prot = macho.PROT.READ | macho.PROT.WRITE,
3197 });
3198 }
3199
3200 {
3201 const memsize: u64 = 1024;
3202 self.zig_bss_seg_index = try self.addSegment("__BSS_ZIG", .{
3203 .vmaddr = base_vmaddr + 0x14000000,
3204 .vmsize = memsize,
3205 .prot = macho.PROT.READ | macho.PROT.WRITE,
3206 });
3207 }
3208 } else {
3209 @panic("TODO initMetadata when relocatable");
3210 }
3211
3212 const appendSect = struct {
3213 fn appendSect(macho_file: *MachO, sect_id: u8, seg_id: u8) void {
3214 const sect = &macho_file.sections.items(.header)[sect_id];
3215 const seg = &macho_file.segments.items[seg_id];
3216 seg.cmdsize += @sizeOf(macho.section_64);
3217 seg.nsects += 1;
3218 sect.addr = seg.vmaddr;
3219 sect.offset = @intCast(seg.fileoff);
3220 sect.size = seg.vmsize;
3221 macho_file.sections.items(.segment_id)[sect_id] = seg_id;
3222 }
3223 }.appendSect;
31363224
3137 if (self.zig_text_section_index == null) {3225 if (self.zig_text_section_index == null) {
3138 self.zig_text_section_index = try self.addSection("__TEXT", "__text", .{3226 self.zig_text_section_index = try self.addSection("__TEXT_ZIG", "__text_zig", .{
3139 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,3227 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3140 });3228 });
3229 appendSect(self, self.zig_text_section_index.?, self.zig_text_seg_index.?);
3141 }3230 }
31423231
3143 if (self.zig_got_section_index == null and !self.base.isRelocatable()) {3232 if (self.zig_got_section_index == null and !self.base.isRelocatable()) {
3144 self.zig_got_section_index = try self.addSection("__DATA_CONST", "__got_zig", .{});3233 self.zig_got_section_index = try self.addSection("__GOT_ZIG", "__got_zig", .{});
3234 appendSect(self, self.zig_got_section_index.?, self.zig_got_seg_index.?);
3145 }3235 }
31463236
3147 if (self.zig_data_const_section_index == null) {3237 if (self.zig_const_section_index == null) {
3148 self.zig_data_const_section_index = try self.addSection("__DATA_CONST", "__const", .{});3238 self.zig_const_section_index = try self.addSection("__CONST_ZIG", "__const_zig", .{});
3239 appendSect(self, self.zig_const_section_index.?, self.zig_const_seg_index.?);
3149 }3240 }
31503241
3151 if (self.zig_data_section_index == null) {3242 if (self.zig_data_section_index == null) {
3152 self.zig_data_section_index = try self.addSection("__DATA", "__data", .{});3243 self.zig_data_section_index = try self.addSection("__DATA_ZIG", "__data_zig", .{});
3244 appendSect(self, self.zig_data_section_index.?, self.zig_data_seg_index.?);
3153 }3245 }
31543246
3155 if (self.zig_bss_section_index == null) {3247 if (self.zig_bss_section_index == null) {
3156 self.zig_bss_section_index = try self.addSection("__DATA", "_bss", .{3248 self.zig_bss_section_index = try self.addSection("__BSS_ZIG", "__bss_zig", .{
3157 .flags = macho.S_ZEROFILL,3249 .flags = macho.S_ZEROFILL,
3158 });3250 });
3251 appendSect(self, self.zig_bss_section_index.?, self.zig_bss_seg_index.?);
3159 }3252 }
3160}3253}
31613254
src/link/MachO/ZigObject.zig+2-2
...@@ -478,7 +478,7 @@ fn getDeclOutputSection(...@@ -478,7 +478,7 @@ fn getDeclOutputSection(
478 );478 );
479 }479 }
480480
481 if (variable.is_const) break :blk macho_file.zig_data_const_section_index.?;481 if (variable.is_const) break :blk macho_file.zig_const_section_index.?;
482 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {482 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
483 // TODO: get the optimize_mode from the Module that owns the decl instead483 // TODO: get the optimize_mode from the Module that owns the decl instead
484 // of using the root module here.484 // of using the root module here.
...@@ -496,7 +496,7 @@ fn getDeclOutputSection(...@@ -496,7 +496,7 @@ fn getDeclOutputSection(
496 if (is_all_zeroes) break :blk macho_file.zig_bss_section_index.?;496 if (is_all_zeroes) break :blk macho_file.zig_bss_section_index.?;
497 break :blk macho_file.zig_data_section_index.?;497 break :blk macho_file.zig_data_section_index.?;
498 }498 }
499 break :blk macho_file.zig_data_const_section_index.?;499 break :blk macho_file.zig_const_section_index.?;
500 },500 },
501 };501 };
502 return sect_id;502 return sect_id;