Commit 785bd270ed
Changed files (3)
src
link
src/link/Elf/Atom.zig
@@ -388,6 +388,12 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, undefs: anytype) !void {
elf.R_X86_64_PC32 => {},
+ elf.R_X86_64_TPOFF32,
+ elf.R_X86_64_TPOFF64,
+ => {
+ // if (is_shared) self.picError(symbol, rel, elf_file);
+ },
+
else => {
var err = try elf_file.addErrorWithNotes(1);
try err.addMsg(elf_file, "fatal linker error: unhandled relocation type {}", .{
@@ -473,9 +479,9 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
// Relative offset to the start of the global offset table.
const G = @as(i64, @intCast(target.gotAddress(elf_file))) - GOT;
// // Address of the thread pointer.
- // const TP = @as(i64, @intCast(elf_file.getTpAddress()));
+ const TP = @as(i64, @intCast(elf_file.tpAddress()));
// // Address of the dynamic thread pointer.
- // const DTP = @as(i64, @intCast(elf_file.getDtpAddress()));
+ // const DTP = @as(i64, @intCast(elf_file.dtpAddress()));
relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ({s})", .{
fmtRelocType(r_type),
@@ -522,6 +528,9 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
try cwriter.writeIntLittle(i32, @as(i32, @intCast(G + GOT + A - P)));
},
+ elf.R_X86_64_TPOFF32 => try cwriter.writeIntLittle(i32, @as(i32, @truncate(S + A - TP))),
+ elf.R_X86_64_TPOFF64 => try cwriter.writeIntLittle(i64, S + A - TP),
+
else => {},
}
}
src/link/Elf/Symbol.zig
@@ -196,9 +196,9 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
// if (symbol.flags.is_canonical) break :blk symbol.address(.{}, elf_file);
// break :blk 0;
// }
- // if (st_shndx == elf.SHN_ABS) break :blk symbol.value;
- // const shdr = &elf_file.sections.items(.shdr)[st_shndx];
- // if (Elf.shdrIsTls(shdr)) break :blk symbol.value - elf_file.getTlsAddress();
+ if (st_shndx == elf.SHN_ABS) break :blk symbol.value;
+ const shdr = &elf_file.shdrs.items[st_shndx];
+ if (shdr.sh_flags & elf.SHF_TLS != 0) break :blk symbol.value - elf_file.tlsAddress();
break :blk symbol.value;
};
out.* = .{
src/link/Elf.zig
@@ -247,7 +247,8 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
else
elf.VER_NDX_LOCAL;
- var dwarf: ?Dwarf = if (!options.strip and options.module != null)
+ const use_llvm = options.use_llvm;
+ var dwarf: ?Dwarf = if (!options.strip and options.module != null and !use_llvm)
Dwarf.init(gpa, &self.base, options.target)
else
null;
@@ -264,7 +265,6 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
.page_size = page_size,
.default_sym_version = default_sym_version,
};
- const use_llvm = options.use_llvm;
if (use_llvm and options.module != null) {
self.llvm_object = try LlvmObject.create(gpa, options);
}
@@ -643,6 +643,13 @@ pub fn populateMissingMetadata(self: *Elf) !void {
}
if (self.phdr_load_tls_zerofill_index == null) {
+ // TODO .tbss doesn't need any physical or memory representation (aka a loadable segment)
+ // since the loader only cares about the PT_TLS to work out TLS size. However, when
+ // relocating we need to have .tdata and .tbss contiguously laid out so that we can
+ // work out correct offsets to the start/end of the TLS segment. I am thinking that
+ // perhaps it's possible to completely spoof it by having an abstracted mechanism
+ // for this that wouldn't require us to explicitly track .tbss. Anyhow, for now,
+ // we go the savage route of treating .tbss like .bss.
const alignment = if (is_linux) self.page_size else @as(u16, ptr_size);
self.phdr_load_tls_zerofill_index = try self.allocateSegment(.{
.size = 0,
@@ -655,6 +662,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
}
if (self.phdr_tls_index == null) {
+ self.phdr_tls_index = @intCast(self.phdrs.items.len);
const phdr_tdata = &self.phdrs.items[self.phdr_load_tls_data_index.?];
const phdr_tbss = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?];
try self.phdrs.append(gpa, .{
@@ -1280,6 +1288,36 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
try self.allocateObjects();
self.allocateLinkerDefinedSymbols();
+ // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't
+ // get mapped by the loader
+ if (self.data_section_index) |data_shndx| blk: {
+ const bss_shndx = self.bss_section_index orelse break :blk;
+ const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?;
+ const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?;
+ self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset;
+ self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset;
+ }
+
+ // Same treatment for .tbss section.
+ if (self.tdata_section_index) |tdata_shndx| blk: {
+ const tbss_shndx = self.tbss_section_index orelse break :blk;
+ const tdata_phndx = self.phdr_to_shdr_table.get(tdata_shndx).?;
+ const tbss_phndx = self.phdr_to_shdr_table.get(tbss_shndx).?;
+ self.shdrs.items[tbss_shndx].sh_offset = self.shdrs.items[tdata_shndx].sh_offset;
+ self.phdrs.items[tbss_phndx].p_offset = self.phdrs.items[tdata_phndx].p_offset;
+ }
+
+ if (self.phdr_tls_index) |tls_index| {
+ const tdata_phdr = &self.phdrs.items[self.phdr_load_tls_data_index.?];
+ const tbss_phdr = &self.phdrs.items[self.phdr_load_tls_zerofill_index.?];
+ const phdr = &self.phdrs.items[tls_index];
+ phdr.p_offset = tdata_phdr.p_offset;
+ phdr.p_filesz = tdata_phdr.p_filesz;
+ phdr.p_vaddr = tdata_phdr.p_vaddr;
+ phdr.p_paddr = tdata_phdr.p_vaddr;
+ phdr.p_memsz = tbss_phdr.p_vaddr + tbss_phdr.p_memsz - tdata_phdr.p_vaddr;
+ }
+
// Beyond this point, everything has been allocated a virtual address and we can resolve
// the relocations, and commit objects to file.
if (self.zig_module_index) |index| {
@@ -1325,22 +1363,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
try self.updateSymtabSize();
try self.writeSymtab();
- // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't
- // get mapped by the loader
- if (self.data_section_index) |data_shndx| blk: {
- const bss_shndx = self.bss_section_index orelse break :blk;
- const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?;
- const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?;
- self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset;
- self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset;
- }
-
- // Same treatment for .tbss section.
- if (self.tdata_section_index) |tdata_shndx| blk: {
- const tbss_shndx = self.tbss_section_index orelse break :blk;
- self.shdrs.items[tbss_shndx].sh_offset = self.shdrs.items[tdata_shndx].sh_offset;
- }
-
// Dump the state for easy debugging.
// State can be dumped via `--debug-log link_state`.
if (build_options.enable_logging) {
@@ -4066,6 +4088,22 @@ pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupO
return &self.comdat_groups_owners.items[index];
}
+pub fn tpAddress(self: *Elf) u64 {
+ const index = self.phdr_tls_index orelse return 0;
+ const phdr = self.phdrs.items[index];
+ return mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align);
+}
+
+pub fn dtpAddress(self: *Elf) u64 {
+ return self.tlsAddress();
+}
+
+pub fn tlsAddress(self: *Elf) u64 {
+ const index = self.phdr_tls_index orelse return 0;
+ const phdr = self.phdrs.items[index];
+ return phdr.p_vaddr;
+}
+
const ErrorWithNotes = struct {
/// Allocated index in misc_errors array.
index: usize,