Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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 "src/eh-frame.h" | |
| 6 #include "testing/gtest/include/gtest/gtest.h" | |
| 7 | |
| 8 // Test enabled only on supported architectures. | |
| 9 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM) || \ | |
| 10 defined(V8_TARGET_ARCH_ARM64) | |
| 11 | |
| 12 using namespace v8::internal; | |
| 13 | |
| 14 namespace v8 { | |
| 15 namespace internal { | |
| 16 | |
| 17 class EhFrameWriterInternals : public testing::Test { | |
| 18 protected: | |
| 19 // Being a non-negative 6bit value, this also serves as its LEB128 encoding. | |
| 20 static const int kTestRegisterCode = 0; | |
|
rmcilroy
2016/07/05 10:56:13
I would test a more interesting code than '0', tha
| |
| 21 | |
| 22 void WriteULEB128(int value) { writer_.WriteULEB128(value); } | |
| 23 void WriteSLEB128(int value) { writer_.WriteSLEB128(value); } | |
| 24 void Align() { writer_.Align(); } | |
| 25 void WriteByte(byte c) { writer_.WriteByte(c); } | |
| 26 | |
| 27 static uint32_t DecodeULEB128(const byte* data, int* decoded_size) { | |
| 28 return EhFrameWriter::DecodeULEB128(data, decoded_size); | |
| 29 } | |
| 30 | |
| 31 static int32_t DecodeSLEB128(const byte* data, int* decoded_size) { | |
| 32 return EhFrameWriter::DecodeSLEB128(data, decoded_size); | |
| 33 } | |
| 34 | |
| 35 byte* eh_frame_buffer() { return writer_.eh_frame_buffer_.data(); } | |
| 36 int eh_frame_offset() const { return writer_.eh_frame_offset(); } | |
| 37 int cie_size() const { return writer_.cie_size_; } | |
| 38 int fde_offset() const { return writer_.fde_offset(); } | |
| 39 int procedure_address_offset() const { | |
| 40 return writer_.procedure_address_offset(); | |
| 41 } | |
| 42 int procedure_size_offset() const { return writer_.procedure_size_offset(); } | |
| 43 | |
| 44 EhFrameWriter writer_; | |
| 45 }; | |
| 46 | |
| 47 STATIC_CONST_MEMBER_DEFINITION const int | |
| 48 EhFrameWriterInternals::kTestRegisterCode; | |
|
rmcilroy
2016/07/05 10:56:13
Don't think you should need this?
Stefano Sanfilippo
2016/07/05 16:02:14
Also in this case, omitting this bit results in a
| |
| 49 | |
| 50 } // namespace internal | |
| 51 } // namespace v8 | |
| 52 | |
| 53 TEST_F(EhFrameWriterInternals, RecordsAlignment) { | |
|
rmcilroy
2016/07/05 10:56:13
The fixture should be named EhFrameWriterTest
Stefano Sanfilippo
2016/07/05 16:02:14
Done.
| |
| 54 writer_.Finish(100); | |
| 55 EXPECT_EQ(4, EhFrameWriter::kTerminatorSize); | |
| 56 EXPECT_EQ(0, EhFrameHdr::kRecordSize % 4); | |
| 57 EXPECT_EQ(0, (eh_frame_offset() - EhFrameHdr::kRecordSize - | |
| 58 EhFrameWriter::kTerminatorSize) % | |
| 59 8); | |
| 60 } | |
| 61 | |
| 62 TEST_F(EhFrameWriterInternals, Align) { | |
| 63 // Ensure the buffer size is not already aligned. | |
| 64 if (eh_frame_offset() % 8 == 0) WriteByte(0); | |
| 65 Align(); | |
| 66 EXPECT_EQ(eh_frame_offset() % 8, 0); | |
| 67 } | |
| 68 | |
| 69 TEST_F(EhFrameWriterInternals, AlignNop) { | |
| 70 Align(); | |
| 71 int first_size = eh_frame_offset(); | |
| 72 // This second align should result in a nop | |
| 73 Align(); | |
| 74 int second_size = eh_frame_offset(); | |
| 75 EXPECT_EQ(first_size, second_size); | |
| 76 } | |
| 77 | |
| 78 TEST_F(EhFrameWriterInternals, ProcedureBoundaries) { | |
| 79 writer_.Finish(100); | |
| 80 int32_t procedure_offset = | |
| 81 ReadUnalignedUInt32(eh_frame_buffer() + procedure_address_offset()); | |
| 82 EXPECT_EQ(-(procedure_address_offset() + RoundUp(100, 8)), procedure_offset); | |
| 83 uint32_t procedure_size = | |
| 84 ReadUnalignedUInt32(eh_frame_buffer() + procedure_size_offset()); | |
| 85 EXPECT_EQ(100, procedure_size); | |
| 86 } | |
| 87 | |
| 88 TEST_F(EhFrameWriterInternals, CIESize) { | |
| 89 writer_.Finish(42); | |
| 90 uint32_t encoded_cie_size = ReadUnalignedUInt32(eh_frame_buffer()); | |
| 91 // The encoded CIE size does not include the size field itself. | |
| 92 EXPECT_EQ(cie_size(), encoded_cie_size + kInt32Size); | |
| 93 } | |
| 94 | |
| 95 TEST_F(EhFrameWriterInternals, FDESize) { | |
| 96 writer_.Finish(42); | |
| 97 uint32_t fde_size = ReadUnalignedUInt32(eh_frame_buffer() + fde_offset()); | |
| 98 EXPECT_EQ(eh_frame_offset() - EhFrameHdr::kRecordSize - cie_size() - | |
| 99 EhFrameWriter::kTerminatorSize, | |
| 100 fde_size); | |
| 101 } | |
| 102 | |
| 103 TEST_F(EhFrameWriterInternals, SetOffset) { | |
| 104 Register base_register_before_update = writer_.base_register(); | |
| 105 int start = eh_frame_offset(); | |
| 106 writer_.SetBaseAddressOffset(64); | |
| 107 int end = eh_frame_offset(); | |
| 108 EXPECT_EQ(64, writer_.base_offset()); | |
| 109 EXPECT_TRUE(base_register_before_update.is(writer_.base_register())); | |
| 110 EXPECT_EQ(2, end - start); | |
| 111 EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]); | |
| 112 EXPECT_EQ(64, eh_frame_buffer()[start + 1]); | |
| 113 } | |
| 114 | |
| 115 TEST_F(EhFrameWriterInternals, IncreaseOffset) { | |
| 116 int base_offset_before_update = writer_.base_offset(); | |
| 117 Register base_register_before_update = writer_.base_register(); | |
| 118 int start = eh_frame_offset(); | |
| 119 writer_.IncreaseBaseAddressOffset(16); | |
| 120 int end = eh_frame_offset(); | |
| 121 EXPECT_EQ(base_offset_before_update + 16, writer_.base_offset()); | |
| 122 EXPECT_TRUE(base_register_before_update.is(writer_.base_register())); | |
| 123 EXPECT_EQ(2, end - start); | |
| 124 EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]); | |
| 125 EXPECT_EQ(base_offset_before_update + 16, eh_frame_buffer()[start + 1]); | |
| 126 } | |
| 127 | |
| 128 TEST_F(EhFrameWriterInternals, SetRegister) { | |
| 129 int base_offset_before_update = writer_.base_offset(); | |
| 130 int start = eh_frame_offset(); | |
| 131 Register test_register = Register::from_code(kTestRegisterCode); | |
| 132 writer_.SetBaseAddressRegister(test_register); | |
| 133 int end = eh_frame_offset(); | |
| 134 EXPECT_TRUE(writer_.base_register().is(test_register)); | |
| 135 EXPECT_EQ(base_offset_before_update, writer_.base_offset()); | |
| 136 EXPECT_EQ(2, end - start); | |
| 137 EXPECT_EQ(EhFrameWriter::kDefCfaRegister, eh_frame_buffer()[start + 0]); | |
| 138 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
| 139 } | |
| 140 | |
| 141 TEST_F(EhFrameWriterInternals, SetRegisterAndOffset) { | |
| 142 int start = eh_frame_offset(); | |
| 143 Register test_register = Register::from_code(0); | |
| 144 writer_.SetBaseAddressRegisterAndOffset(test_register, 24); | |
| 145 int end = eh_frame_offset(); | |
| 146 EXPECT_EQ(24, writer_.base_offset()); | |
| 147 EXPECT_TRUE(writer_.base_register().is(test_register)); | |
| 148 EXPECT_EQ(3, end - start); | |
| 149 EXPECT_EQ(EhFrameWriter::kDefCfa, eh_frame_buffer()[start + 0]); | |
| 150 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
| 151 EXPECT_EQ(24, eh_frame_buffer()[start + 2]); | |
| 152 } | |
| 153 | |
| 154 TEST_F(EhFrameWriterInternals, ULEB128Encoding) { | |
| 155 int start = eh_frame_offset(); | |
| 156 WriteULEB128(624485); | |
| 157 int end = eh_frame_offset(); | |
| 158 static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26}; | |
| 159 | |
| 160 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
| 161 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
| 162 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
| 163 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
| 164 } | |
| 165 | |
| 166 TEST_F(EhFrameWriterInternals, SLEB128EncodingPositive) { | |
| 167 int start = eh_frame_offset(); | |
| 168 WriteSLEB128(624485); | |
| 169 int end = eh_frame_offset(); | |
| 170 static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26}; | |
| 171 | |
| 172 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
| 173 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
| 174 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
| 175 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
| 176 } | |
| 177 | |
| 178 TEST_F(EhFrameWriterInternals, SLEB128EncodingNegative) { | |
| 179 int start = eh_frame_offset(); | |
| 180 WriteSLEB128(-624485); | |
| 181 int end = eh_frame_offset(); | |
| 182 static const byte kExpectedEncoding[] = {0x9b, 0xf1, 0x59}; | |
| 183 | |
| 184 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
| 185 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
| 186 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
| 187 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
| 188 } | |
| 189 | |
| 190 TEST_F(EhFrameWriterInternals, ULEB128Decoding) { | |
| 191 static const byte kEncoded[] = {0xe5, 0x8e, 0x26}; | |
| 192 int size = 0; | |
| 193 uint32_t value = DecodeULEB128(kEncoded, &size); | |
| 194 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
| 195 EXPECT_EQ(624485, value); | |
| 196 } | |
| 197 | |
| 198 TEST_F(EhFrameWriterInternals, SLEB128DecodingPositive) { | |
| 199 static const byte kEncoded[] = {0xe5, 0x8e, 0x26}; | |
| 200 int size = 0; | |
| 201 int32_t value = DecodeSLEB128(kEncoded, &size); | |
| 202 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
| 203 EXPECT_EQ(624485, value); | |
| 204 } | |
| 205 | |
| 206 TEST_F(EhFrameWriterInternals, SLEB128DecodingNegative) { | |
| 207 static const byte kEncoded[] = {0x9b, 0xf1, 0x59}; | |
| 208 int size = 0; | |
| 209 int32_t value = DecodeSLEB128(kEncoded, &size); | |
| 210 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
| 211 EXPECT_EQ(-624485, value); | |
| 212 } | |
| 213 | |
| 214 TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bit) { | |
| 215 EXPECT_EQ(0, writer_.last_pc_offset()); | |
| 216 int start = eh_frame_offset(); | |
| 217 writer_.AdvanceLocation(42); | |
| 218 int end = eh_frame_offset(); | |
| 219 EXPECT_EQ(1, end - start); | |
| 220 EXPECT_EQ((1 << 6) | 42, eh_frame_buffer()[start + 0]); | |
| 221 EXPECT_EQ(42, writer_.last_pc_offset()); | |
| 222 } | |
| 223 | |
| 224 TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bitDelta) { | |
| 225 writer_.AdvanceLocation(42); | |
| 226 int start = eh_frame_offset(); | |
| 227 writer_.AdvanceLocation(65); | |
| 228 int end = eh_frame_offset(); | |
| 229 EXPECT_EQ(1, end - start); | |
| 230 EXPECT_EQ((1 << 6) | (65 - 42), eh_frame_buffer()[start + 0]); | |
| 231 EXPECT_EQ(65, writer_.last_pc_offset()); | |
| 232 } | |
| 233 | |
| 234 TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bit) { | |
| 235 EXPECT_EQ(0, writer_.last_pc_offset()); | |
| 236 int start = eh_frame_offset(); | |
| 237 writer_.AdvanceLocation(0x42); | |
| 238 int end = eh_frame_offset(); | |
| 239 EXPECT_EQ(1 + sizeof(uint8_t), end - start); | |
| 240 EXPECT_EQ(EhFrameWriter::kAdvanceLoc1, eh_frame_buffer()[start + 0]); | |
| 241 EXPECT_EQ(0x42, eh_frame_buffer()[start + 1]); | |
| 242 EXPECT_EQ(0x42, writer_.last_pc_offset()); | |
| 243 } | |
| 244 | |
| 245 TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bitDelta) { | |
| 246 writer_.AdvanceLocation(0x10); | |
| 247 int start = eh_frame_offset(); | |
| 248 writer_.AdvanceLocation(0x70); | |
| 249 int end = eh_frame_offset(); | |
| 250 EXPECT_EQ(1 + sizeof(uint8_t), end - start); | |
| 251 EXPECT_EQ(0x70 - 0x10, eh_frame_buffer()[start + 1]); | |
| 252 EXPECT_EQ(0x70, writer_.last_pc_offset()); | |
| 253 } | |
| 254 | |
| 255 TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bit) { | |
| 256 EXPECT_EQ(0, writer_.last_pc_offset()); | |
| 257 int start = eh_frame_offset(); | |
| 258 writer_.AdvanceLocation(42 + kMaxUInt8); | |
| 259 int end = eh_frame_offset(); | |
| 260 EXPECT_EQ(1 + sizeof(uint16_t), end - start); | |
| 261 EXPECT_EQ(EhFrameWriter::kAdvanceLoc2, eh_frame_buffer()[start + 0]); | |
| 262 EXPECT_EQ(42 + kMaxUInt8, ReadUnalignedUInt16(eh_frame_buffer() + start + 1)); | |
| 263 EXPECT_EQ(42 + kMaxUInt8, writer_.last_pc_offset()); | |
| 264 } | |
| 265 | |
| 266 TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bitDelta) { | |
| 267 writer_.AdvanceLocation(41); | |
| 268 int start = eh_frame_offset(); | |
| 269 writer_.AdvanceLocation(62 + kMaxUInt8); | |
| 270 int end = eh_frame_offset(); | |
| 271 EXPECT_EQ(1 + sizeof(uint16_t), end - start); | |
| 272 EXPECT_EQ(62 + kMaxUInt8 - 41, | |
| 273 ReadUnalignedUInt16(eh_frame_buffer() + start + 1)); | |
| 274 EXPECT_EQ(62 + kMaxUInt8, writer_.last_pc_offset()); | |
| 275 } | |
| 276 | |
| 277 TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bit) { | |
| 278 EXPECT_EQ(0, writer_.last_pc_offset()); | |
| 279 int start = eh_frame_offset(); | |
| 280 writer_.AdvanceLocation(42 + kMaxUInt16); | |
| 281 int end = eh_frame_offset(); | |
| 282 EXPECT_EQ(1 + sizeof(uint32_t), end - start); | |
| 283 EXPECT_EQ(EhFrameWriter::kAdvanceLoc4, eh_frame_buffer()[start + 0]); | |
| 284 EXPECT_EQ(42 + kMaxUInt16, | |
| 285 ReadUnalignedUInt32(eh_frame_buffer() + start + 1)); | |
| 286 EXPECT_EQ(42 + kMaxUInt16, writer_.last_pc_offset()); | |
| 287 } | |
| 288 | |
| 289 TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bitDelta) { | |
| 290 writer_.AdvanceLocation(41); | |
| 291 int start = eh_frame_offset(); | |
| 292 writer_.AdvanceLocation(62 + kMaxUInt16); | |
| 293 int end = eh_frame_offset(); | |
| 294 EXPECT_EQ(1 + sizeof(uint32_t), end - start); | |
| 295 EXPECT_EQ(62 + kMaxUInt16 - 41, | |
| 296 ReadUnalignedUInt32(eh_frame_buffer() + start + 1)); | |
| 297 EXPECT_EQ(62 + kMaxUInt16, writer_.last_pc_offset()); | |
| 298 } | |
| 299 | |
| 300 TEST_F(EhFrameWriterInternals, GetEhFrame) { | |
| 301 writer_.Finish(42); | |
| 302 CodeDesc code_desc; | |
| 303 writer_.GetEhFrame(&code_desc); | |
| 304 EXPECT_EQ(eh_frame_offset(), code_desc.unwinding_info_size); | |
| 305 EXPECT_EQ(0, memcmp(eh_frame_buffer(), code_desc.unwinding_info, | |
| 306 eh_frame_offset())); | |
| 307 } | |
| 308 | |
| 309 TEST_F(EhFrameWriterInternals, SaveRegisterPositiveOffset) { | |
| 310 int start = eh_frame_offset(); | |
| 311 Register test_register = Register::from_code(kTestRegisterCode); | |
| 312 writer_.RegisterSavedToStack(test_register, 16); | |
| 313 int end = eh_frame_offset(); | |
| 314 EXPECT_EQ(2, end - start); | |
| 315 EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]); | |
| 316 EXPECT_EQ(16 / std::abs(EhFrameWriter::kDataAlignmentFactor), | |
| 317 eh_frame_buffer()[start + 1]); | |
| 318 } | |
| 319 | |
| 320 TEST_F(EhFrameWriterInternals, SaveRegisterNegativeOffset) { | |
| 321 int start = eh_frame_offset(); | |
| 322 Register test_register = Register::from_code(kTestRegisterCode); | |
| 323 writer_.RegisterSavedToStack(test_register, -16); | |
| 324 int end = eh_frame_offset(); | |
| 325 EXPECT_EQ(3, end - start); | |
| 326 EXPECT_EQ(EhFrameWriter::kOffsetExtendedSf, eh_frame_buffer()[start + 0]); | |
| 327 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
| 328 if (EhFrameWriter::kDataAlignmentFactor == -4) { | |
| 329 EXPECT_EQ(0x7c, eh_frame_buffer()[start + 2]); // -4 SLEB128 encoded. | |
| 330 } else if (EhFrameWriter::kDataAlignmentFactor == -8) { | |
| 331 EXPECT_EQ(0x7e, eh_frame_buffer()[start + 2]); // -2 SLEB128 encoded. | |
| 332 } else { | |
| 333 EXPECT_TRUE(false && "Data alignment not handled in test."); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 TEST_F(EhFrameWriterInternals, SaveRegisterToTop) { | |
| 338 int base_offset_before_call = writer_.base_offset(); | |
| 339 int start = eh_frame_offset(); | |
| 340 Register test_register = Register::from_code(kTestRegisterCode); | |
| 341 writer_.RegisterSavedToStack(test_register); | |
| 342 int end = eh_frame_offset(); | |
| 343 EXPECT_EQ(base_offset_before_call, writer_.base_offset()); | |
| 344 EXPECT_GE(base_offset_before_call, 0); | |
| 345 EXPECT_EQ(2, end - start); | |
| 346 EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]); | |
| 347 EXPECT_EQ( | |
| 348 base_offset_before_call / std::abs(EhFrameWriter::kDataAlignmentFactor), | |
| 349 eh_frame_buffer()[start + 1]); | |
| 350 } | |
| 351 | |
| 352 TEST_F(EhFrameWriterInternals, RegisterIsValid) { | |
| 353 Register test_register = Register::from_code(kTestRegisterCode); | |
| 354 int start = eh_frame_offset(); | |
| 355 writer_.RegisterIsValid(test_register); | |
| 356 int end = eh_frame_offset(); | |
| 357 EXPECT_EQ(2, end - start); | |
| 358 EXPECT_EQ(EhFrameWriter::kSameValue, eh_frame_buffer()[start + 0]); | |
| 359 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
| 360 } | |
| 361 | |
| 362 #endif | |
| OLD | NEW |