| ... | ... | @@ -3797,10 +3797,11 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De |
| 3797 | 3797 | atom.code.clearRetainingCapacity(); |
| 3798 | 3798 | try atom.code.appendSlice(self.base.allocator, code); |
| 3799 | 3799 | |
| 3800 | | const match = try self.getMatchingSectionAtom(atom, typed_value.ty, typed_value.val); |
| 3800 | const match = try self.getMatchingSectionAtom(atom, decl_name, typed_value.ty, typed_value.val); |
| 3801 | 3801 | const addr = try self.allocateAtom(atom, code.len, required_alignment, match); |
| 3802 | 3802 | |
| 3803 | 3803 | log.debug("allocated atom for {s} at 0x{x}", .{ name, addr }); |
| 3804 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 3804 | 3805 | |
| 3805 | 3806 | errdefer self.freeAtom(atom, match, true); |
| 3806 | 3807 | |
| ... | ... | @@ -3903,28 +3904,60 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3903 | 3904 | try self.updateDeclExports(module, decl, decl_exports); |
| 3904 | 3905 | } |
| 3905 | 3906 | |
| 3906 | | fn isElemTyPointer(ty: Type) bool { |
| 3907 | /// Checks if the value, or any of its embedded values stores a pointer, and thus requires |
| 3908 | /// a rebase opcode for the dynamic linker. |
| 3909 | fn needsPointerRebase(ty: Type, val: Value) bool { |
| 3910 | if (ty.zigTypeTag() == .Fn) { |
| 3911 | return false; |
| 3912 | } |
| 3913 | if (val.pointerDecl()) |_| { |
| 3914 | return true; |
| 3915 | } |
| 3916 | |
| 3907 | 3917 | switch (ty.zigTypeTag()) { |
| 3908 | | .Fn => return false, |
| 3918 | .Fn => unreachable, |
| 3909 | 3919 | .Pointer => return true, |
| 3910 | | .Array => { |
| 3911 | | const elem_ty = ty.elemType(); |
| 3912 | | return isElemTyPointer(elem_ty); |
| 3920 | .Array, .Vector => { |
| 3921 | if (ty.arrayLen() == 0) return false; |
| 3922 | const elem_ty = ty.childType(); |
| 3923 | var elem_value_buf: Value.ElemValueBuffer = undefined; |
| 3924 | const elem_val = val.elemValueBuffer(0, &elem_value_buf); |
| 3925 | return needsPointerRebase(elem_ty, elem_val); |
| 3913 | 3926 | }, |
| 3914 | | .Struct, .Union => { |
| 3915 | | const len = ty.structFieldCount(); |
| 3916 | | var i: usize = 0; |
| 3917 | | while (i < len) : (i += 1) { |
| 3918 | | const field_ty = ty.structFieldType(i); |
| 3919 | | if (isElemTyPointer(field_ty)) return true; |
| 3920 | | } |
| 3921 | | return false; |
| 3927 | .Struct => { |
| 3928 | const fields = ty.structFields().values(); |
| 3929 | if (fields.len == 0) return false; |
| 3930 | if (val.castTag(.@"struct")) |payload| { |
| 3931 | const field_values = payload.data; |
| 3932 | for (field_values) |field_val, i| { |
| 3933 | if (needsPointerRebase(fields[i].ty, field_val)) return true; |
| 3934 | } else return false; |
| 3935 | } else return false; |
| 3936 | }, |
| 3937 | .Optional => { |
| 3938 | if (val.castTag(.opt_payload)) |payload| { |
| 3939 | const sub_val = payload.data; |
| 3940 | var buffer: Type.Payload.ElemType = undefined; |
| 3941 | const sub_ty = ty.optionalChild(&buffer); |
| 3942 | return needsPointerRebase(sub_ty, sub_val); |
| 3943 | } else return false; |
| 3944 | }, |
| 3945 | .Union => { |
| 3946 | const union_obj = val.cast(Value.Payload.Union).?.data; |
| 3947 | const active_field_ty = ty.unionFieldType(union_obj.tag); |
| 3948 | return needsPointerRebase(active_field_ty, union_obj.val); |
| 3949 | }, |
| 3950 | .ErrorUnion => { |
| 3951 | if (val.castTag(.eu_payload)) |payload| { |
| 3952 | const payload_ty = ty.errorUnionPayload(); |
| 3953 | return needsPointerRebase(payload_ty, payload.data); |
| 3954 | } else return false; |
| 3922 | 3955 | }, |
| 3923 | 3956 | else => return false, |
| 3924 | 3957 | } |
| 3925 | 3958 | } |
| 3926 | 3959 | |
| 3927 | | fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !MatchingSection { |
| 3960 | fn getMatchingSectionAtom(self: *MachO, atom: *Atom, name: []const u8, ty: Type, val: Value) !MatchingSection { |
| 3928 | 3961 | const code = atom.code.items; |
| 3929 | 3962 | const alignment = ty.abiAlignment(self.base.options.target); |
| 3930 | 3963 | const align_log_2 = math.log2(alignment); |
| ... | ... | @@ -3938,10 +3971,25 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3938 | 3971 | .seg = self.data_segment_cmd_index.?, |
| 3939 | 3972 | .sect = self.bss_section_index.?, |
| 3940 | 3973 | }; |
| 3974 | } else { |
| 3975 | break :blk MatchingSection{ |
| 3976 | .seg = self.data_segment_cmd_index.?, |
| 3977 | .sect = self.data_section_index.?, |
| 3978 | }; |
| 3941 | 3979 | } |
| 3980 | } |
| 3981 | |
| 3982 | if (val.castTag(.variable)) |_| { |
| 3983 | break :blk MatchingSection{ |
| 3984 | .seg = self.data_segment_cmd_index.?, |
| 3985 | .sect = self.data_section_index.?, |
| 3986 | }; |
| 3987 | } |
| 3988 | |
| 3989 | if (needsPointerRebase(ty, val)) { |
| 3942 | 3990 | break :blk (try self.getMatchingSection(.{ |
| 3943 | | .segname = makeStaticString("__DATA"), |
| 3944 | | .sectname = makeStaticString("__data"), |
| 3991 | .segname = makeStaticString("__DATA_CONST"), |
| 3992 | .sectname = makeStaticString("__const"), |
| 3945 | 3993 | .size = code.len, |
| 3946 | 3994 | .@"align" = align_log_2, |
| 3947 | 3995 | })).?; |
| ... | ... | @@ -3954,8 +4002,8 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3954 | 4002 | .sect = self.text_section_index.?, |
| 3955 | 4003 | }; |
| 3956 | 4004 | }, |
| 3957 | | .Array => switch (val.tag()) { |
| 3958 | | .bytes => { |
| 4005 | .Array => { |
| 4006 | if (val.tag() == .bytes) { |
| 3959 | 4007 | switch (ty.tag()) { |
| 3960 | 4008 | .array_u8_sentinel_0, |
| 3961 | 4009 | .const_slice_u8_sentinel_0, |
| ... | ... | @@ -3969,79 +4017,23 @@ fn getMatchingSectionAtom(self: *MachO, atom: *Atom, ty: Type, val: Value) !Matc |
| 3969 | 4017 | .@"align" = align_log_2, |
| 3970 | 4018 | })).?; |
| 3971 | 4019 | }, |
| 3972 | | else => { |
| 3973 | | break :blk (try self.getMatchingSection(.{ |
| 3974 | | .segname = makeStaticString("__TEXT"), |
| 3975 | | .sectname = makeStaticString("__const"), |
| 3976 | | .size = code.len, |
| 3977 | | .@"align" = align_log_2, |
| 3978 | | })).?; |
| 3979 | | }, |
| 3980 | | } |
| 3981 | | }, |
| 3982 | | .array => { |
| 3983 | | if (isElemTyPointer(ty)) { |
| 3984 | | break :blk (try self.getMatchingSection(.{ |
| 3985 | | .segname = makeStaticString("__DATA_CONST"), |
| 3986 | | .sectname = makeStaticString("__const"), |
| 3987 | | .size = code.len, |
| 3988 | | .@"align" = align_log_2, |
| 3989 | | })).?; |
| 3990 | | } else { |
| 3991 | | break :blk (try self.getMatchingSection(.{ |
| 3992 | | .segname = makeStaticString("__TEXT"), |
| 3993 | | .sectname = makeStaticString("__const"), |
| 3994 | | .size = code.len, |
| 3995 | | .@"align" = align_log_2, |
| 3996 | | })).?; |
| 4020 | else => {}, |
| 3997 | 4021 | } |
| 3998 | | }, |
| 3999 | | else => { |
| 4000 | | break :blk (try self.getMatchingSection(.{ |
| 4001 | | .segname = makeStaticString("__TEXT"), |
| 4002 | | .sectname = makeStaticString("__const"), |
| 4003 | | .size = code.len, |
| 4004 | | .@"align" = align_log_2, |
| 4005 | | })).?; |
| 4006 | | }, |
| 4007 | | }, |
| 4008 | | .Pointer => { |
| 4009 | | if (val.castTag(.variable)) |_| { |
| 4010 | | break :blk MatchingSection{ |
| 4011 | | .seg = self.data_segment_cmd_index.?, |
| 4012 | | .sect = self.data_section_index.?, |
| 4013 | | }; |
| 4014 | | } else { |
| 4015 | | break :blk (try self.getMatchingSection(.{ |
| 4016 | | .segname = makeStaticString("__DATA_CONST"), |
| 4017 | | .sectname = makeStaticString("__const"), |
| 4018 | | .size = code.len, |
| 4019 | | .@"align" = align_log_2, |
| 4020 | | })).?; |
| 4021 | | } |
| 4022 | | }, |
| 4023 | | else => { |
| 4024 | | if (val.castTag(.variable)) |_| { |
| 4025 | | break :blk MatchingSection{ |
| 4026 | | .seg = self.data_segment_cmd_index.?, |
| 4027 | | .sect = self.data_section_index.?, |
| 4028 | | }; |
| 4029 | | } else { |
| 4030 | | break :blk (try self.getMatchingSection(.{ |
| 4031 | | .segname = makeStaticString("__TEXT"), |
| 4032 | | .sectname = makeStaticString("__const"), |
| 4033 | | .size = code.len, |
| 4034 | | .@"align" = align_log_2, |
| 4035 | | })).?; |
| 4036 | 4022 | } |
| 4037 | 4023 | }, |
| 4024 | else => {}, |
| 4038 | 4025 | } |
| 4026 | break :blk (try self.getMatchingSection(.{ |
| 4027 | .segname = makeStaticString("__TEXT"), |
| 4028 | .sectname = makeStaticString("__const"), |
| 4029 | .size = code.len, |
| 4030 | .@"align" = align_log_2, |
| 4031 | })).?; |
| 4039 | 4032 | }; |
| 4040 | | const local = self.locals.items[atom.local_sym_index]; |
| 4041 | 4033 | const seg = self.load_commands.items[match.seg].segment; |
| 4042 | 4034 | const sect = seg.sections.items[match.sect]; |
| 4043 | 4035 | log.debug(" allocating atom '{s}' in '{s},{s}' ({d},{d})", .{ |
| 4044 | | self.getString(local.n_strx), |
| 4036 | name, |
| 4045 | 4037 | sect.segName(), |
| 4046 | 4038 | sect.sectName(), |
| 4047 | 4039 | match.seg, |
| ... | ... | @@ -4055,13 +4047,14 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4055 | 4047 | assert(decl.link.macho.local_sym_index != 0); // Caller forgot to call allocateDeclIndexes() |
| 4056 | 4048 | const symbol = &self.locals.items[decl.link.macho.local_sym_index]; |
| 4057 | 4049 | |
| 4050 | const sym_name = try decl.getFullyQualifiedName(self.base.allocator); |
| 4051 | defer self.base.allocator.free(sym_name); |
| 4052 | |
| 4058 | 4053 | const decl_ptr = self.decls.getPtr(decl).?; |
| 4059 | 4054 | if (decl_ptr.* == null) { |
| 4060 | | decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, decl.ty, decl.val); |
| 4055 | decl_ptr.* = try self.getMatchingSectionAtom(&decl.link.macho, sym_name, decl.ty, decl.val); |
| 4061 | 4056 | } |
| 4062 | 4057 | const match = decl_ptr.*.?; |
| 4063 | | const sym_name = try decl.getFullyQualifiedName(self.base.allocator); |
| 4064 | | defer self.base.allocator.free(sym_name); |
| 4065 | 4058 | |
| 4066 | 4059 | if (decl.link.macho.size != 0) { |
| 4067 | 4060 | const capacity = decl.link.macho.capacity(self.*); |
| ... | ... | @@ -4071,6 +4064,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4071 | 4064 | const vaddr = try self.growAtom(&decl.link.macho, code_len, required_alignment, match); |
| 4072 | 4065 | |
| 4073 | 4066 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, symbol.n_value, vaddr }); |
| 4067 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 4074 | 4068 | |
| 4075 | 4069 | if (vaddr != symbol.n_value) { |
| 4076 | 4070 | log.debug(" (writing new GOT entry)", .{}); |
| ... | ... | @@ -4105,6 +4099,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 4105 | 4099 | const addr = try self.allocateAtom(&decl.link.macho, code_len, required_alignment, match); |
| 4106 | 4100 | |
| 4107 | 4101 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, addr }); |
| 4102 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 4108 | 4103 | |
| 4109 | 4104 | errdefer self.freeAtom(&decl.link.macho, match, false); |
| 4110 | 4105 | |