Generalize compression tool
1. One binary for all architectures
2. Generalize (and slightly improve) compression
2.1 works on all relocation types (rela?.dyn section only so far)
2.2 Uses same format to encode ElfW(Rel) as well as ElfW(Rela) tables
Bug: 18051137
Change-Id: I66c95d9076954ca115816fc577d0f5ef274e5e72
diff --git a/tools/relocation_packer/src/delta_encoder_unittest.cc b/tools/relocation_packer/src/delta_encoder_unittest.cc
index b9bf39a..06d9c96 100644
--- a/tools/relocation_packer/src/delta_encoder_unittest.cc
+++ b/tools/relocation_packer/src/delta_encoder_unittest.cc
@@ -6,27 +6,29 @@
#include <vector>
#include "elf.h"
-#include "elf_traits.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "gtest/gtest.h"
namespace {
-void AddRelocation(ELF::Addr addr,
- ELF::Sxword addend,
- std::vector<ELF::Rela>* relocations) {
- ELF::Rela relocation;
+template <typename T>
+void AddRelocation(uint32_t addr,
+ uint32_t info,
+ int32_t addend,
+ std::vector<T>* relocations) {
+ T relocation;
relocation.r_offset = addr;
- relocation.r_info = ELF_R_INFO(0, ELF::kRelativeRelocationCode);
+ relocation.r_info = info;
relocation.r_addend = addend;
relocations->push_back(relocation);
}
-bool CheckRelocation(ELF::Addr addr,
- ELF::Sxword addend,
- const ELF::Rela& relocation) {
+template <typename T>
+bool CheckRelocation(uint32_t addr,
+ uint32_t info,
+ int32_t addend,
+ const T& relocation) {
return relocation.r_offset == addr &&
- ELF_R_SYM(relocation.r_info) == 0 &&
- ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode &&
+ relocation.r_info == info &&
relocation.r_addend == addend;
}
@@ -34,117 +36,188 @@
namespace relocation_packer {
-TEST(Delta, Encode) {
- std::vector<ELF::Rela> relocations;
- std::vector<ELF::Sxword> packed;
+template <typename ELF>
+static void encode() {
+ std::vector<typename ELF::Rela> relocations;
+ std::vector<typename ELF::Addr> packed;
- RelocationDeltaCodec codec;
+ RelocationDeltaCodec<ELF> codec;
- packed.clear();
codec.Encode(relocations, &packed);
- EXPECT_EQ(0, packed.size());
+ ASSERT_EQ(0U, packed.size());
// Initial relocation.
- AddRelocation(0xf00d0000, 10000, &relocations);
+ AddRelocation(0xf00d0000, 11U, 10000, &relocations);
- packed.clear();
codec.Encode(relocations, &packed);
- EXPECT_EQ(3, packed.size());
+ // size of reloc table, size of group, flags, 3 fields, zero
+ EXPECT_EQ(7U, packed.size());
// One pair present.
- EXPECT_EQ(1, packed[0]);
- // Delta from the neutral element is the initial relocation.
- EXPECT_EQ(0xf00d0000, packed[1]);
- EXPECT_EQ(10000, packed[2]);
+ size_t ndx = 0;
+ EXPECT_EQ(1U, packed[ndx++]);
+ EXPECT_EQ(0xf00d0000, packed[ndx++]);
+ EXPECT_EQ(1U, packed[ndx++]); // group_size
+ EXPECT_EQ(8U, packed[ndx++]); // flags
+ // Delta from the neutral element is zero
+ EXPECT_EQ(0U, packed[ndx++]); // offset_delta
+ EXPECT_EQ(11U, packed[ndx++]); // info
+ EXPECT_EQ(10000U, packed[ndx++]); // addend_delta
// Add a second relocation, 4 byte offset delta, 12 byte addend delta.
- AddRelocation(0xf00d0004, 10012, &relocations);
+ // same info
+ AddRelocation(0xf00d0004, 11U, 10012, &relocations);
packed.clear();
codec.Encode(relocations, &packed);
- EXPECT_EQ(5, packed.size());
- // Two pairs present.
- EXPECT_EQ(2, packed[0]);
- // Delta from the neutral element is the initial relocation.
- EXPECT_EQ(0xf00d0000, packed[1]);
- EXPECT_EQ(10000, packed[2]);
- // 4 byte offset delta, 12 byte addend delta.
- EXPECT_EQ(4, packed[3]);
- EXPECT_EQ(12, packed[4]);
+ ndx = 0;
+ EXPECT_EQ(8U, packed.size());
+
+ EXPECT_EQ(2U, packed[ndx++]); // relocs count
+ EXPECT_EQ(0xf00cfffc, packed[ndx++]); // initial offset
+ EXPECT_EQ(2U, packed[ndx++]); // group count
+ EXPECT_EQ(11U, packed[ndx++]); // flags
+ EXPECT_EQ(4U, packed[ndx++]); // group offset delta
+ EXPECT_EQ(11U, packed[ndx++]); // info
+
+ EXPECT_EQ(10000U, packed[ndx++]); // addend delta
+ EXPECT_EQ(12U, packed[ndx++]); // addend delta
// Add a third relocation, 4 byte offset delta, 12 byte addend delta.
- AddRelocation(0xf00d0008, 10024, &relocations);
+ // different info
+ AddRelocation(0xf00d0008, 41U, 10024, &relocations);
// Add three more relocations, 8 byte offset deltas, -24 byte addend deltas.
- AddRelocation(0xf00d0010, 10000, &relocations);
- AddRelocation(0xf00d0018, 9976, &relocations);
- AddRelocation(0xf00d0020, 9952, &relocations);
+ AddRelocation(0xf00d0010, 42U, 10000, &relocations);
+ AddRelocation(0xf00d0018, 42U, 9976, &relocations);
+ AddRelocation(0xf00d0020, 42U, 9952, &relocations);
+
+ AddRelocation(0xf00d2028, 1042U, 0, &relocations);
+ AddRelocation(0xf00d2030, 3442U, 0, &relocations);
packed.clear();
codec.Encode(relocations, &packed);
- EXPECT_EQ(13, packed.size());
- // Six pairs present.
- EXPECT_EQ(6, packed[0]);
+ ndx = 0;
+ EXPECT_EQ(26U, packed.size());
+ // Total number of relocs
+ EXPECT_EQ(8U, packed[ndx++]);
+ EXPECT_EQ(0xf00cfffc, packed[ndx++]);
+ // 2 in first group
+ EXPECT_EQ(2U, packed[ndx++]);
+ EXPECT_EQ(11U, packed[ndx++]); //flags
+ EXPECT_EQ(4U, packed[ndx++]); // group offset delta
+ EXPECT_EQ(11U, packed[ndx++]); // info
+
// Initial relocation.
- EXPECT_EQ(0xf00d0000, packed[1]);
- EXPECT_EQ(10000, packed[2]);
+ EXPECT_EQ(10000U, packed[ndx++]); // addend delta
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
- EXPECT_EQ(4, packed[3]);
- EXPECT_EQ(12, packed[4]);
- EXPECT_EQ(4, packed[5]);
- EXPECT_EQ(12, packed[6]);
+ EXPECT_EQ(12U, packed[ndx++]); // addend delta
+
+ // second group has only one reloc
+ EXPECT_EQ(1U, packed[ndx++]); // count
+ EXPECT_EQ(8U, packed[ndx++]); // flags
+
+ EXPECT_EQ(4U, packed[ndx++]); // offset delta
+ EXPECT_EQ(41U, packed[ndx++]); // info
+ EXPECT_EQ(12U, packed[ndx++]); // addend delta
+
+ // next - 3 relocs grouped by info
+ EXPECT_EQ(3U, packed[ndx++]); // count
+ EXPECT_EQ(11U, packed[ndx++]); // flags
+ EXPECT_EQ(8U, packed[ndx++]); // group offset delta
+ EXPECT_EQ(42U, packed[ndx++]); // info
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
- EXPECT_EQ(8, packed[7]);
- EXPECT_EQ(-24, packed[8]);
- EXPECT_EQ(8, packed[9]);
- EXPECT_EQ(-24, packed[10]);
- EXPECT_EQ(8, packed[11]);
- EXPECT_EQ(-24, packed[12]);
+ EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
+ EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
+ EXPECT_EQ(static_cast<typename ELF::Addr>(-24), packed[ndx++]);
+
+ // and last - 2 relocations without addend
+ EXPECT_EQ(2U, packed[ndx++]);
+ EXPECT_EQ(0U, packed[ndx++]); // flags
+ // offset_deltas and r_infos for next 2 relocations
+ EXPECT_EQ(0x2008U, packed[ndx++]); // offset delta
+ EXPECT_EQ(1042U, packed[ndx++]); // r_info
+ EXPECT_EQ(0x8U, packed[ndx++]); // offset delta
+ EXPECT_EQ(3442U, packed[ndx++]); // r_info
+
+ EXPECT_EQ(packed.size(), ndx);
}
-TEST(Delta, Decode) {
- std::vector<ELF::Sxword> packed;
- std::vector<ELF::Rela> relocations;
+TEST(Delta, Encode32) {
+ encode<ELF32_traits>();
+}
- RelocationDeltaCodec codec;
+TEST(Delta, Encode64) {
+ encode<ELF64_traits>();
+}
+
+template <typename ELF>
+static void decode() {
+ std::vector<typename ELF::Addr> packed;
+ std::vector<typename ELF::Rela> relocations;
+
+ RelocationDeltaCodec<ELF> codec;
codec.Decode(packed, &relocations);
- EXPECT_EQ(0, relocations.size());
+ EXPECT_EQ(0U, relocations.size());
// Six pairs.
- packed.push_back(6);
+ packed.push_back(6U); // count
+ packed.push_back(0xc0ddfffc); // base offset
+ packed.push_back(3U); // group count
+ packed.push_back(11U); // flags
+ packed.push_back(4U); // offset delta
+ packed.push_back(11U); // info
// Initial relocation.
- packed.push_back(0xc0de0000);
- packed.push_back(10000);
+ packed.push_back(10000U);
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
- packed.push_back(4);
- packed.push_back(12);
- packed.push_back(4);
- packed.push_back(12);
+ packed.push_back(12U); // addend
+ packed.push_back(12U); // addend
+
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
- packed.push_back(8);
- packed.push_back(-24);
- packed.push_back(8);
- packed.push_back(-24);
- packed.push_back(8);
- packed.push_back(-24);
+ packed.push_back(1U); // group count
+ packed.push_back(9U); // flags
+ packed.push_back(11U); // info
+
+ packed.push_back(8U);
+ packed.push_back(static_cast<typename ELF::Addr>(-24));
+ // next group with 2 relocs
+ packed.push_back(2U); // group count
+ packed.push_back(11U); // flags
+ packed.push_back(8U); // offset
+ packed.push_back(42U); // info
+
+ packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
+ packed.push_back(static_cast<typename ELF::Addr>(-24)); // addend
relocations.clear();
codec.Decode(packed, &relocations);
- EXPECT_EQ(6, relocations.size());
+ EXPECT_EQ(6U, relocations.size());
// Initial relocation.
- EXPECT_TRUE(CheckRelocation(0xc0de0000, 10000, relocations[0]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0000, 11U, 10000, relocations[0]));
// Two relocations, 4 byte offset deltas, 12 byte addend deltas.
- EXPECT_TRUE(CheckRelocation(0xc0de0004, 10012, relocations[1]));
- EXPECT_TRUE(CheckRelocation(0xc0de0008, 10024, relocations[2]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0004, 11U, 10012, relocations[1]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0008, 11U, 10024, relocations[2]));
// Three relocations, 8 byte offset deltas, -24 byte addend deltas.
- EXPECT_TRUE(CheckRelocation(0xc0de0010, 10000, relocations[3]));
- EXPECT_TRUE(CheckRelocation(0xc0de0018, 9976, relocations[4]));
- EXPECT_TRUE(CheckRelocation(0xc0de0020, 9952, relocations[5]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0010, 11U, 10000, relocations[3]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0018, 42U, 9976, relocations[4]));
+ EXPECT_TRUE(CheckRelocation(0xc0de0020, 42U, 9952, relocations[5]));
}
+TEST(Delta, Decode32) {
+ decode<ELF32_traits>();
+}
+
+TEST(Delta, Decode64) {
+ decode<ELF64_traits>();
+}
+
+// TODO (dimitry): add more tests (fix by 19 January 2038 03:14:07 UTC)
+// TODO (dimtiry): 1. Incorrect packed array for decode
+// TODO (dimtiry): 2. Try to catch situation where it is likely to get series of groups with size 1
+
} // namespace relocation_packer