aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-12-15 00:39:04 -0800
committerAlex Rønne Petersen <alex@alexrp.com>2025-02-11 20:41:52 +0100
commit914f822025b9f761ccf0fd55a50d8cd6ecb51ec1 (patch)
tree878ed9f19077f184c209402dc5aafb23220d025e /src
parent4162f401cbaa2013eae8fa518cf255ce4c5c952b (diff)
downloadzig-914f822025b9f761ccf0fd55a50d8cd6ecb51ec1.tar.gz
zig-914f822025b9f761ccf0fd55a50d8cd6ecb51ec1.zip
link.Elf: implement non-alloc `{SET,SUB}_ULEB128`
Diffstat (limited to 'src')
-rw-r--r--src/link/Elf/Atom.zig6
-rw-r--r--src/link/riscv.zig25
2 files changed, 31 insertions, 0 deletions
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig
index 10e6f669d3..33a4663e79 100644
--- a/src/link/Elf/Atom.zig
+++ b/src/link/Elf/Atom.zig
@@ -1882,6 +1882,9 @@ const riscv = struct {
.LO12_S,
.ADD32,
.SUB32,
+
+ .SUB_ULEB128,
+ .SET_ULEB128,
=> {},
else => try atom.reportUnhandledRelocError(rel, elf_file),
@@ -2071,6 +2074,9 @@ const riscv = struct {
.SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A),
.SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A),
+ .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A),
+ .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A),
+
else => try atom.reportUnhandledRelocError(rel, elf_file),
}
}
diff --git a/src/link/riscv.zig b/src/link/riscv.zig
index 106fd1a817..bb16cb7d80 100644
--- a/src/link/riscv.zig
+++ b/src/link/riscv.zig
@@ -9,6 +9,31 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytyp
mem.writeInt(u8, code, value, .little);
}
+pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void {
+ switch (op) {
+ .set => try overwriteUleb(stream, @intCast(addend)),
+ .sub => {
+ const position = try stream.getPos();
+ const value: u64 = try std.leb.readUleb128(u64, stream.reader());
+ try stream.seekTo(position);
+ try overwriteUleb(stream, value -% @as(u64, @intCast(addend)));
+ },
+ }
+}
+
+fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void {
+ var value: u64 = addend;
+ const writer = stream.writer();
+
+ while (true) {
+ const byte = stream.buffer[stream.pos];
+ if (byte & 0x80 == 0) break;
+ try writer.writeByte(0x80 | @as(u8, @truncate(value & 0x7f)));
+ value >>= 7;
+ }
+ stream.buffer[stream.pos] = @truncate(value & 0x7f);
+}
+
pub fn writeAddend(
comptime Int: type,
comptime op: enum { add, sub },