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