Remove unused/unusable relocation packer files.
Removes: - src/run_length_encoder.h artifact of the original packing tool, not used here - test_data/generate_elf_file_unittest_relocs.sh - test_data/generate_elf_file_unittest_relocs.py test data generation for chromium/gyp, not usable here - README.TXT because it is now almost entirely outdated Change-Id: Ic4cd372647d9a365dc52833a6cc1cf66f0c95ec9
This commit is contained in:
parent
f5e0ba94d9
commit
d2bd5739ed
@ -1,135 +0,0 @@
|
|||||||
Introduction:
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Relative relocations are the bulk of dynamic relocations (the .rel.dyn
|
|
||||||
or .rela.dyn sections) in libchrome.<version>.so. The ELF standard
|
|
||||||
representation of them is wasteful.
|
|
||||||
|
|
||||||
Packing uses a combination of run length encoding, delta encoding, and LEB128
|
|
||||||
encoding to store them more efficiently. Packed relocations are placed in
|
|
||||||
a new .android.rel.dyn or .android.rela.dyn section. Packing reduces
|
|
||||||
the footprint of libchrome.<version>.so in the filesystem, in APK downloads,
|
|
||||||
and in memory when loaded on the device.
|
|
||||||
|
|
||||||
A packed libchrome.<version>.so is designed so that it can be loaded directly
|
|
||||||
on Android, but requires the explicit support of a crazy linker that has been
|
|
||||||
extended to understand packed relocations. Packed relocations are currently
|
|
||||||
only supported on ARM.
|
|
||||||
|
|
||||||
A packed libchrome.<version>.so cannot currently be used with the standard
|
|
||||||
Android runtime linker.
|
|
||||||
|
|
||||||
See src/*.h for design and implementation notes.
|
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
------
|
|
||||||
|
|
||||||
Packing does not adjust debug data. An unstripped libchrome.<version>.so
|
|
||||||
can be packed and will run, but may no longer be useful for debugging.
|
|
||||||
|
|
||||||
Unpacking on the device requires the explicit support of an extended crazy
|
|
||||||
linker. Adds the following new .dynamic tags, used by the crazy linker to
|
|
||||||
find the packed .android.rel.dyn or .android.rela.dyn section data:
|
|
||||||
|
|
||||||
DT_ANDROID_REL_OFFSET = DT_LOOS (Operating System specific: 0x6000000d)
|
|
||||||
- The offset of packed relocation data in libchrome.<version>.so
|
|
||||||
DT_ANDROID_REL_SIZE = DT_LOOS + 1 (Operating System Specific: 0x6000000e)
|
|
||||||
- The size of packed relocation data in bytes
|
|
||||||
|
|
||||||
32 bit ARM libraries use relocations without addends. 64 bit ARM libraries
|
|
||||||
use relocations with addends. The packing strategy necessarily differs for
|
|
||||||
the two relocation types.
|
|
||||||
|
|
||||||
Where libchrome.<version>.so contains relocations without addends, the format
|
|
||||||
of .android.rel.dyn data is:
|
|
||||||
|
|
||||||
"APR1" identifier
|
|
||||||
N: the number of count-delta pairs in the encoding
|
|
||||||
A: the initial offset
|
|
||||||
N * C,D: N count-delta pairs
|
|
||||||
|
|
||||||
Where libchrome.<version>.so contains relocations with addends, the format
|
|
||||||
of .android.rela.dyn data is:
|
|
||||||
|
|
||||||
"APA1" identifier
|
|
||||||
N: the number of addr-addend delta pairs in the encoding
|
|
||||||
N * A,V: N addr-addend delta pairs
|
|
||||||
|
|
||||||
All numbers in the encoding stream are stored as LEB128 values. For details
|
|
||||||
see http://en.wikipedia.org/wiki/LEB128.
|
|
||||||
|
|
||||||
The streaming unpacking algorithm for 32 bit ARM is:
|
|
||||||
|
|
||||||
skip over "APR1"
|
|
||||||
pairs, addr = next leb128 value, next leb128 value
|
|
||||||
emit R_ARM_RELATIVE relocation with r_offset = addr
|
|
||||||
while pairs:
|
|
||||||
count, delta = next leb128 value, next leb128 value
|
|
||||||
while count:
|
|
||||||
addr += delta
|
|
||||||
emit R_ARM_RELATIVE relocation with r_offset = addr
|
|
||||||
count--
|
|
||||||
pairs--
|
|
||||||
|
|
||||||
The streaming unpacking algorithm for 64 bit ARM is:
|
|
||||||
|
|
||||||
skip over "APA1"
|
|
||||||
pairs = next signed leb128 value
|
|
||||||
addr, addend = 0, 0
|
|
||||||
while pairs:
|
|
||||||
addr += next signed leb128 value
|
|
||||||
addend += next signed leb128 value
|
|
||||||
emit R_AARCH64_RELATIVE relocation with r_offset = addr, r_addend = addend
|
|
||||||
pairs--
|
|
||||||
|
|
||||||
|
|
||||||
Usage instructions:
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
To pack relocations, add an empty .android.rel.dyn or .android.rela.dyn and
|
|
||||||
then run the tool:
|
|
||||||
|
|
||||||
echo -n 'NULL' >/tmp/small
|
|
||||||
if file libchrome.<version>.so | grep -q 'ELF 32'; then
|
|
||||||
arm-linux-androideabi-objcopy
|
|
||||||
--add-section .android.rel.dyn=/tmp/small
|
|
||||||
libchrome.<version>.so libchrome.<version>.so.packed
|
|
||||||
else
|
|
||||||
aarch64-linux-android-objcopy
|
|
||||||
--add-section .android.rela.dyn=/tmp/small
|
|
||||||
libchrome.<version>.so libchrome.<version>.so.packed
|
|
||||||
fi
|
|
||||||
rm /tmp/small
|
|
||||||
relocation_packer libchrome.<version>.so.packed
|
|
||||||
|
|
||||||
To unpack and restore the shared library to its original state:
|
|
||||||
|
|
||||||
cp libchrome.<version>.so.packed unpackable
|
|
||||||
relocation_packer -u unpackable
|
|
||||||
if file libchrome.<version>.so | grep -q 'ELF 32'; then
|
|
||||||
arm-linux-androideabi-objcopy \
|
|
||||||
--remove-section=.android.rel.dyn unpackable libchrome.<version>.so
|
|
||||||
else
|
|
||||||
aarch64-linux-android-objcopy \
|
|
||||||
--remove-section=.android.rela.dyn unpackable libchrome.<version>.so
|
|
||||||
endif
|
|
||||||
rm unpackable
|
|
||||||
|
|
||||||
|
|
||||||
Bugs & TODOs:
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Requires two free slots in the .dynamic section. Uses these to add data that
|
|
||||||
tells the crazy linker where to find the packed relocation data. Fails
|
|
||||||
if insufficient free slots exist (use gold --spare-dynamic-slots to increase
|
|
||||||
the allocation).
|
|
||||||
|
|
||||||
Requires libelf 0.158 or later. Earlier libelf releases may be buggy in
|
|
||||||
ways that prevent the packer from working correctly.
|
|
||||||
|
|
||||||
|
|
||||||
Testing:
|
|
||||||
--------
|
|
||||||
|
|
||||||
Unittests run under gtest, on the host system.
|
|
@ -1,81 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Run-length encode and decode relative relocations.
|
|
||||||
//
|
|
||||||
// Relative relocations are the bulk of dynamic relocations (the
|
|
||||||
// .rel.dyn or .rela.dyn sections) in libchrome.<version>.so, and the ELF
|
|
||||||
// standard representation of them is wasteful. .rel.dyn contains
|
|
||||||
// relocations without addends, .rela.dyn relocations with addends.
|
|
||||||
//
|
|
||||||
// A relocation with no addend is 8 bytes on 32 bit platforms and 16 bytes
|
|
||||||
// on 64 bit plaforms, split into offset and info fields. Offsets strictly
|
|
||||||
// increase, and each is commonly a few bytes different from its predecessor.
|
|
||||||
// There are long runs where the difference does not change. The info field
|
|
||||||
// is constant. Example, from 'readelf -x4 libchrome.<version>.so' 32 bit:
|
|
||||||
//
|
|
||||||
// offset info offset info
|
|
||||||
// 808fef01 17000000 848fef01 17000000 ................
|
|
||||||
// 888fef01 17000000 8c8fef01 17000000 ................
|
|
||||||
// 908fef01 17000000 948fef01 17000000 ................
|
|
||||||
//
|
|
||||||
// Run length encoding packs this data more efficiently, by representing it
|
|
||||||
// as a delta and a count of entries each differing from its predecessor
|
|
||||||
// by this delta. The above can be represented as a start address followed
|
|
||||||
// by an encoded count of 6 and offset difference of 4:
|
|
||||||
//
|
|
||||||
// start count diff
|
|
||||||
// 01ef8f80 00000006 00000004
|
|
||||||
//
|
|
||||||
// Because relative relocation offsets strictly increase, the complete
|
|
||||||
// set of relative relocations in libchrome.<version>.so can be
|
|
||||||
// represented by a single start address followed by one or more difference
|
|
||||||
// and count encoded word pairs:
|
|
||||||
//
|
|
||||||
// start run1 count run1 diff run2 count run2 diff
|
|
||||||
// 01ef8f80 00000006 00000004 00000010 00000008 ...
|
|
||||||
//
|
|
||||||
// Decoding regenerates relative relocations beginning at address
|
|
||||||
// 'start' and for each encoded run, incrementing the address by 'difference'
|
|
||||||
// for 'count' iterations and emitting a new relative relocation.
|
|
||||||
//
|
|
||||||
// Once encoded, data is prefixed by a single word count of packed delta and
|
|
||||||
// count pairs. A final run-length encoded relative relocations vector
|
|
||||||
// might therefore look something like:
|
|
||||||
//
|
|
||||||
// pairs start run 1 run 2 ... run 15
|
|
||||||
// 0000000f 01ef8f80 00000006 00000004 00000010 00000008 ...
|
|
||||||
// Interpreted as:
|
|
||||||
// pairs=15 start=.. count=6,delta=4 count=16,delta=8
|
|
||||||
|
|
||||||
#ifndef TOOLS_RELOCATION_PACKER_SRC_RUN_LENGTH_ENCODER_H_
|
|
||||||
#define TOOLS_RELOCATION_PACKER_SRC_RUN_LENGTH_ENCODER_H_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "elf.h"
|
|
||||||
#include "elf_traits.h"
|
|
||||||
|
|
||||||
namespace relocation_packer {
|
|
||||||
|
|
||||||
// A RelocationRunLengthCodec packs vectors of relative relocations
|
|
||||||
// into more compact forms, and unpacks them to reproduce the pre-packed data.
|
|
||||||
class RelocationRunLengthCodec {
|
|
||||||
public:
|
|
||||||
// Encode relative relocations into a more compact form.
|
|
||||||
// |relocations| is a vector of relative relocation structs.
|
|
||||||
// |packed| is the vector of packed words into which relocations are packed.
|
|
||||||
static void Encode(const std::vector<ELF::Rel>& relocations,
|
|
||||||
std::vector<ELF::Xword>* packed);
|
|
||||||
|
|
||||||
// Decode relative relocations from their more compact form.
|
|
||||||
// |packed| is the vector of packed relocations.
|
|
||||||
// |relocations| is a vector of unpacked relative relocation structs.
|
|
||||||
static void Decode(const std::vector<ELF::Xword>& packed,
|
|
||||||
std::vector<ELF::Rel>* relocations);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace relocation_packer
|
|
||||||
|
|
||||||
#endif // TOOLS_RELOCATION_PACKER_SRC_RUN_LENGTH_ENCODER_H_
|
|
@ -1,88 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""Build relocation packer unit test data.
|
|
||||||
|
|
||||||
Uses a built relocation packer to generate 'golden' reference test data
|
|
||||||
files for elf_file_unittests.cc.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import optparse
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
def PackArmLibraryRelocations(android_pack_relocations,
|
|
||||||
android_objcopy,
|
|
||||||
added_section,
|
|
||||||
input_path,
|
|
||||||
output_path):
|
|
||||||
# Copy and add a 'NULL' .android.rel.dyn section for the packing tool.
|
|
||||||
with tempfile.NamedTemporaryFile() as stream:
|
|
||||||
stream.write('NULL')
|
|
||||||
stream.flush()
|
|
||||||
objcopy_command = [android_objcopy,
|
|
||||||
'--add-section', '%s=%s' % (added_section, stream.name),
|
|
||||||
input_path, output_path]
|
|
||||||
subprocess.check_call(objcopy_command)
|
|
||||||
|
|
||||||
# Pack relocations.
|
|
||||||
pack_command = [android_pack_relocations, output_path]
|
|
||||||
subprocess.check_call(pack_command)
|
|
||||||
|
|
||||||
|
|
||||||
def UnpackArmLibraryRelocations(android_pack_relocations,
|
|
||||||
input_path,
|
|
||||||
output_path):
|
|
||||||
shutil.copy(input_path, output_path)
|
|
||||||
|
|
||||||
# Unpack relocations. We leave the .android.rel.dyn or .android.rela.dyn
|
|
||||||
# in place.
|
|
||||||
unpack_command = [android_pack_relocations, '-u', output_path]
|
|
||||||
subprocess.check_call(unpack_command)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = optparse.OptionParser()
|
|
||||||
|
|
||||||
parser.add_option('--android-pack-relocations',
|
|
||||||
help='Path to the ARM relocations packer binary')
|
|
||||||
parser.add_option('--android-objcopy',
|
|
||||||
help='Path to the toolchain\'s objcopy binary')
|
|
||||||
parser.add_option('--added-section',
|
|
||||||
choices=['.android.rel.dyn', '.android.rela.dyn'],
|
|
||||||
help='Section to add, one of ".android.rel.dyn" or ".android.rela.dyn"')
|
|
||||||
parser.add_option('--test-file',
|
|
||||||
help='Path to the input test file, an unpacked ARM .so')
|
|
||||||
parser.add_option('--unpacked-output',
|
|
||||||
help='Path to the output file for reference unpacked data')
|
|
||||||
parser.add_option('--packed-output',
|
|
||||||
help='Path to the output file for reference packed data')
|
|
||||||
|
|
||||||
options, _ = parser.parse_args()
|
|
||||||
|
|
||||||
for output in [options.unpacked_output, options.packed_output]:
|
|
||||||
directory = os.path.dirname(output)
|
|
||||||
if not os.path.exists(directory):
|
|
||||||
os.makedirs(directory)
|
|
||||||
|
|
||||||
PackArmLibraryRelocations(options.android_pack_relocations,
|
|
||||||
options.android_objcopy,
|
|
||||||
options.added_section,
|
|
||||||
options.test_file,
|
|
||||||
options.packed_output)
|
|
||||||
|
|
||||||
UnpackArmLibraryRelocations(options.android_pack_relocations,
|
|
||||||
options.packed_output,
|
|
||||||
options.unpacked_output)
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
@ -1,35 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# Generates elf_file_unittest_relocs_arm{32,64}{,_packed}.so test data files
|
|
||||||
# from elf_file_unittest_relocs.cc. Run once to create these test data
|
|
||||||
# files; the files are checked into the source tree.
|
|
||||||
#
|
|
||||||
# To use:
|
|
||||||
# ./generate_elf_file_unittest_relocs.sh
|
|
||||||
# git add elf_file_unittest_relocs_arm{32,64}{,_packed}.so
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
local '-r' test_data_directory="$(pwd)"
|
|
||||||
cd '../../..'
|
|
||||||
|
|
||||||
source tools/cr/cr-bash-helpers.sh
|
|
||||||
local arch
|
|
||||||
for arch in 'arm32' 'arm64'; do
|
|
||||||
cr 'init' '--platform=android' '--type=Debug' '--architecture='"${arch}"
|
|
||||||
cr 'build' 'relocation_packer_unittests_test_data'
|
|
||||||
done
|
|
||||||
|
|
||||||
local '-r' packer='out_android/Debug/obj/tools/relocation_packer'
|
|
||||||
local '-r' gen="${packer}/relocation_packer_unittests_test_data.gen"
|
|
||||||
|
|
||||||
cp "${gen}/elf_file_unittest_relocs_arm"{32,64}{,_packed}'.so' \
|
|
||||||
"${test_data_directory}"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
main
|
|
Loading…
Reference in New Issue
Block a user