Make Chromoting browser tests pass again
[chromium-blink-merge.git] / tools / relocation_packer / src / main.cc
blob28f5b0469878f7ae687c86ad9db6e5f141a4cea7
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Tool to pack and unpack relative relocations in a shared library.
6 //
7 // Packing removes relative relocations from .rel.dyn and writes them
8 // in a more compact form to .android.rel.dyn. Unpacking does the reverse.
9 //
10 // Invoke with -v to trace actions taken when packing or unpacking.
11 // Invoke with -p to pad removed relocations with R_*_NONE. Suppresses
12 // shrinking of .rel.dyn.
13 // See PrintUsage() below for full usage details.
15 // NOTE: Breaks with libelf 0.152, which is buggy. libelf 0.158 works.
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <getopt.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <string>
26 #include "debug.h"
27 #include "elf_file.h"
28 #include "libelf.h"
30 namespace {
32 void PrintUsage(const char* argv0) {
33 std::string temporary = argv0;
34 const size_t last_slash = temporary.find_last_of("/");
35 if (last_slash != temporary.npos) {
36 temporary.erase(0, last_slash + 1);
38 const char* basename = temporary.c_str();
40 printf(
41 "Usage: %s [-u] [-v] [-p] file\n\n"
42 "Pack or unpack relative relocations in a shared library.\n\n"
43 " -u, --unpack unpack previously packed relative relocations\n"
44 " -v, --verbose trace object file modifications (for debugging)\n"
45 " -p, --pad do not shrink relocations, but pad (for debugging)\n\n",
46 basename);
48 if (ELF::kMachine == EM_ARM) {
49 printf(
50 "Extracts relative relocations from the .rel.dyn section, packs them\n"
51 "into a more compact format, and stores the packed relocations in\n"
52 ".android.rel.dyn. Expands .android.rel.dyn to hold the packed\n"
53 "data, and shrinks .rel.dyn by the amount of unpacked data removed\n"
54 "from it.\n\n"
55 "Before being packed, a shared library needs to be prepared by adding\n"
56 "a null .android.rel.dyn section.\n\n"
57 "To pack relocations in a shared library:\n\n"
58 " echo -n 'NULL' >/tmp/small\n"
59 " arm-linux-androideabi-objcopy \\\n"
60 " --add-section .android.rel.dyn=/tmp/small \\\n"
61 " libchrome.<version>.so\n"
62 " rm /tmp/small\n"
63 " %s libchrome.<version>.so\n\n"
64 "To unpack and restore the shared library to its original state:\n\n"
65 " %s -u libchrome.<version>.so\n"
66 " arm-linux-androideabi-objcopy \\\n"
67 " --remove-section=.android.rel.dyn libchrome.<version>.so\n\n",
68 basename, basename);
69 } else if (ELF::kMachine == EM_AARCH64) {
70 printf(
71 "Extracts relative relocations from the .rela.dyn section, packs them\n"
72 "into a more compact format, and stores the packed relocations in\n"
73 ".android.rela.dyn. Expands .android.rela.dyn to hold the packed\n"
74 "data, and shrinks .rela.dyn by the amount of unpacked data removed\n"
75 "from it.\n\n"
76 "Before being packed, a shared library needs to be prepared by adding\n"
77 "a null .android.rela.dyn section.\n\n"
78 "To pack relocations in a shared library:\n\n"
79 " echo -n 'NULL' >/tmp/small\n"
80 " aarch64-linux-android-objcopy \\\n"
81 " --add-section .android.rela.dyn=/tmp/small \\\n"
82 " libchrome.<version>.so\n"
83 " rm /tmp/small\n"
84 " %s libchrome.<version>.so\n\n"
85 "To unpack and restore the shared library to its original state:\n\n"
86 " %s -u libchrome.<version>.so\n"
87 " aarch64-linux-android-objcopy \\\n"
88 " --remove-section=.android.rela.dyn libchrome.<version>.so\n\n",
89 basename, basename);
90 } else {
91 NOTREACHED();
94 printf(
95 "Debug sections are not handled, so packing should not be used on\n"
96 "shared libraries compiled for debugging or otherwise unstripped.\n");
99 } // namespace
101 int main(int argc, char* argv[]) {
102 bool is_unpacking = false;
103 bool is_verbose = false;
104 bool is_padding = false;
106 static const option options[] = {
107 {"unpack", 0, 0, 'u'}, {"verbose", 0, 0, 'v'}, {"pad", 0, 0, 'p'},
108 {"help", 0, 0, 'h'}, {NULL, 0, 0, 0}
110 bool has_options = true;
111 while (has_options) {
112 int c = getopt_long(argc, argv, "uvph", options, NULL);
113 switch (c) {
114 case 'u':
115 is_unpacking = true;
116 break;
117 case 'v':
118 is_verbose = true;
119 break;
120 case 'p':
121 is_padding = true;
122 break;
123 case 'h':
124 PrintUsage(argv[0]);
125 return 0;
126 case '?':
127 LOG(INFO) << "Try '" << argv[0] << " --help' for more information.";
128 return 1;
129 case -1:
130 has_options = false;
131 break;
132 default:
133 NOTREACHED();
134 return 1;
137 if (optind != argc - 1) {
138 LOG(INFO) << "Try '" << argv[0] << " --help' for more information.";
139 return 1;
142 if (elf_version(EV_CURRENT) == EV_NONE) {
143 LOG(WARNING) << "Elf Library is out of date!";
146 LOG(INFO) << "Configured for " << ELF::Machine();
148 const char* file = argv[argc - 1];
149 const int fd = open(file, O_RDWR);
150 if (fd == -1) {
151 LOG(ERROR) << file << ": " << strerror(errno);
152 return 1;
155 if (is_verbose)
156 relocation_packer::Logger::SetVerbose(1);
158 relocation_packer::ElfFile elf_file(fd);
159 elf_file.SetPadding(is_padding);
161 bool status;
162 if (is_unpacking)
163 status = elf_file.UnpackRelocations();
164 else
165 status = elf_file.PackRelocations();
167 close(fd);
169 if (!status) {
170 LOG(ERROR) << file << ": failed to pack/unpack file";
171 return 1;
174 return 0;