authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-19 18:59:10+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-19 22:39:49+01:00
log7d3aa58e16dc90852316324efddae5ffc11d0606
tree08ef320a14e742ea3b568c49d906c3f87ba44272
parent287f640cc94d7f1cddb30e9ef57a8c921621a5b9

macho: make int casts safer


1 files changed, 34 insertions(+), 23 deletions(-)

src/link/MachO.zig+34-23
...@@ -1229,14 +1229,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1229,14 +1229,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1229 const this_addr = symbol.n_value + fixup.start;1229 const this_addr = symbol.n_value + fixup.start;
1230 switch (self.base.options.target.cpu.arch) {1230 switch (self.base.options.target.cpu.arch) {
1231 .x86_64 => {1231 .x86_64 => {
1232 const displacement = @intCast(u32, target_addr - this_addr - fixup.len);1232 assert(target_addr >= this_addr + fixup.len);
1233 const displacement = try math.cast(u32, target_addr - this_addr - fixup.len);
1233 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];1234 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];
1234 mem.writeIntSliceLittle(u32, placeholder, displacement);1235 mem.writeIntSliceLittle(u32, placeholder, displacement);
1235 },1236 },
1236 .aarch64 => {1237 .aarch64 => {
1237 const displacement = @intCast(u27, target_addr - this_addr);1238 assert(target_addr >= this_addr);
1239 const displacement = try math.cast(u27, target_addr - this_addr);
1238 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];1240 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];
1239 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.b(@intCast(i28, displacement)).toU32());1241 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.b(@as(i28, displacement)).toU32());
1240 },1242 },
1241 else => unreachable, // unsupported target architecture1243 else => unreachable, // unsupported target architecture
1242 }1244 }
...@@ -1249,14 +1251,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1249,14 +1251,16 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1249 const text_addr = symbol.n_value + fixup.start;1251 const text_addr = symbol.n_value + fixup.start;
1250 switch (self.base.options.target.cpu.arch) {1252 switch (self.base.options.target.cpu.arch) {
1251 .x86_64 => {1253 .x86_64 => {
1252 const displacement = @intCast(u32, stub_addr - text_addr - fixup.len);1254 assert(stub_addr >= text_addr + fixup.len);
1255 const displacement = try math.cast(u32, stub_addr - text_addr - fixup.len);
1253 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];1256 var placeholder = code_buffer.items[fixup.start + fixup.len - @sizeOf(u32) ..][0..@sizeOf(u32)];
1254 mem.writeIntSliceLittle(u32, placeholder, displacement);1257 mem.writeIntSliceLittle(u32, placeholder, displacement);
1255 },1258 },
1256 .aarch64 => {1259 .aarch64 => {
1257 const displacement = @intCast(u32, stub_addr - text_addr);1260 assert(stub_addr >= text_addr);
1261 const displacement = try math.cast(i28, stub_addr - text_addr);
1258 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];1262 var placeholder = code_buffer.items[fixup.start..][0..fixup.len];
1259 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(@intCast(i28, displacement)).toU32());1263 mem.writeIntSliceLittle(u32, placeholder, aarch64.Instruction.bl(displacement).toU32());
1260 },1264 },
1261 else => unreachable, // unsupported target architecture1265 else => unreachable, // unsupported target architecture
1262 }1266 }
...@@ -2074,7 +2078,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -2074,7 +2078,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
2074 code[1] = 0x8d;2078 code[1] = 0x8d;
2075 code[2] = 0x1d;2079 code[2] = 0x1d;
2076 {2080 {
2077 const displacement = @intCast(u32, data.addr - stub_helper.addr - 7);2081 const displacement = try math.cast(u32, data.addr - stub_helper.addr - 7);
2078 mem.writeIntLittle(u32, code[3..7], displacement);2082 mem.writeIntLittle(u32, code[3..7], displacement);
2079 }2083 }
2080 // push %r112084 // push %r11
...@@ -2084,7 +2088,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -2084,7 +2088,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
2084 code[9] = 0xff;2088 code[9] = 0xff;
2085 code[10] = 0x25;2089 code[10] = 0x25;
2086 {2090 {
2087 const displacement = @intCast(u32, got.addr - stub_helper.addr - code_size);2091 const displacement = try math.cast(u32, got.addr - stub_helper.addr - code_size);
2088 mem.writeIntLittle(u32, code[11..], displacement);2092 mem.writeIntLittle(u32, code[11..], displacement);
2089 }2093 }
2090 self.stub_helper_stubs_start_off = stub_helper.offset + code_size;2094 self.stub_helper_stubs_start_off = stub_helper.offset + code_size;
...@@ -2093,8 +2097,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -2093,8 +2097,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
2093 .aarch64 => {2097 .aarch64 => {
2094 var code: [4 * @sizeOf(u32)]u8 = undefined;2098 var code: [4 * @sizeOf(u32)]u8 = undefined;
2095 {2099 {
2096 const displacement = data.addr - stub_helper.addr;2100 const displacement = try math.cast(i21, data.addr - stub_helper.addr);
2097 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, @intCast(i21, displacement)).toU32());2101 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, displacement).toU32());
2098 }2102 }
2099 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.stp(2103 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.stp(
2100 .x16,2104 .x16,
...@@ -2103,9 +2107,10 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -2103,9 +2107,10 @@ pub fn populateMissingMetadata(self: *MachO) !void {
2103 aarch64.Instruction.LoadStorePairOffset.pre_index(-16),2107 aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
2104 ).toU32());2108 ).toU32());
2105 {2109 {
2106 const displacement = got.addr - stub_helper.addr - 2 * @sizeOf(u32);2110 const displacement = try math.divExact(u64, got.addr - stub_helper.addr - 2 * @sizeOf(u32), 4);
2111 const literal = try math.cast(u19, displacement);
2107 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.ldr(.x16, .{2112 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.ldr(.x16, .{
2108 .literal = @intCast(u19, displacement / 4),2113 .literal = literal,
2109 }).toU32());2114 }).toU32());
2110 }2115 }
2111 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.br(.x16).toU32());2116 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.br(.x16).toU32());
...@@ -2445,8 +2450,8 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {...@@ -2445,8 +2450,8 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
2445 var code: [8]u8 = undefined;2450 var code: [8]u8 = undefined;
2446 switch (self.base.options.target.cpu.arch) {2451 switch (self.base.options.target.cpu.arch) {
2447 .x86_64 => {2452 .x86_64 => {
2448 const pos_symbol_off = @intCast(u31, vmaddr - self.offset_table.items[index] + 7);2453 const pos_symbol_off = try math.cast(u31, vmaddr - self.offset_table.items[index] + 7);
2449 const symbol_off = @bitCast(u32, @intCast(i32, pos_symbol_off) * -1);2454 const symbol_off = @bitCast(u32, @as(i32, pos_symbol_off) * -1);
2450 // lea %rax, [rip - disp]2455 // lea %rax, [rip - disp]
2451 code[0] = 0x48;2456 code[0] = 0x48;
2452 code[1] = 0x8D;2457 code[1] = 0x8D;
...@@ -2456,8 +2461,8 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {...@@ -2456,8 +2461,8 @@ fn writeOffsetTableEntry(self: *MachO, index: usize) !void {
2456 code[7] = 0xC3;2461 code[7] = 0xC3;
2457 },2462 },
2458 .aarch64 => {2463 .aarch64 => {
2459 const pos_symbol_off = @intCast(u20, vmaddr - self.offset_table.items[index]);2464 const pos_symbol_off = try math.cast(u20, vmaddr - self.offset_table.items[index]);
2460 const symbol_off = @intCast(i21, pos_symbol_off) * -1;2465 const symbol_off = @as(i21, pos_symbol_off) * -1;
2461 // adr x0, #-disp2466 // adr x0, #-disp
2462 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x0, symbol_off).toU32());2467 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x0, symbol_off).toU32());
2463 // ret x282468 // ret x28
...@@ -2503,16 +2508,19 @@ fn writeStub(self: *MachO, index: u32) !void {...@@ -2503,16 +2508,19 @@ fn writeStub(self: *MachO, index: u32) !void {
2503 defer self.base.allocator.free(code);2508 defer self.base.allocator.free(code);
2504 switch (self.base.options.target.cpu.arch) {2509 switch (self.base.options.target.cpu.arch) {
2505 .x86_64 => {2510 .x86_64 => {
2506 const displacement = @intCast(u32, la_ptr_addr - stub_addr - stubs.reserved2);2511 assert(la_ptr_addr >= stub_addr + stubs.reserved2);
2512 const displacement = try math.cast(u32, la_ptr_addr - stub_addr - stubs.reserved2);
2507 // jmp2513 // jmp
2508 code[0] = 0xff;2514 code[0] = 0xff;
2509 code[1] = 0x25;2515 code[1] = 0x25;
2510 mem.writeIntLittle(u32, code[2..][0..4], displacement);2516 mem.writeIntLittle(u32, code[2..][0..4], displacement);
2511 },2517 },
2512 .aarch64 => {2518 .aarch64 => {
2513 const displacement = la_ptr_addr - stub_addr;2519 assert(la_ptr_addr >= stub_addr);
2520 const displacement = try math.divExact(u64, la_ptr_addr - stub_addr, 4);
2521 const literal = try math.cast(u19, displacement);
2514 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.x16, .{2522 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.x16, .{
2515 .literal = @intCast(u19, displacement / 4),2523 .literal = literal,
2516 }).toU32());2524 }).toU32());
2517 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.br(.x16).toU32());2525 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.br(.x16).toU32());
2518 },2526 },
...@@ -2535,7 +2543,10 @@ fn writeStubInStubHelper(self: *MachO, index: u32) !void {...@@ -2535,7 +2543,10 @@ fn writeStubInStubHelper(self: *MachO, index: u32) !void {
2535 defer self.base.allocator.free(code);2543 defer self.base.allocator.free(code);
2536 switch (self.base.options.target.cpu.arch) {2544 switch (self.base.options.target.cpu.arch) {
2537 .x86_64 => {2545 .x86_64 => {
2538 const displacement = @intCast(i32, @intCast(i64, stub_helper.offset) - @intCast(i64, stub_off) - stub_size);2546 const displacement = try math.cast(
2547 i32,
2548 @intCast(i64, stub_helper.offset) - @intCast(i64, stub_off) - stub_size,
2549 );
2539 // pushq2550 // pushq
2540 code[0] = 0x68;2551 code[0] = 0x68;
2541 mem.writeIntLittle(u32, code[1..][0..4], 0x0); // Just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.2552 mem.writeIntLittle(u32, code[1..][0..4], 0x0); // Just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.
...@@ -2544,11 +2555,11 @@ fn writeStubInStubHelper(self: *MachO, index: u32) !void {...@@ -2544,11 +2555,11 @@ fn writeStubInStubHelper(self: *MachO, index: u32) !void {
2544 mem.writeIntLittle(u32, code[6..][0..4], @bitCast(u32, displacement));2555 mem.writeIntLittle(u32, code[6..][0..4], @bitCast(u32, displacement));
2545 },2556 },
2546 .aarch64 => {2557 .aarch64 => {
2547 const displacement = @intCast(i64, stub_helper.offset) - @intCast(i64, stub_off) - 4;2558 const displacement = try math.cast(i28, @intCast(i64, stub_helper.offset) - @intCast(i64, stub_off) - 4);
2548 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.w16, .{2559 mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.w16, .{
2549 .literal = 0x2,2560 .literal = @divExact(stub_size - @sizeOf(u32), 4),
2550 }).toU32());2561 }).toU32());
2551 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(@intCast(i28, displacement)).toU32());2562 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(displacement).toU32());
2552 mem.writeIntLittle(u32, code[8..12], 0x0); // Just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.2563 mem.writeIntLittle(u32, code[8..12], 0x0); // Just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.
2553 },2564 },
2554 else => unreachable,2565 else => unreachable,