Skip to content

Commit

Permalink
elf: emit GOTTP placeholders in GOT
Browse files Browse the repository at this point in the history
  • Loading branch information
kubkon committed Jul 12, 2023
1 parent 1c05728 commit 12544e5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,10 @@ fn scanRelocs(self: *Elf) !void {
log.debug("'{s}' needs TLSGD", .{symbol.getName(self)});
try self.got.addTlsGdSymbol(index, self);
}
if (symbol.flags.gottp) {
log.debug("'{s}' needs GOTTP", .{symbol.getName(self)});
try self.got.addGotTpSymbol(index, self);
}
}

if (self.needs_tlsld) {
Expand Down
12 changes: 8 additions & 4 deletions src/Elf/Atom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf) !void {
break :blk true;
};
if (!should_relax) {
@panic("TODO");
symbol.flags.gottp = true;
}
},

Expand Down Expand Up @@ -585,9 +585,13 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, writer: anytype) !void {
elf.R_X86_64_DTPOFF64 => try cwriter.writeIntLittle(i64, S + A - DTP),

elf.R_X86_64_GOTTPOFF => {
relaxGotTpOff(code[rel.r_offset - 3 ..]) catch
elf_file.base.fatal("TODO could not rewrite GOTTPOFF", .{});
try cwriter.writeIntLittle(i32, @as(i32, @intCast(S - TP)));
if (target.flags.gottp) {
const S_ = @as(i64, @intCast(target.getGotTpAddress(elf_file)));
try cwriter.writeIntLittle(i32, @as(i32, @intCast(S_ + A - P)));
} else {
try relaxGotTpOff(code[rel.r_offset - 3 ..]);
try cwriter.writeIntLittle(i32, @as(i32, @intCast(S - TP)));
}
},

elf.R_X86_64_TLSGD => {
Expand Down
12 changes: 11 additions & 1 deletion src/Elf/Symbol.zig
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,18 @@ pub fn getGotAddress(symbol: Symbol, elf_file: *Elf) u64 {
return elf_file.getGotEntryAddress(extra.got);
}

pub inline fn getTlsGdAddress(symbol: Symbol, elf_file: *Elf) u64 {
pub fn getTlsGdAddress(symbol: Symbol, elf_file: *Elf) u64 {
if (!symbol.flags.tlsgd) return 0;
const extra = symbol.getExtra(elf_file).?;
return elf_file.getGotEntryAddress(extra.tlsgd);
}

pub fn getGotTpAddress(symbol: Symbol, elf_file: *Elf) u64 {
if (!symbol.flags.gottp) return 0;
const extra = symbol.getExtra(elf_file).?;
return elf_file.getGotEntryAddress(extra.gottp);
}

pub fn getAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
const file = symbol.getFile(elf_file) orelse return 0;
const shared = file.shared;
Expand Down Expand Up @@ -286,6 +292,9 @@ pub const Flags = packed struct {

/// Whether the symbol contains TLSGD indirection.
tlsgd: bool = false,

/// Whether the symbol contains GOTTP indirection.
gottp: bool = false,
};

pub const Extra = struct {
Expand All @@ -295,6 +304,7 @@ pub const Extra = struct {
dynamic: u32 = 0,
copy_rel: u32 = 0,
tlsgd: u32 = 0,
gottp: u32 = 0,
};

const std = @import("std");
Expand Down
51 changes: 49 additions & 2 deletions src/Elf/synthetic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ pub const GotSection = struct {
const GotSymbol = union(enum) {
got: u32,
tlsgd: u32,
gottp: u32,

pub inline fn getIndex(gt: GotSymbol) u32 {
return switch (gt) {
Expand Down Expand Up @@ -617,10 +618,22 @@ pub const GotSection = struct {
got.next_index += 2;
}

pub fn addGotTpSymbol(got: *GotSection, sym_index: u32, elf_file: *Elf) !void {
const index = got.next_index;
const symbol = elf_file.getSymbol(sym_index);
if (symbol.getExtra(elf_file)) |extra| {
var new_extra = extra;
new_extra.gottp = index;
symbol.setExtra(new_extra, elf_file);
} else try symbol.addExtra(.{ .gottp = index }, elf_file);
try got.symbols.append(elf_file.base.allocator, .{ .gottp = sym_index });
got.next_index += 1;
}

pub fn size(got: GotSection) usize {
var s: usize = 0;
for (got.symbols.items) |sym| switch (sym) {
.got => s += 8,
.got, .gottp => s += 8,
.tlsgd => s += 16,
};
if (got.emit_tlsld) s += 8;
Expand All @@ -646,6 +659,15 @@ pub const GotSection = struct {
try writer.writeIntLittle(u64, symbol.getAddress(.{}, elf_file) - elf_file.getDtpAddress());
}
},
.gottp => {
if (symbol.flags.import) {
try writer.writeIntLittle(u64, 0);
} else if (is_shared) {
try writer.writeIntLittle(u64, symbol.getAddress(.{}, elf_file) - elf_file.getTlsAddress());
} else {
try writer.writeIntLittle(u64, symbol.getAddress(.{}, elf_file) - elf_file.getTpAddress());
}
},
}
}

Expand Down Expand Up @@ -692,6 +714,7 @@ pub const GotSection = struct {
});
}
},

.tlsgd => {
const offset = symbol.getTlsGdAddress(elf_file);

Expand All @@ -714,6 +737,24 @@ pub const GotSection = struct {
});
}
},

.gottp => {
const offset = symbol.getGotTpAddress(elf_file);

if (symbol.flags.import) {
elf_file.addRelaDynAssumeCapacity(.{
.offset = offset,
.sym = extra.dynamic,
.type = elf.R_X86_64_TPOFF64,
});
} else if (is_shared) {
elf_file.addRelaDynAssumeCapacity(.{
.offset = offset,
.type = elf.R_X86_64_TPOFF64,
.addend = @intCast(symbol.getGotTpAddress(elf_file) - elf_file.getTlsAddress()),
});
}
},
}
}
}
Expand All @@ -729,11 +770,14 @@ pub const GotSection = struct {
{
num += 1;
},

.tlsgd => if (symbol.flags.import) {
num += 2;
} else if (is_shared) {
num += 1;
},

.gottp => num += 1,
}
}
return num;
Expand All @@ -747,6 +791,7 @@ pub const GotSection = struct {
const suffix_len = switch (sym) {
.tlsgd => "$tlsgd".len,
.got => "$got".len,
.gottp => "$gottp".len,
};
const symbol = elf_file.getSymbol(sym.getIndex());
const name_len = symbol.getName(elf_file).len;
Expand All @@ -769,6 +814,7 @@ pub const GotSection = struct {
const suffix = switch (sym) {
.tlsgd => "$tlsgd",
.got => "$got",
.gottp => "$gottp",
};
const symbol = elf_file.getSymbol(sym.getIndex());
const name = try std.fmt.allocPrint(gpa, "{s}{s}", .{ symbol.getName(elf_file), suffix });
Expand All @@ -777,10 +823,11 @@ pub const GotSection = struct {
const st_value = switch (sym) {
.tlsgd => symbol.getTlsGdAddress(elf_file),
.got => symbol.getGotAddress(elf_file),
.gottp => symbol.getGotTpAddress(elf_file),
};
const st_size: u64 = switch (sym) {
.tlsgd => 16,
.got => 8,
.got, .gottp => 8,
};
ctx.symtab[ilocal] = .{
.st_name = st_name,
Expand Down

0 comments on commit 12544e5

Please sign in to comment.