Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Unified Diff: test/unittests/eh-frame-writer-unittest.cc

Issue 2023503002: Reland Implement .eh_frame writer and disassembler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@eh-frame-base
Patch Set: SaveRegisterToStack => RegisterSavedToStack. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: test/unittests/eh-frame-writer-unittest.cc
diff --git a/test/unittests/eh-frame-writer-unittest.cc b/test/unittests/eh-frame-writer-unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b1d60e458d3d837e2154430f914525480679f336
--- /dev/null
+++ b/test/unittests/eh-frame-writer-unittest.cc
@@ -0,0 +1,362 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/eh-frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test enabled only on supported architectures.
+#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM) || \
+ defined(V8_TARGET_ARCH_ARM64)
+
+using namespace v8::internal;
+
+namespace v8 {
+namespace internal {
+
+class EhFrameWriterInternals : public testing::Test {
+ protected:
+ // Being a non-negative 6bit value, this also serves as its LEB128 encoding.
+ static const int kTestRegisterCode = 0;
rmcilroy 2016/07/05 10:56:13 I would test a more interesting code than '0', tha
+
+ void WriteULEB128(int value) { writer_.WriteULEB128(value); }
+ void WriteSLEB128(int value) { writer_.WriteSLEB128(value); }
+ void Align() { writer_.Align(); }
+ void WriteByte(byte c) { writer_.WriteByte(c); }
+
+ static uint32_t DecodeULEB128(const byte* data, int* decoded_size) {
+ return EhFrameWriter::DecodeULEB128(data, decoded_size);
+ }
+
+ static int32_t DecodeSLEB128(const byte* data, int* decoded_size) {
+ return EhFrameWriter::DecodeSLEB128(data, decoded_size);
+ }
+
+ byte* eh_frame_buffer() { return writer_.eh_frame_buffer_.data(); }
+ int eh_frame_offset() const { return writer_.eh_frame_offset(); }
+ int cie_size() const { return writer_.cie_size_; }
+ int fde_offset() const { return writer_.fde_offset(); }
+ int procedure_address_offset() const {
+ return writer_.procedure_address_offset();
+ }
+ int procedure_size_offset() const { return writer_.procedure_size_offset(); }
+
+ EhFrameWriter writer_;
+};
+
+STATIC_CONST_MEMBER_DEFINITION const int
+ 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
+
+} // namespace internal
+} // namespace v8
+
+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.
+ writer_.Finish(100);
+ EXPECT_EQ(4, EhFrameWriter::kTerminatorSize);
+ EXPECT_EQ(0, EhFrameHdr::kRecordSize % 4);
+ EXPECT_EQ(0, (eh_frame_offset() - EhFrameHdr::kRecordSize -
+ EhFrameWriter::kTerminatorSize) %
+ 8);
+}
+
+TEST_F(EhFrameWriterInternals, Align) {
+ // Ensure the buffer size is not already aligned.
+ if (eh_frame_offset() % 8 == 0) WriteByte(0);
+ Align();
+ EXPECT_EQ(eh_frame_offset() % 8, 0);
+}
+
+TEST_F(EhFrameWriterInternals, AlignNop) {
+ Align();
+ int first_size = eh_frame_offset();
+ // This second align should result in a nop
+ Align();
+ int second_size = eh_frame_offset();
+ EXPECT_EQ(first_size, second_size);
+}
+
+TEST_F(EhFrameWriterInternals, ProcedureBoundaries) {
+ writer_.Finish(100);
+ int32_t procedure_offset =
+ ReadUnalignedUInt32(eh_frame_buffer() + procedure_address_offset());
+ EXPECT_EQ(-(procedure_address_offset() + RoundUp(100, 8)), procedure_offset);
+ uint32_t procedure_size =
+ ReadUnalignedUInt32(eh_frame_buffer() + procedure_size_offset());
+ EXPECT_EQ(100, procedure_size);
+}
+
+TEST_F(EhFrameWriterInternals, CIESize) {
+ writer_.Finish(42);
+ uint32_t encoded_cie_size = ReadUnalignedUInt32(eh_frame_buffer());
+ // The encoded CIE size does not include the size field itself.
+ EXPECT_EQ(cie_size(), encoded_cie_size + kInt32Size);
+}
+
+TEST_F(EhFrameWriterInternals, FDESize) {
+ writer_.Finish(42);
+ uint32_t fde_size = ReadUnalignedUInt32(eh_frame_buffer() + fde_offset());
+ EXPECT_EQ(eh_frame_offset() - EhFrameHdr::kRecordSize - cie_size() -
+ EhFrameWriter::kTerminatorSize,
+ fde_size);
+}
+
+TEST_F(EhFrameWriterInternals, SetOffset) {
+ Register base_register_before_update = writer_.base_register();
+ int start = eh_frame_offset();
+ writer_.SetBaseAddressOffset(64);
+ int end = eh_frame_offset();
+ EXPECT_EQ(64, writer_.base_offset());
+ EXPECT_TRUE(base_register_before_update.is(writer_.base_register()));
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(64, eh_frame_buffer()[start + 1]);
+}
+
+TEST_F(EhFrameWriterInternals, IncreaseOffset) {
+ int base_offset_before_update = writer_.base_offset();
+ Register base_register_before_update = writer_.base_register();
+ int start = eh_frame_offset();
+ writer_.IncreaseBaseAddressOffset(16);
+ int end = eh_frame_offset();
+ EXPECT_EQ(base_offset_before_update + 16, writer_.base_offset());
+ EXPECT_TRUE(base_register_before_update.is(writer_.base_register()));
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(base_offset_before_update + 16, eh_frame_buffer()[start + 1]);
+}
+
+TEST_F(EhFrameWriterInternals, SetRegister) {
+ int base_offset_before_update = writer_.base_offset();
+ int start = eh_frame_offset();
+ Register test_register = Register::from_code(kTestRegisterCode);
+ writer_.SetBaseAddressRegister(test_register);
+ int end = eh_frame_offset();
+ EXPECT_TRUE(writer_.base_register().is(test_register));
+ EXPECT_EQ(base_offset_before_update, writer_.base_offset());
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ(EhFrameWriter::kDefCfaRegister, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]);
+}
+
+TEST_F(EhFrameWriterInternals, SetRegisterAndOffset) {
+ int start = eh_frame_offset();
+ Register test_register = Register::from_code(0);
+ writer_.SetBaseAddressRegisterAndOffset(test_register, 24);
+ int end = eh_frame_offset();
+ EXPECT_EQ(24, writer_.base_offset());
+ EXPECT_TRUE(writer_.base_register().is(test_register));
+ EXPECT_EQ(3, end - start);
+ EXPECT_EQ(EhFrameWriter::kDefCfa, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(24, eh_frame_buffer()[start + 2]);
+}
+
+TEST_F(EhFrameWriterInternals, ULEB128Encoding) {
+ int start = eh_frame_offset();
+ WriteULEB128(624485);
+ int end = eh_frame_offset();
+ static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26};
+
+ EXPECT_EQ(sizeof(kExpectedEncoding), end - start);
+ EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]);
+}
+
+TEST_F(EhFrameWriterInternals, SLEB128EncodingPositive) {
+ int start = eh_frame_offset();
+ WriteSLEB128(624485);
+ int end = eh_frame_offset();
+ static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26};
+
+ EXPECT_EQ(sizeof(kExpectedEncoding), end - start);
+ EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]);
+}
+
+TEST_F(EhFrameWriterInternals, SLEB128EncodingNegative) {
+ int start = eh_frame_offset();
+ WriteSLEB128(-624485);
+ int end = eh_frame_offset();
+ static const byte kExpectedEncoding[] = {0x9b, 0xf1, 0x59};
+
+ EXPECT_EQ(sizeof(kExpectedEncoding), end - start);
+ EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]);
+}
+
+TEST_F(EhFrameWriterInternals, ULEB128Decoding) {
+ static const byte kEncoded[] = {0xe5, 0x8e, 0x26};
+ int size = 0;
+ uint32_t value = DecodeULEB128(kEncoded, &size);
+ EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size);
+ EXPECT_EQ(624485, value);
+}
+
+TEST_F(EhFrameWriterInternals, SLEB128DecodingPositive) {
+ static const byte kEncoded[] = {0xe5, 0x8e, 0x26};
+ int size = 0;
+ int32_t value = DecodeSLEB128(kEncoded, &size);
+ EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size);
+ EXPECT_EQ(624485, value);
+}
+
+TEST_F(EhFrameWriterInternals, SLEB128DecodingNegative) {
+ static const byte kEncoded[] = {0x9b, 0xf1, 0x59};
+ int size = 0;
+ int32_t value = DecodeSLEB128(kEncoded, &size);
+ EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size);
+ EXPECT_EQ(-624485, value);
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bit) {
+ EXPECT_EQ(0, writer_.last_pc_offset());
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(42);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1, end - start);
+ EXPECT_EQ((1 << 6) | 42, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(42, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bitDelta) {
+ writer_.AdvanceLocation(42);
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(65);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1, end - start);
+ EXPECT_EQ((1 << 6) | (65 - 42), eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(65, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bit) {
+ EXPECT_EQ(0, writer_.last_pc_offset());
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(0x42);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint8_t), end - start);
+ EXPECT_EQ(EhFrameWriter::kAdvanceLoc1, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(0x42, eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(0x42, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bitDelta) {
+ writer_.AdvanceLocation(0x10);
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(0x70);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint8_t), end - start);
+ EXPECT_EQ(0x70 - 0x10, eh_frame_buffer()[start + 1]);
+ EXPECT_EQ(0x70, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bit) {
+ EXPECT_EQ(0, writer_.last_pc_offset());
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(42 + kMaxUInt8);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint16_t), end - start);
+ EXPECT_EQ(EhFrameWriter::kAdvanceLoc2, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(42 + kMaxUInt8, ReadUnalignedUInt16(eh_frame_buffer() + start + 1));
+ EXPECT_EQ(42 + kMaxUInt8, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bitDelta) {
+ writer_.AdvanceLocation(41);
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(62 + kMaxUInt8);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint16_t), end - start);
+ EXPECT_EQ(62 + kMaxUInt8 - 41,
+ ReadUnalignedUInt16(eh_frame_buffer() + start + 1));
+ EXPECT_EQ(62 + kMaxUInt8, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bit) {
+ EXPECT_EQ(0, writer_.last_pc_offset());
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(42 + kMaxUInt16);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint32_t), end - start);
+ EXPECT_EQ(EhFrameWriter::kAdvanceLoc4, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(42 + kMaxUInt16,
+ ReadUnalignedUInt32(eh_frame_buffer() + start + 1));
+ EXPECT_EQ(42 + kMaxUInt16, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bitDelta) {
+ writer_.AdvanceLocation(41);
+ int start = eh_frame_offset();
+ writer_.AdvanceLocation(62 + kMaxUInt16);
+ int end = eh_frame_offset();
+ EXPECT_EQ(1 + sizeof(uint32_t), end - start);
+ EXPECT_EQ(62 + kMaxUInt16 - 41,
+ ReadUnalignedUInt32(eh_frame_buffer() + start + 1));
+ EXPECT_EQ(62 + kMaxUInt16, writer_.last_pc_offset());
+}
+
+TEST_F(EhFrameWriterInternals, GetEhFrame) {
+ writer_.Finish(42);
+ CodeDesc code_desc;
+ writer_.GetEhFrame(&code_desc);
+ EXPECT_EQ(eh_frame_offset(), code_desc.unwinding_info_size);
+ EXPECT_EQ(0, memcmp(eh_frame_buffer(), code_desc.unwinding_info,
+ eh_frame_offset()));
+}
+
+TEST_F(EhFrameWriterInternals, SaveRegisterPositiveOffset) {
+ int start = eh_frame_offset();
+ Register test_register = Register::from_code(kTestRegisterCode);
+ writer_.RegisterSavedToStack(test_register, 16);
+ int end = eh_frame_offset();
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(16 / std::abs(EhFrameWriter::kDataAlignmentFactor),
+ eh_frame_buffer()[start + 1]);
+}
+
+TEST_F(EhFrameWriterInternals, SaveRegisterNegativeOffset) {
+ int start = eh_frame_offset();
+ Register test_register = Register::from_code(kTestRegisterCode);
+ writer_.RegisterSavedToStack(test_register, -16);
+ int end = eh_frame_offset();
+ EXPECT_EQ(3, end - start);
+ EXPECT_EQ(EhFrameWriter::kOffsetExtendedSf, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]);
+ if (EhFrameWriter::kDataAlignmentFactor == -4) {
+ EXPECT_EQ(0x7c, eh_frame_buffer()[start + 2]); // -4 SLEB128 encoded.
+ } else if (EhFrameWriter::kDataAlignmentFactor == -8) {
+ EXPECT_EQ(0x7e, eh_frame_buffer()[start + 2]); // -2 SLEB128 encoded.
+ } else {
+ EXPECT_TRUE(false && "Data alignment not handled in test.");
+ }
+}
+
+TEST_F(EhFrameWriterInternals, SaveRegisterToTop) {
+ int base_offset_before_call = writer_.base_offset();
+ int start = eh_frame_offset();
+ Register test_register = Register::from_code(kTestRegisterCode);
+ writer_.RegisterSavedToStack(test_register);
+ int end = eh_frame_offset();
+ EXPECT_EQ(base_offset_before_call, writer_.base_offset());
+ EXPECT_GE(base_offset_before_call, 0);
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(
+ base_offset_before_call / std::abs(EhFrameWriter::kDataAlignmentFactor),
+ eh_frame_buffer()[start + 1]);
+}
+
+TEST_F(EhFrameWriterInternals, RegisterIsValid) {
+ Register test_register = Register::from_code(kTestRegisterCode);
+ int start = eh_frame_offset();
+ writer_.RegisterIsValid(test_register);
+ int end = eh_frame_offset();
+ EXPECT_EQ(2, end - start);
+ EXPECT_EQ(EhFrameWriter::kSameValue, eh_frame_buffer()[start + 0]);
+ EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]);
+}
+
+#endif

Powered by Google App Engine
This is Rietveld 408576698