authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-07 00:22:36+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-06-07 00:22:36+02:00
log920f1dcd2784bf00350843872620f5d64085e267
tree7e231a1e2753d11d2d6aae9388488a130f3eab51
parent367e2b2fe43a2de09767ad8d5657866088b44678
parente05de31a5fa8105b09eed37c9d023501b1289cd1
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11804 from ziglang/elf-dwarf-unions

dwarf: fix incorrect type relocations for union payloads

7 files changed, 130 insertions(+), 82 deletions(-)

src/arch/arm/CodeGen.zig+1-1
...@@ -3187,7 +3187,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {...@@ -3187,7 +3187,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
3187 .macho => unreachable,3187 .macho => unreachable,
3188 else => unreachable,3188 else => unreachable,
3189 };3189 };
3190 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);3190 try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
3191 },3191 },
3192 .plan9 => {},3192 .plan9 => {},
3193 .none => {},3193 .none => {},
src/arch/riscv64/CodeGen.zig+1-1
...@@ -754,7 +754,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {...@@ -754,7 +754,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
754 .macho => unreachable,754 .macho => unreachable,
755 else => unreachable,755 else => unreachable,
756 };756 };
757 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);757 try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
758 },758 },
759 .plan9 => {},759 .plan9 => {},
760 .none => {},760 .none => {},
src/arch/sparc64/CodeGen.zig+1-1
...@@ -1550,7 +1550,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {...@@ -1550,7 +1550,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
1550 .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom,1550 .elf => &mod.declPtr(self.mod_fn.owner_decl).link.elf.dbg_info_atom,
1551 else => unreachable,1551 else => unreachable,
1552 };1552 };
1553 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);1553 try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
1554 },1554 },
1555 else => {},1555 else => {},
1556 }1556 }
src/arch/wasm/CodeGen.zig+1-1
...@@ -1050,7 +1050,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {...@@ -1050,7 +1050,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
1050 const index = dbg_info.items.len;1050 const index = dbg_info.items.len;
1051 try dbg_info.resize(index + 4);1051 try dbg_info.resize(index + 4);
1052 const atom = &self.decl.link.wasm.dbg_info_atom;1052 const atom = &self.decl.link.wasm.dbg_info_atom;
1053 try dwarf.addTypeReloc(atom, ty, @intCast(u32, index), null);1053 try dwarf.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
1054 },1054 },
1055 .plan9 => unreachable,1055 .plan9 => unreachable,
1056 .none => {},1056 .none => {},
src/arch/x86_64/CodeGen.zig+1-1
...@@ -4371,7 +4371,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {...@@ -4371,7 +4371,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
4371 .macho => &fn_owner_decl.link.macho.dbg_info_atom,4371 .macho => &fn_owner_decl.link.macho.dbg_info_atom,
4372 else => unreachable,4372 else => unreachable,
4373 };4373 };
4374 try dw.addTypeReloc(atom, ty, @intCast(u32, index), null);4374 try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index));
4375 },4375 },
4376 .plan9 => {},4376 .plan9 => {},
4377 .none => {},4377 .none => {},
src/link/Dwarf.zig+64-51
...@@ -110,13 +110,22 @@ pub const DeclState = struct {...@@ -110,13 +110,22 @@ pub const DeclState = struct {
110 });110 });
111 }111 }
112112
113 pub fn addTypeReloc(113 /// Adds local type relocation of the form: @offset => @this + addend
114 self: *DeclState,114 /// @this signifies the offset within the .debug_abbrev section of the containing atom.
115 atom: *const Atom,115 pub fn addTypeRelocLocal(self: *DeclState, atom: *const Atom, offset: u32, addend: u32) !void {
116 ty: Type,116 log.debug("{x}: @this + {x}", .{ offset, addend });
117 offset: u32,117 try self.abbrev_relocs.append(self.gpa, .{
118 addend: ?u32,118 .target = null,
119 ) !void {119 .atom = atom,
120 .offset = offset,
121 .addend = addend,
122 });
123 }
124
125 /// Adds global type relocation of the form: @offset => @symbol + 0
126 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section
127 /// which we use as our target of the relocation.
128 pub fn addTypeRelocGlobal(self: *DeclState, atom: *const Atom, ty: Type, offset: u32) !void {
120 const resolv = self.abbrev_resolver.getContext(ty, .{129 const resolv = self.abbrev_resolver.getContext(ty, .{
121 .mod = self.mod,130 .mod = self.mod,
122 }) orelse blk: {131 }) orelse blk: {
...@@ -134,14 +143,12 @@ pub const DeclState = struct {...@@ -134,14 +143,12 @@ pub const DeclState = struct {
134 .mod = self.mod,143 .mod = self.mod,
135 }).?;144 }).?;
136 };145 };
137 const add: u32 = addend orelse 0;146 log.debug("{x}: @{d} + 0", .{ offset, resolv });
138
139 log.debug("{x}: @{d} + {x}", .{ offset, resolv, add });
140 try self.abbrev_relocs.append(self.gpa, .{147 try self.abbrev_relocs.append(self.gpa, .{
141 .target = resolv,148 .target = resolv,
142 .atom = atom,149 .atom = atom,
143 .offset = offset,150 .offset = offset,
144 .addend = add,151 .addend = 0,
145 });152 });
146 }153 }
147154
...@@ -213,7 +220,7 @@ pub const DeclState = struct {...@@ -213,7 +220,7 @@ pub const DeclState = struct {
213 // DW.AT.type, DW.FORM.ref4220 // DW.AT.type, DW.FORM.ref4
214 var index = dbg_info_buffer.items.len;221 var index = dbg_info_buffer.items.len;
215 try dbg_info_buffer.resize(index + 4);222 try dbg_info_buffer.resize(index + 4);
216 try self.addTypeReloc(atom, Type.bool, @intCast(u32, index), null);223 try self.addTypeRelocGlobal(atom, Type.bool, @intCast(u32, index));
217 // DW.AT.data_member_location, DW.FORM.sdata224 // DW.AT.data_member_location, DW.FORM.sdata
218 try dbg_info_buffer.ensureUnusedCapacity(6);225 try dbg_info_buffer.ensureUnusedCapacity(6);
219 dbg_info_buffer.appendAssumeCapacity(0);226 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -225,7 +232,7 @@ pub const DeclState = struct {...@@ -225,7 +232,7 @@ pub const DeclState = struct {
225 // DW.AT.type, DW.FORM.ref4232 // DW.AT.type, DW.FORM.ref4
226 index = dbg_info_buffer.items.len;233 index = dbg_info_buffer.items.len;
227 try dbg_info_buffer.resize(index + 4);234 try dbg_info_buffer.resize(index + 4);
228 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);235 try self.addTypeRelocGlobal(atom, payload_ty, @intCast(u32, index));
229 // DW.AT.data_member_location, DW.FORM.sdata236 // DW.AT.data_member_location, DW.FORM.sdata
230 const offset = abi_size - payload_ty.abiSize(target);237 const offset = abi_size - payload_ty.abiSize(target);
231 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);238 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
...@@ -254,7 +261,7 @@ pub const DeclState = struct {...@@ -254,7 +261,7 @@ pub const DeclState = struct {
254 try dbg_info_buffer.resize(index + 4);261 try dbg_info_buffer.resize(index + 4);
255 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);262 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
256 const ptr_ty = ty.slicePtrFieldType(buf);263 const ptr_ty = ty.slicePtrFieldType(buf);
257 try self.addTypeReloc(atom, ptr_ty, @intCast(u32, index), null);264 try self.addTypeRelocGlobal(atom, ptr_ty, @intCast(u32, index));
258 // DW.AT.data_member_location, DW.FORM.sdata265 // DW.AT.data_member_location, DW.FORM.sdata
259 try dbg_info_buffer.ensureUnusedCapacity(6);266 try dbg_info_buffer.ensureUnusedCapacity(6);
260 dbg_info_buffer.appendAssumeCapacity(0);267 dbg_info_buffer.appendAssumeCapacity(0);
...@@ -266,7 +273,7 @@ pub const DeclState = struct {...@@ -266,7 +273,7 @@ pub const DeclState = struct {
266 // DW.AT.type, DW.FORM.ref4273 // DW.AT.type, DW.FORM.ref4
267 index = dbg_info_buffer.items.len;274 index = dbg_info_buffer.items.len;
268 try dbg_info_buffer.resize(index + 4);275 try dbg_info_buffer.resize(index + 4);
269 try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null);276 try self.addTypeRelocGlobal(atom, Type.usize, @intCast(u32, index));
270 // DW.AT.data_member_location, DW.FORM.sdata277 // DW.AT.data_member_location, DW.FORM.sdata
271 try dbg_info_buffer.ensureUnusedCapacity(2);278 try dbg_info_buffer.ensureUnusedCapacity(2);
272 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize));279 dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize));
...@@ -278,7 +285,7 @@ pub const DeclState = struct {...@@ -278,7 +285,7 @@ pub const DeclState = struct {
278 // DW.AT.type, DW.FORM.ref4285 // DW.AT.type, DW.FORM.ref4
279 const index = dbg_info_buffer.items.len;286 const index = dbg_info_buffer.items.len;
280 try dbg_info_buffer.resize(index + 4);287 try dbg_info_buffer.resize(index + 4);
281 try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null);288 try self.addTypeRelocGlobal(atom, ty.childType(), @intCast(u32, index));
282 }289 }
283 },290 },
284 .Array => {291 .Array => {
...@@ -289,13 +296,13 @@ pub const DeclState = struct {...@@ -289,13 +296,13 @@ pub const DeclState = struct {
289 // DW.AT.type, DW.FORM.ref4296 // DW.AT.type, DW.FORM.ref4
290 var index = dbg_info_buffer.items.len;297 var index = dbg_info_buffer.items.len;
291 try dbg_info_buffer.resize(index + 4);298 try dbg_info_buffer.resize(index + 4);
292 try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null);299 try self.addTypeRelocGlobal(atom, ty.childType(), @intCast(u32, index));
293 // DW.AT.subrange_type300 // DW.AT.subrange_type
294 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim));301 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim));
295 // DW.AT.type, DW.FORM.ref4302 // DW.AT.type, DW.FORM.ref4
296 index = dbg_info_buffer.items.len;303 index = dbg_info_buffer.items.len;
297 try dbg_info_buffer.resize(index + 4);304 try dbg_info_buffer.resize(index + 4);
298 try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null);305 try self.addTypeRelocGlobal(atom, Type.usize, @intCast(u32, index));
299 // DW.AT.count, DW.FORM.udata306 // DW.AT.count, DW.FORM.udata
300 const len = ty.arrayLenIncludingSentinel();307 const len = ty.arrayLenIncludingSentinel();
301 try leb128.writeULEB128(dbg_info_buffer.writer(), len);308 try leb128.writeULEB128(dbg_info_buffer.writer(), len);
...@@ -323,7 +330,7 @@ pub const DeclState = struct {...@@ -323,7 +330,7 @@ pub const DeclState = struct {
323 // DW.AT.type, DW.FORM.ref4330 // DW.AT.type, DW.FORM.ref4
324 var index = dbg_info_buffer.items.len;331 var index = dbg_info_buffer.items.len;
325 try dbg_info_buffer.resize(index + 4);332 try dbg_info_buffer.resize(index + 4);
326 try self.addTypeReloc(atom, field, @intCast(u32, index), null);333 try self.addTypeRelocGlobal(atom, field, @intCast(u32, index));
327 // DW.AT.data_member_location, DW.FORM.sdata334 // DW.AT.data_member_location, DW.FORM.sdata
328 const field_off = ty.structFieldOffset(field_index, target);335 const field_off = ty.structFieldOffset(field_index, target);
329 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);336 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
...@@ -354,7 +361,7 @@ pub const DeclState = struct {...@@ -354,7 +361,7 @@ pub const DeclState = struct {
354 // DW.AT.type, DW.FORM.ref4361 // DW.AT.type, DW.FORM.ref4
355 var index = dbg_info_buffer.items.len;362 var index = dbg_info_buffer.items.len;
356 try dbg_info_buffer.resize(index + 4);363 try dbg_info_buffer.resize(index + 4);
357 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);364 try self.addTypeRelocGlobal(atom, field.ty, @intCast(u32, index));
358 // DW.AT.data_member_location, DW.FORM.sdata365 // DW.AT.data_member_location, DW.FORM.sdata
359 const field_off = ty.structFieldOffset(field_index, target);366 const field_off = ty.structFieldOffset(field_index, target);
360 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);367 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
...@@ -434,7 +441,7 @@ pub const DeclState = struct {...@@ -434,7 +441,7 @@ pub const DeclState = struct {
434 // DW.AT.type, DW.FORM.ref4441 // DW.AT.type, DW.FORM.ref4
435 const inner_union_index = dbg_info_buffer.items.len;442 const inner_union_index = dbg_info_buffer.items.len;
436 try dbg_info_buffer.resize(inner_union_index + 4);443 try dbg_info_buffer.resize(inner_union_index + 4);
437 try self.addTypeReloc(atom, ty, @intCast(u32, inner_union_index), 5);444 try self.addTypeRelocLocal(atom, @intCast(u32, inner_union_index), 5);
438 // DW.AT.data_member_location, DW.FORM.sdata445 // DW.AT.data_member_location, DW.FORM.sdata
439 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);446 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
440 }447 }
...@@ -461,7 +468,7 @@ pub const DeclState = struct {...@@ -461,7 +468,7 @@ pub const DeclState = struct {
461 // DW.AT.type, DW.FORM.ref4468 // DW.AT.type, DW.FORM.ref4
462 const index = dbg_info_buffer.items.len;469 const index = dbg_info_buffer.items.len;
463 try dbg_info_buffer.resize(index + 4);470 try dbg_info_buffer.resize(index + 4);
464 try self.addTypeReloc(atom, field.ty, @intCast(u32, index), null);471 try self.addTypeRelocGlobal(atom, field.ty, @intCast(u32, index));
465 // DW.AT.data_member_location, DW.FORM.sdata472 // DW.AT.data_member_location, DW.FORM.sdata
466 try dbg_info_buffer.append(0);473 try dbg_info_buffer.append(0);
467 }474 }
...@@ -478,7 +485,7 @@ pub const DeclState = struct {...@@ -478,7 +485,7 @@ pub const DeclState = struct {
478 // DW.AT.type, DW.FORM.ref4485 // DW.AT.type, DW.FORM.ref4
479 const index = dbg_info_buffer.items.len;486 const index = dbg_info_buffer.items.len;
480 try dbg_info_buffer.resize(index + 4);487 try dbg_info_buffer.resize(index + 4);
481 try self.addTypeReloc(atom, union_obj.tag_ty, @intCast(u32, index), null);488 try self.addTypeRelocGlobal(atom, union_obj.tag_ty, @intCast(u32, index));
482 // DW.AT.data_member_location, DW.FORM.sdata489 // DW.AT.data_member_location, DW.FORM.sdata
483 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);490 try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
484491
...@@ -521,7 +528,7 @@ pub const DeclState = struct {...@@ -521,7 +528,7 @@ pub const DeclState = struct {
521 // DW.AT.type, DW.FORM.ref4528 // DW.AT.type, DW.FORM.ref4
522 var index = dbg_info_buffer.items.len;529 var index = dbg_info_buffer.items.len;
523 try dbg_info_buffer.resize(index + 4);530 try dbg_info_buffer.resize(index + 4);
524 try self.addTypeReloc(atom, payload_ty, @intCast(u32, index), null);531 try self.addTypeRelocGlobal(atom, payload_ty, @intCast(u32, index));
525 // DW.AT.data_member_location, DW.FORM.sdata532 // DW.AT.data_member_location, DW.FORM.sdata
526 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);533 try leb128.writeULEB128(dbg_info_buffer.writer(), payload_off);
527534
...@@ -534,7 +541,7 @@ pub const DeclState = struct {...@@ -534,7 +541,7 @@ pub const DeclState = struct {
534 // DW.AT.type, DW.FORM.ref4541 // DW.AT.type, DW.FORM.ref4
535 index = dbg_info_buffer.items.len;542 index = dbg_info_buffer.items.len;
536 try dbg_info_buffer.resize(index + 4);543 try dbg_info_buffer.resize(index + 4);
537 try self.addTypeReloc(atom, error_ty, @intCast(u32, index), null);544 try self.addTypeRelocGlobal(atom, error_ty, @intCast(u32, index));
538 // DW.AT.data_member_location, DW.FORM.sdata545 // DW.AT.data_member_location, DW.FORM.sdata
539 try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);546 try leb128.writeULEB128(dbg_info_buffer.writer(), error_off);
540547
...@@ -556,7 +563,9 @@ pub const AbbrevEntry = struct {...@@ -556,7 +563,9 @@ pub const AbbrevEntry = struct {
556};563};
557564
558pub const AbbrevRelocation = struct {565pub const AbbrevRelocation = struct {
559 target: u32,566 /// If target is null, we deal with a local relocation that is based on simple offset + addend
567 /// only.
568 target: ?u32,
560 atom: *const Atom,569 atom: *const Atom,
561 offset: u32,570 offset: u32,
562 addend: u32,571 addend: u32,
...@@ -740,12 +749,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState...@@ -740,12 +749,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl: *Module.Decl) !DeclState
740 .wasm => &decl.link.wasm.dbg_info_atom,749 .wasm => &decl.link.wasm.dbg_info_atom,
741 else => unreachable,750 else => unreachable,
742 };751 };
743 try decl_state.addTypeReloc(752 try decl_state.addTypeRelocGlobal(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len));
744 atom,
745 fn_ret_type,
746 @intCast(u32, dbg_info_buffer.items.len),
747 null,
748 );
749 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4753 dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
750 }754 }
751755
...@@ -1036,30 +1040,39 @@ pub fn commitDeclState(...@@ -1036,30 +1040,39 @@ pub fn commitDeclState(
1036 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));1040 try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
10371041
1038 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {1042 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
1039 const symbol = decl_state.abbrev_table.items[reloc.target];1043 if (reloc.target) |target| {
1040 const ty = symbol.@"type";1044 const symbol = decl_state.abbrev_table.items[target];
1041 const deferred: bool = blk: {1045 const ty = symbol.@"type";
1042 if (ty.isAnyError()) break :blk true;1046 const deferred: bool = blk: {
1043 switch (ty.tag()) {1047 if (ty.isAnyError()) break :blk true;
1044 .error_set_inferred => {1048 switch (ty.tag()) {
1045 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;1049 .error_set_inferred => {
1046 },1050 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
1047 else => {},1051 },
1052 else => {},
1053 }
1054 break :blk false;
1055 };
1056 if (deferred) {
1057 try self.global_abbrev_relocs.append(gpa, .{
1058 .target = null,
1059 .offset = reloc.offset,
1060 .atom = reloc.atom,
1061 .addend = reloc.addend,
1062 });
1063 } else {
1064 mem.writeInt(
1065 u32,
1066 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
1067 symbol.atom.off + symbol.offset + reloc.addend,
1068 target_endian,
1069 );
1048 }1070 }
1049 break :blk false;
1050 };
1051 if (deferred) {
1052 try self.global_abbrev_relocs.append(gpa, .{
1053 .target = undefined,
1054 .offset = reloc.offset,
1055 .atom = reloc.atom,
1056 .addend = reloc.addend,
1057 });
1058 } else {1071 } else {
1059 mem.writeInt(1072 mem.writeInt(
1060 u32,1073 u32,
1061 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],1074 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
1062 symbol.atom.off + symbol.offset + reloc.addend,1075 reloc.atom.off + reloc.offset + reloc.addend,
1063 target_endian,1076 target_endian,
1064 );1077 );
1065 }1078 }
src/link/Elf.zig+61-26
...@@ -497,7 +497,7 @@ fn makeString(self: *Elf, bytes: []const u8) !u32 {...@@ -497,7 +497,7 @@ fn makeString(self: *Elf, bytes: []const u8) !u32 {
497 return @intCast(u32, result);497 return @intCast(u32, result);
498}498}
499499
500fn getString(self: *Elf, str_off: u32) []const u8 {500fn getString(self: Elf, str_off: u32) []const u8 {
501 assert(str_off < self.shstrtab.items.len);501 assert(str_off < self.shstrtab.items.len);
502 return mem.sliceTo(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off), 0);502 return mem.sliceTo(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off), 0);
503}503}
...@@ -1015,6 +1015,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1015,6 +1015,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1015 // mixing local and global symbols within a symbol table.1015 // mixing local and global symbols within a symbol table.
1016 try self.writeAllGlobalSymbols();1016 try self.writeAllGlobalSymbols();
10171017
1018 if (build_options.enable_logging) {
1019 self.logSymtab();
1020 }
1021
1018 if (self.dwarf) |*dw| {1022 if (self.dwarf) |*dw| {
1019 if (self.debug_abbrev_section_dirty) {1023 if (self.debug_abbrev_section_dirty) {
1020 try dw.writeDbgAbbrev(&self.base);1024 try dw.writeDbgAbbrev(&self.base);
...@@ -1167,7 +1171,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1167,7 +1171,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11671171
1168 for (buf) |*shdr, i| {1172 for (buf) |*shdr, i| {
1169 shdr.* = sectHeaderTo32(self.sections.items[i]);1173 shdr.* = sectHeaderTo32(self.sections.items[i]);
1170 log.debug("writing section {}", .{shdr.*});1174 log.debug("writing section {s}: {}", .{ self.getString(shdr.sh_name), shdr.* });
1171 if (foreign_endian) {1175 if (foreign_endian) {
1172 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);1176 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
1173 }1177 }
...@@ -1180,7 +1184,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1180,7 +1184,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11801184
1181 for (buf) |*shdr, i| {1185 for (buf) |*shdr, i| {
1182 shdr.* = self.sections.items[i];1186 shdr.* = self.sections.items[i];
1183 log.debug("writing section {}", .{shdr.*});1187 log.debug("writing section {s}: {}", .{ self.getString(shdr.sh_name), shdr.* });
1184 if (foreign_endian) {1188 if (foreign_endian) {
1185 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);1189 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
1186 }1190 }
...@@ -2794,8 +2798,14 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -2794,8 +2798,14 @@ fn writeSymbol(self: *Elf, index: usize) !void {
2794 if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {2798 if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {
2795 // Move all the symbols to a new file location.2799 // Move all the symbols to a new file location.
2796 const new_offset = self.findFreeSpace(needed_size, sym_align);2800 const new_offset = self.findFreeSpace(needed_size, sym_align);
2801 log.debug("moving '.symtab' from 0x{x} to 0x{x}", .{ syms_sect.sh_offset, new_offset });
2797 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;2802 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;
2798 const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size);2803 const amt = try self.base.file.?.copyRangeAll(
2804 syms_sect.sh_offset,
2805 self.base.file.?,
2806 new_offset,
2807 existing_size,
2808 );
2799 if (amt != existing_size) return error.InputOutput;2809 if (amt != existing_size) return error.InputOutput;
2800 syms_sect.sh_offset = new_offset;2810 syms_sect.sh_offset = new_offset;
2801 }2811 }
...@@ -2804,30 +2814,35 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -2804,30 +2814,35 @@ fn writeSymbol(self: *Elf, index: usize) !void {
2804 self.shdr_table_dirty = true; // TODO look into only writing one section2814 self.shdr_table_dirty = true; // TODO look into only writing one section
2805 }2815 }
2806 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();2816 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
2817 const off = switch (self.ptr_width) {
2818 .p32 => syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index,
2819 .p64 => syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index,
2820 };
2821 const local = self.local_symbols.items[index];
2822 log.debug("writing symbol {d}, '{s}' at 0x{x}", .{ index, self.getString(local.st_name), off });
2823 log.debug(" ({})", .{local});
2807 switch (self.ptr_width) {2824 switch (self.ptr_width) {
2808 .p32 => {2825 .p32 => {
2809 var sym = [1]elf.Elf32_Sym{2826 var sym = [1]elf.Elf32_Sym{
2810 .{2827 .{
2811 .st_name = self.local_symbols.items[index].st_name,2828 .st_name = local.st_name,
2812 .st_value = @intCast(u32, self.local_symbols.items[index].st_value),2829 .st_value = @intCast(u32, local.st_value),
2813 .st_size = @intCast(u32, self.local_symbols.items[index].st_size),2830 .st_size = @intCast(u32, local.st_size),
2814 .st_info = self.local_symbols.items[index].st_info,2831 .st_info = local.st_info,
2815 .st_other = self.local_symbols.items[index].st_other,2832 .st_other = local.st_other,
2816 .st_shndx = self.local_symbols.items[index].st_shndx,2833 .st_shndx = local.st_shndx,
2817 },2834 },
2818 };2835 };
2819 if (foreign_endian) {2836 if (foreign_endian) {
2820 mem.byteSwapAllFields(elf.Elf32_Sym, &sym[0]);2837 mem.byteSwapAllFields(elf.Elf32_Sym, &sym[0]);
2821 }2838 }
2822 const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index;
2823 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);2839 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
2824 },2840 },
2825 .p64 => {2841 .p64 => {
2826 var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]};2842 var sym = [1]elf.Elf64_Sym{local};
2827 if (foreign_endian) {2843 if (foreign_endian) {
2828 mem.byteSwapAllFields(elf.Elf64_Sym, &sym[0]);2844 mem.byteSwapAllFields(elf.Elf64_Sym, &sym[0]);
2829 }2845 }
2830 const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index;
2831 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);2846 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
2832 },2847 },
2833 }2848 }
...@@ -2847,8 +2862,14 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2847,8 +2862,14 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
2847 if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {2862 if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {
2848 // Move all the symbols to a new file location.2863 // Move all the symbols to a new file location.
2849 const new_offset = self.findFreeSpace(needed_size, sym_align);2864 const new_offset = self.findFreeSpace(needed_size, sym_align);
2865 log.debug("moving '.symtab' from 0x{x} to 0x{x}", .{ syms_sect.sh_offset, new_offset });
2850 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;2866 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;
2851 const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size);2867 const amt = try self.base.file.?.copyRangeAll(
2868 syms_sect.sh_offset,
2869 self.base.file.?,
2870 new_offset,
2871 existing_size,
2872 );
2852 if (amt != existing_size) return error.InputOutput;2873 if (amt != existing_size) return error.InputOutput;
2853 syms_sect.sh_offset = new_offset;2874 syms_sect.sh_offset = new_offset;
2854 }2875 }
...@@ -2857,19 +2878,21 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2857,19 +2878,21 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
28572878
2858 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();2879 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
2859 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;2880 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
2881 log.debug("writing {d} global symbols at 0x{x}", .{ self.global_symbols.items.len, global_syms_off });
2860 switch (self.ptr_width) {2882 switch (self.ptr_width) {
2861 .p32 => {2883 .p32 => {
2862 const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len);2884 const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len);
2863 defer self.base.allocator.free(buf);2885 defer self.base.allocator.free(buf);
28642886
2865 for (buf) |*sym, i| {2887 for (buf) |*sym, i| {
2888 const global = self.global_symbols.items[i];
2866 sym.* = .{2889 sym.* = .{
2867 .st_name = self.global_symbols.items[i].st_name,2890 .st_name = global.st_name,
2868 .st_value = @intCast(u32, self.global_symbols.items[i].st_value),2891 .st_value = @intCast(u32, global.st_value),
2869 .st_size = @intCast(u32, self.global_symbols.items[i].st_size),2892 .st_size = @intCast(u32, global.st_size),
2870 .st_info = self.global_symbols.items[i].st_info,2893 .st_info = global.st_info,
2871 .st_other = self.global_symbols.items[i].st_other,2894 .st_other = global.st_other,
2872 .st_shndx = self.global_symbols.items[i].st_shndx,2895 .st_shndx = global.st_shndx,
2873 };2896 };
2874 if (foreign_endian) {2897 if (foreign_endian) {
2875 mem.byteSwapAllFields(elf.Elf32_Sym, sym);2898 mem.byteSwapAllFields(elf.Elf32_Sym, sym);
...@@ -2882,13 +2905,14 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2882,13 +2905,14 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
2882 defer self.base.allocator.free(buf);2905 defer self.base.allocator.free(buf);
28832906
2884 for (buf) |*sym, i| {2907 for (buf) |*sym, i| {
2908 const global = self.global_symbols.items[i];
2885 sym.* = .{2909 sym.* = .{
2886 .st_name = self.global_symbols.items[i].st_name,2910 .st_name = global.st_name,
2887 .st_value = self.global_symbols.items[i].st_value,2911 .st_value = global.st_value,
2888 .st_size = self.global_symbols.items[i].st_size,2912 .st_size = global.st_size,
2889 .st_info = self.global_symbols.items[i].st_info,2913 .st_info = global.st_info,
2890 .st_other = self.global_symbols.items[i].st_other,2914 .st_other = global.st_other,
2891 .st_shndx = self.global_symbols.items[i].st_shndx,2915 .st_shndx = global.st_shndx,
2892 };2916 };
2893 if (foreign_endian) {2917 if (foreign_endian) {
2894 mem.byteSwapAllFields(elf.Elf64_Sym, sym);2918 mem.byteSwapAllFields(elf.Elf64_Sym, sym);
...@@ -3194,3 +3218,14 @@ const CsuObjects = struct {...@@ -3194,3 +3218,14 @@ const CsuObjects = struct {
3194 self.crtn = crtn;3218 self.crtn = crtn;
3195 }3219 }
3196};3220};
3221
3222fn logSymtab(self: Elf) void {
3223 log.debug("locals:", .{});
3224 for (self.local_symbols.items) |sym, id| {
3225 log.debug(" {d}: {s}: @{x} in {d}", .{ id, self.getString(sym.st_name), sym.st_value, sym.st_shndx });
3226 }
3227 log.debug("globals:", .{});
3228 for (self.global_symbols.items) |sym, id| {
3229 log.debug(" {d}: {s}: @{x} in {d}", .{ id, self.getString(sym.st_name), sym.st_value, sym.st_shndx });
3230 }
3231}