Commit 914f822025

David Rubin <daviru007@icloud.com>
2024-12-15 09:39:04
link.Elf: implement non-alloc `{SET,SUB}_ULEB128`
1 parent 4162f40
Changed files (2)
src
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),
         }
     }
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 },