1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdlib.h> 6 7 #include "src/v8.h" 8 9 #include "src/debug/debug.h" 10 #include "src/disasm.h" 11 #include "src/disassembler.h" 12 #include "src/ic/ic.h" 13 #include "src/macro-assembler.h" 14 #include "src/x87/frames-x87.h" 15 #include "test/cctest/cctest.h" 16 #include "test/cctest/compiler/c-signature.h" 17 #include "test/cctest/compiler/call-tester.h" 18 19 using namespace v8::internal; 20 using namespace v8::internal::compiler; 21 22 #define __ assm. 23 24 static int32_t DummyStaticFunction(Object* result) { return 1; } 25 26 TEST(WasmRelocationX87MemoryReference) { 27 Isolate* isolate = CcTest::i_isolate(); 28 Zone zone(isolate->allocator()); 29 HandleScope scope(isolate); 30 v8::internal::byte buffer[4096]; 31 Assembler assm(isolate, buffer, sizeof buffer); 32 DummyStaticFunction(NULL); 33 int32_t imm = 1234567; 34 35 __ mov(eax, Immediate(reinterpret_cast<Address>(imm), 36 RelocInfo::WASM_MEMORY_REFERENCE)); 37 __ nop(); 38 __ ret(0); 39 40 CSignature0<int32_t> csig; 41 CodeDesc desc; 42 assm.GetCode(&desc); 43 Handle<Code> code = isolate->factory()->NewCode( 44 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 45 USE(code); 46 47 CodeRunner<int32_t> runnable(isolate, code, &csig); 48 int32_t ret_value = runnable.Call(); 49 CHECK_EQ(ret_value, imm); 50 51 #ifdef OBJECT_PRINT 52 OFStream os(stdout); 53 code->Print(os); 54 byte* begin = code->instruction_start(); 55 byte* end = begin + code->instruction_size(); 56 disasm::Disassembler::Disassemble(stdout, begin, end); 57 #endif 58 59 size_t offset = 1234; 60 61 // Relocating references by offset 62 int mode_mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE); 63 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { 64 RelocInfo::Mode mode = it.rinfo()->rmode(); 65 if (RelocInfo::IsWasmMemoryReference(mode)) { 66 // Dummy values of size used here as the objective of the test is to 67 // verify that the immediate is patched correctly 68 it.rinfo()->update_wasm_memory_reference( 69 it.rinfo()->wasm_memory_reference(), 70 it.rinfo()->wasm_memory_reference() + offset, 1, 2, 71 SKIP_ICACHE_FLUSH); 72 } 73 } 74 75 // Check if immediate is updated correctly 76 ret_value = runnable.Call(); 77 CHECK_EQ(ret_value, imm + offset); 78 79 #ifdef OBJECT_PRINT 80 code->Print(os); 81 begin = code->instruction_start(); 82 end = begin + code->instruction_size(); 83 disasm::Disassembler::Disassemble(stdout, begin, end); 84 #endif 85 } 86 87 TEST(WasmRelocationX87MemorySizeReference) { 88 CcTest::InitializeVM(); 89 Isolate* isolate = CcTest::i_isolate(); 90 Zone zone(isolate->allocator()); 91 HandleScope scope(isolate); 92 v8::internal::byte buffer[4096]; 93 Assembler assm(isolate, buffer, sizeof buffer); 94 DummyStaticFunction(NULL); 95 int32_t size = 80; 96 Label fail; 97 98 __ mov(eax, Immediate(reinterpret_cast<Address>(size), 99 RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); 100 __ cmp(eax, Immediate(reinterpret_cast<Address>(size), 101 RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); 102 __ j(not_equal, &fail); 103 __ ret(0); 104 __ bind(&fail); 105 __ mov(eax, 0xdeadbeef); 106 __ ret(0); 107 108 CSignature0<int32_t> csig; 109 CodeDesc desc; 110 assm.GetCode(&desc); 111 Handle<Code> code = isolate->factory()->NewCode( 112 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 113 USE(code); 114 115 CodeRunner<int32_t> runnable(isolate, code, &csig); 116 int32_t ret_value = runnable.Call(); 117 CHECK_NE(ret_value, 0xdeadbeef); 118 119 #ifdef OBJECT_PRINT 120 OFStream os(stdout); 121 code->Print(os); 122 byte* begin = code->instruction_start(); 123 byte* end = begin + code->instruction_size(); 124 disasm::Disassembler::Disassemble(stdout, begin, end); 125 #endif 126 127 size_t offset = 10; 128 129 int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); 130 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { 131 RelocInfo::Mode mode = it.rinfo()->rmode(); 132 if (RelocInfo::IsWasmMemorySizeReference(mode)) { 133 it.rinfo()->update_wasm_memory_reference( 134 reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234), 135 it.rinfo()->wasm_memory_size_reference(), 136 it.rinfo()->wasm_memory_size_reference() + offset, SKIP_ICACHE_FLUSH); 137 } 138 } 139 140 ret_value = runnable.Call(); 141 CHECK_NE(ret_value, 0xdeadbeef); 142 143 #ifdef OBJECT_PRINT 144 code->Print(os); 145 begin = code->instruction_start(); 146 end = begin + code->instruction_size(); 147 disasm::Disassembler::Disassemble(stdout, begin, end); 148 #endif 149 } 150 #undef __ 151