| Index: third_party/android_platform/relocation_packer/src/packer.cc
|
| diff --git a/third_party/android_platform/relocation_packer/src/packer.cc b/third_party/android_platform/relocation_packer/src/packer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e30612e550601a474d114b8e36d7a9dc8192984
|
| --- /dev/null
|
| +++ b/third_party/android_platform/relocation_packer/src/packer.cc
|
| @@ -0,0 +1,88 @@
|
| +// Copyright 2014 The Chromium 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 "packer.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "debug.h"
|
| +#include "delta_encoder.h"
|
| +#include "elf_traits.h"
|
| +#include "leb128.h"
|
| +#include "sleb128.h"
|
| +
|
| +namespace relocation_packer {
|
| +
|
| +// Pack relocations into a group encoded packed representation.
|
| +template <typename ELF>
|
| +void RelocationPacker<ELF>::PackRelocations(const std::vector<typename ELF::Rela>& relocations,
|
| + std::vector<uint8_t>* packed) {
|
| + // Run-length encode.
|
| + std::vector<typename ELF::Addr> packed_words;
|
| + RelocationDeltaCodec<ELF> codec;
|
| + codec.Encode(relocations, &packed_words);
|
| +
|
| + // If insufficient data do nothing.
|
| + if (packed_words.empty())
|
| + return;
|
| +
|
| + Sleb128Encoder<typename ELF::Addr> sleb128_encoder;
|
| + Leb128Encoder<typename ELF::Addr> leb128_encoder;
|
| +
|
| + std::vector<uint8_t> leb128_packed;
|
| + std::vector<uint8_t> sleb128_packed;
|
| +
|
| + leb128_encoder.EnqueueAll(packed_words);
|
| + leb128_encoder.GetEncoding(&leb128_packed);
|
| +
|
| + sleb128_encoder.EnqueueAll(packed_words);
|
| + sleb128_encoder.GetEncoding(&sleb128_packed);
|
| +
|
| + // TODO (simonb): Estimate savings on current android system image and consider using
|
| + // one encoder for all packed relocations to reduce complexity.
|
| + if (leb128_packed.size() <= sleb128_packed.size()) {
|
| + packed->push_back('A');
|
| + packed->push_back('P');
|
| + packed->push_back('U');
|
| + packed->push_back('2');
|
| + packed->insert(packed->end(), leb128_packed.begin(), leb128_packed.end());
|
| + } else {
|
| + packed->push_back('A');
|
| + packed->push_back('P');
|
| + packed->push_back('S');
|
| + packed->push_back('2');
|
| + packed->insert(packed->end(), sleb128_packed.begin(), sleb128_packed.end());
|
| + }
|
| +}
|
| +
|
| +// Unpack relative relocations from a run-length encoded packed
|
| +// representation.
|
| +template <typename ELF>
|
| +void RelocationPacker<ELF>::UnpackRelocations(
|
| + const std::vector<uint8_t>& packed,
|
| + std::vector<typename ELF::Rela>* relocations) {
|
| +
|
| + std::vector<typename ELF::Addr> packed_words;
|
| + CHECK(packed.size() > 4 &&
|
| + packed[0] == 'A' &&
|
| + packed[1] == 'P' &&
|
| + (packed[2] == 'U' || packed[2] == 'S') &&
|
| + packed[3] == '2');
|
| +
|
| + if (packed[2] == 'U') {
|
| + Leb128Decoder<typename ELF::Addr> decoder(packed, 4);
|
| + decoder.DequeueAll(&packed_words);
|
| + } else {
|
| + Sleb128Decoder<typename ELF::Addr> decoder(packed, 4);
|
| + decoder.DequeueAll(&packed_words);
|
| + }
|
| +
|
| + RelocationDeltaCodec<ELF> codec;
|
| + codec.Decode(packed_words, relocations);
|
| +}
|
| +
|
| +template class RelocationPacker<ELF32_traits>;
|
| +template class RelocationPacker<ELF64_traits>;
|
| +
|
| +} // namespace relocation_packer
|
|
|