Skip to content

Commit

Permalink
elf: handle .ifunc action for dynamic abs relocs
Browse files Browse the repository at this point in the history
  • Loading branch information
kubkon committed Jul 11, 2023
1 parent d461c91 commit d3caa57
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 26 deletions.
3 changes: 2 additions & 1 deletion src/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{},
comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{},

needs_tlsld: bool = false,
num_ifunc_dynrelocs: usize = 0,
default_sym_version: elf.Elf64_Versym,

pub fn openPath(allocator: Allocator, options: Options, thread_pool: *ThreadPool) !*Elf {
Expand Down Expand Up @@ -2444,7 +2445,7 @@ fn sortRelaDyn(self: *Elf) void {
}

fn getNumIRelativeRelocs(self: *Elf) usize {
var count: usize = 0;
var count: usize = self.num_ifunc_dynrelocs;

for (self.got.symbols.items) |sym_index| {
const sym = self.getSymbol(sym_index);
Expand Down
35 changes: 10 additions & 25 deletions src/Elf/Atom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -315,17 +315,12 @@ fn scanReloc(self: Atom, symbol: *Symbol, rel: elf.Elf64_Rela, action: RelocActi
}
},

.dynrel => {
.dynrel, .baserel, .ifunc => {
self.checkTextReloc(symbol, elf_file);
object.num_dynrelocs += 1;
},

.baserel => {
self.checkTextReloc(symbol, elf_file);
object.num_dynrelocs += 1;
if (action == .ifunc) elf_file.num_ifunc_dynrelocs += 1;
},

.ifunc => self.unhandledRelocError(symbol, rel, action, elf_file),
}
}

Expand All @@ -348,23 +343,6 @@ inline fn checkTextReloc(self: Atom, symbol: *const Symbol, elf_file: *Elf) void
}
}

inline fn unhandledRelocError(
self: Atom,
symbol: *const Symbol,
rel: elf.Elf64_Rela,
action: RelocAction,
elf_file: *Elf,
) void {
elf_file.base.fatal("{s}: {s}: unhandled {} relocation at offset 0x{x} against symbol '{s}': action {s}", .{
self.getObject(elf_file).fmtPath(),
self.getName(elf_file),
fmtRelocType(rel.r_type()),
rel.r_offset,
symbol.getName(elf_file),
@tagName(action),
});
}

inline fn noPicError(self: Atom, symbol: *const Symbol, rel: elf.Elf64_Rela, elf_file: *Elf) void {
elf_file.base.fatal(
"{s}: {s}: {} relocation at offset 0x{x} against symbol '{s}' cannot be used; recompile with -fno-PIC",
Expand Down Expand Up @@ -726,7 +704,14 @@ fn resolveDynAbsReloc(
});
},

.ifunc => self.unhandledRelocError(target, rel, action, elf_file),
.ifunc => {
const S_ = @as(i64, @intCast(target.getAddress(.{ .plt = false }, elf_file)));
elf_file.addRelaDynAssumeCapacity(.{
.offset = P,
.type = elf.R_X86_64_IRELATIVE,
.addend = S_ + A,
});
},
}
}

Expand Down
24 changes: 24 additions & 0 deletions test/elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub fn addElfTests(b: *Build, opts: Options) *Step {
elf_step.dependOn(testCopyrelAlias(b, opts));
elf_step.dependOn(testDsoIfunc(b, opts));
elf_step.dependOn(testDsoPlt(b, opts));
elf_step.dependOn(testIfuncAlias(b, opts));
elf_step.dependOn(testIfuncDynamic(b, opts));
elf_step.dependOn(testIfuncFuncPtr(b, opts));
elf_step.dependOn(testIfuncNoPlt(b, opts));
Expand Down Expand Up @@ -195,6 +196,28 @@ fn testDsoPlt(b: *Build, opts: Options) *Step {
return test_step;
}

fn testIfuncAlias(b: *Build, opts: Options) *Step {
const test_step = b.step("test-elf-ifunc-alias", "");

const exe = cc(b, null, opts);
exe.addSourceBytes(
\\#include <assert.h>
\\void foo() {}
\\int bar() __attribute__((ifunc("resolve_bar")));
\\void *resolve_bar() { return foo; }
\\void *bar2 = bar;
\\int main() {
\\ assert(bar == bar2);
\\}
, "main.c");
exe.addArg("-fPIC");

const run = exe.run();
test_step.dependOn(run.step());

return test_step;
}

fn testIfuncDynamic(b: *Build, opts: Options) *Step {
const test_step = b.step("test-elf-ifunc-dynamic", "");

Expand Down Expand Up @@ -309,6 +332,7 @@ fn testIfuncStatic(b: *Build, opts: Options) *Step {

const exe = cc(b, null, opts);
exe.addSourceBytes(
\\#include <stdio.h>
\\void foo() __attribute__((ifunc("resolve_foo")));
\\void hello() {
\\ printf("Hello world\n");
Expand Down

0 comments on commit d3caa57

Please sign in to comment.