Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: tools/relocation_packer/src/elf_file.cc

Issue 410933004: Extend relocation packing to cover arm64. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to master Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "elf_file.h" 5 #include "elf_file.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 #include <sys/types.h> 8 #include <sys/types.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 #include <string> 10 #include <string>
11 #include <vector> 11 #include <vector>
12 12
13 #include "debug.h" 13 #include "debug.h"
14 #include "elf_traits.h" 14 #include "elf_traits.h"
15 #include "libelf.h" 15 #include "libelf.h"
16 #include "packer.h" 16 #include "packer.h"
17 17
18 namespace relocation_packer { 18 namespace relocation_packer {
19 19
20 // Stub identifier written to 'null out' packed data, "NULL". 20 // Stub identifier written to 'null out' packed data, "NULL".
21 static const uint32_t kStubIdentifier = 0x4c4c554eu; 21 static const uint32_t kStubIdentifier = 0x4c4c554eu;
22 22
23 // Out-of-band dynamic tags used to indicate the offset and size of the 23 // Out-of-band dynamic tags used to indicate the offset and size of the
24 // .android.rel.dyn section. 24 // android packed relocations section.
25 static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS; 25 static const ELF::Sword DT_ANDROID_REL_OFFSET = DT_LOOS;
26 static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1; 26 static const ELF::Sword DT_ANDROID_REL_SIZE = DT_LOOS + 1;
27 27
28 // Alignment to preserve, in bytes. This must be at least as large as the 28 // Alignment to preserve, in bytes. This must be at least as large as the
29 // largest d_align and sh_addralign values found in the loaded file. 29 // largest d_align and sh_addralign values found in the loaded file.
30 static const size_t kPreserveAlignment = 256; 30 static const size_t kPreserveAlignment = 256;
31 31
32 namespace { 32 namespace {
33 33
34 // Get section data. Checks that the section has exactly one data entry, 34 // Get section data. Checks that the section has exactly one data entry,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 VLOG(1) << " data"; 102 VLOG(1) << " data";
103 VLOG(1) << " d_buf = " << data->d_buf; 103 VLOG(1) << " d_buf = " << data->d_buf;
104 VLOG(1) << " d_off = " << data->d_off; 104 VLOG(1) << " d_off = " << data->d_off;
105 VLOG(1) << " d_size = " << data->d_size; 105 VLOG(1) << " d_size = " << data->d_size;
106 VLOG(1) << " d_align = " << data->d_align; 106 VLOG(1) << " d_align = " << data->d_align;
107 } 107 }
108 108
109 } // namespace 109 } // namespace
110 110
111 // Load the complete ELF file into a memory image in libelf, and identify 111 // Load the complete ELF file into a memory image in libelf, and identify
112 // the .rel.dyn, .dynamic, and .android.rel.dyn sections. No-op if the 112 // the .rel.dyn or .rela.dyn, .dynamic, and .android.rel.dyn or
113 // ELF file has already been loaded. 113 // .android.rela.dyn sections. No-op if the ELF file has already been loaded.
114 bool ElfFile::Load() { 114 bool ElfFile::Load() {
115 if (elf_) 115 if (elf_)
116 return true; 116 return true;
117 117
118 Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL); 118 Elf* elf = elf_begin(fd_, ELF_C_RDWR, NULL);
119 CHECK(elf); 119 CHECK(elf);
120 120
121 if (elf_kind(elf) != ELF_K_ELF) { 121 if (elf_kind(elf) != ELF_K_ELF) {
122 LOG(ERROR) << "File not in ELF format"; 122 LOG(ERROR) << "File not in ELF format";
123 return false; 123 return false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 if (program_header->p_type == PT_DYNAMIC) { 157 if (program_header->p_type == PT_DYNAMIC) {
158 CHECK(dynamic_program_header == NULL); 158 CHECK(dynamic_program_header == NULL);
159 dynamic_program_header = program_header; 159 dynamic_program_header = program_header;
160 } 160 }
161 } 161 }
162 CHECK(dynamic_program_header != NULL); 162 CHECK(dynamic_program_header != NULL);
163 163
164 size_t string_index; 164 size_t string_index;
165 elf_getshdrstrndx(elf, &string_index); 165 elf_getshdrstrndx(elf, &string_index);
166 166
167 // Notes of the .rel.dyn, .android.rel.dyn, and .dynamic sections. Found 167 // Notes of the dynamic relocations, packed relocations, and .dynamic
168 // while iterating sections, and later stored in class attributes. 168 // sections. Found while iterating sections, and later stored in class
169 Elf_Scn* found_rel_dyn_section = NULL; 169 // attributes.
170 Elf_Scn* found_android_rel_dyn_section = NULL; 170 Elf_Scn* found_relocations_section = NULL;
171 Elf_Scn* found_android_relocations_section = NULL;
171 Elf_Scn* found_dynamic_section = NULL; 172 Elf_Scn* found_dynamic_section = NULL;
172 173
174 // Notes of relocation section types seen. We require one or the other of
175 // these; both is unsupported.
176 bool has_rel_relocations = false;
177 bool has_rela_relocations = false;
178
173 // Flag set if we encounter any .debug* section. We do not adjust any 179 // Flag set if we encounter any .debug* section. We do not adjust any
174 // offsets or addresses of any debug data, so if we find one of these then 180 // offsets or addresses of any debug data, so if we find one of these then
175 // the resulting output shared object should still run, but might not be 181 // the resulting output shared object should still run, but might not be
176 // usable for debugging, disassembly, and so on. Provides a warning if 182 // usable for debugging, disassembly, and so on. Provides a warning if
177 // this occurs. 183 // this occurs.
178 bool has_debug_section = false; 184 bool has_debug_section = false;
179 185
180 Elf_Scn* section = NULL; 186 Elf_Scn* section = NULL;
181 while ((section = elf_nextscn(elf, section)) != NULL) { 187 while ((section = elf_nextscn(elf, section)) != NULL) {
182 const ELF::Shdr* section_header = ELF::getshdr(section); 188 const ELF::Shdr* section_header = ELF::getshdr(section);
183 std::string name = elf_strptr(elf, string_index, section_header->sh_name); 189 std::string name = elf_strptr(elf, string_index, section_header->sh_name);
184 VerboseLogSectionHeader(name, section_header); 190 VerboseLogSectionHeader(name, section_header);
185 191
192 // Note relocation section types.
193 if (section_header->sh_type == SHT_REL) {
194 has_rel_relocations = true;
195 }
196 if (section_header->sh_type == SHT_RELA) {
197 has_rela_relocations = true;
198 }
199
186 // Note special sections as we encounter them. 200 // Note special sections as we encounter them.
187 if (name == ".rel.dyn") { 201 if (name == ".rel.dyn" || name == ".rela.dyn") {
188 found_rel_dyn_section = section; 202 found_relocations_section = section;
189 } 203 }
190 if (name == ".android.rel.dyn") { 204 if (name == ".android.rel.dyn" || name == ".android.rela.dyn") {
191 found_android_rel_dyn_section = section; 205 found_android_relocations_section = section;
192 } 206 }
193 if (section_header->sh_offset == dynamic_program_header->p_offset) { 207 if (section_header->sh_offset == dynamic_program_header->p_offset) {
194 found_dynamic_section = section; 208 found_dynamic_section = section;
195 } 209 }
196 210
197 // If we find a section named .debug*, set the debug warning flag. 211 // If we find a section named .debug*, set the debug warning flag.
198 if (std::string(name).find(".debug") == 0) { 212 if (std::string(name).find(".debug") == 0) {
199 has_debug_section = true; 213 has_debug_section = true;
200 } 214 }
201 215
202 // Ensure we preserve alignment, repeated later for the data block(s). 216 // Ensure we preserve alignment, repeated later for the data block(s).
203 CHECK(section_header->sh_addralign <= kPreserveAlignment); 217 CHECK(section_header->sh_addralign <= kPreserveAlignment);
204 218
205 Elf_Data* data = NULL; 219 Elf_Data* data = NULL;
206 while ((data = elf_getdata(section, data)) != NULL) { 220 while ((data = elf_getdata(section, data)) != NULL) {
207 CHECK(data->d_align <= kPreserveAlignment); 221 CHECK(data->d_align <= kPreserveAlignment);
208 VerboseLogSectionData(data); 222 VerboseLogSectionData(data);
209 } 223 }
210 } 224 }
211 225
212 // Loading failed if we did not find the required special sections. 226 // Loading failed if we did not find the required special sections.
213 if (!found_rel_dyn_section) { 227 if (!found_relocations_section) {
214 LOG(ERROR) << "Missing .rel.dyn section"; 228 LOG(ERROR) << "Missing .rel.dyn or .rela.dyn section";
215 return false; 229 return false;
216 } 230 }
217 if (!found_dynamic_section) { 231 if (!found_dynamic_section) {
218 LOG(ERROR) << "Missing .dynamic section"; 232 LOG(ERROR) << "Missing .dynamic section";
219 return false; 233 return false;
220 } 234 }
221 if (!found_android_rel_dyn_section) { 235 if (!found_android_relocations_section) {
222 LOG(ERROR) << "Missing .android.rel.dyn section " 236 LOG(ERROR) << "Missing .android.rel.dyn or .android.rela.dyn section "
223 << "(to fix, run with --help and follow the pre-packing " 237 << "(to fix, run with --help and follow the pre-packing "
224 << "instructions)"; 238 << "instructions)";
225 return false; 239 return false;
226 } 240 }
227 241
242 // Loading failed if we could not identify the relocations type.
243 if (!has_rel_relocations && !has_rela_relocations) {
244 LOG(ERROR) << "No relocations sections found";
245 return false;
246 }
247 if (has_rel_relocations && has_rela_relocations) {
248 LOG(ERROR) << "Multiple relocations sections with different types found, "
249 << "not currently supported";
250 return false;
251 }
252
228 if (has_debug_section) { 253 if (has_debug_section) {
229 LOG(WARNING) << "Found .debug section(s), and ignored them"; 254 LOG(WARNING) << "Found .debug section(s), and ignored them";
230 } 255 }
231 256
232 elf_ = elf; 257 elf_ = elf;
233 rel_dyn_section_ = found_rel_dyn_section; 258 relocations_section_ = found_relocations_section;
234 dynamic_section_ = found_dynamic_section; 259 dynamic_section_ = found_dynamic_section;
235 android_rel_dyn_section_ = found_android_rel_dyn_section; 260 android_relocations_section_ = found_android_relocations_section;
261 relocations_type_ = has_rel_relocations ? REL : RELA;
236 return true; 262 return true;
237 } 263 }
238 264
239 namespace { 265 namespace {
240 266
241 // Helper for ResizeSection(). Adjust the main ELF header for the hole. 267 // Helper for ResizeSection(). Adjust the main ELF header for the hole.
242 void AdjustElfHeaderForHole(ELF::Ehdr* elf_header, 268 void AdjustElfHeaderForHole(ELF::Ehdr* elf_header,
243 ELF::Off hole_start, 269 ELF::Off hole_start,
244 ssize_t hole_size) { 270 ssize_t hole_size) {
245 if (elf_header->e_phoff > hole_start) { 271 if (elf_header->e_phoff > hole_start) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 if (section_header->sh_addr != 0) { 337 if (section_header->sh_addr != 0) {
312 section_header->sh_addr += hole_size; 338 section_header->sh_addr += hole_size;
313 VLOG(1) << "section " << name 339 VLOG(1) << "section " << name
314 << " sh_addr adjusted to " << section_header->sh_addr; 340 << " sh_addr adjusted to " << section_header->sh_addr;
315 } 341 }
316 } 342 }
317 } 343 }
318 } 344 }
319 345
320 // Helper for ResizeSection(). Adjust the .dynamic section for the hole. 346 // Helper for ResizeSection(). Adjust the .dynamic section for the hole.
347 template <typename Rel>
321 void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, 348 void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
322 bool is_rel_dyn_resize, 349 bool is_relocations_resize,
323 ELF::Off hole_start, 350 ELF::Off hole_start,
324 ssize_t hole_size) { 351 ssize_t hole_size) {
325 Elf_Data* data = GetSectionData(dynamic_section); 352 Elf_Data* data = GetSectionData(dynamic_section);
326 353
327 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); 354 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
328 std::vector<ELF::Dyn> dynamics( 355 std::vector<ELF::Dyn> dynamics(
329 dynamic_base, 356 dynamic_base,
330 dynamic_base + data->d_size / sizeof(dynamics[0])); 357 dynamic_base + data->d_size / sizeof(dynamics[0]));
331 358
332 for (size_t i = 0; i < dynamics.size(); ++i) { 359 for (size_t i = 0; i < dynamics.size(); ++i) {
(...skipping 11 matching lines...) Expand all
344 tag == DT_JMPREL || 371 tag == DT_JMPREL ||
345 tag == DT_INIT_ARRAY || 372 tag == DT_INIT_ARRAY ||
346 tag == DT_FINI_ARRAY || 373 tag == DT_FINI_ARRAY ||
347 tag == DT_ANDROID_REL_OFFSET); 374 tag == DT_ANDROID_REL_OFFSET);
348 if (is_adjustable && dynamic->d_un.d_ptr > hole_start) { 375 if (is_adjustable && dynamic->d_un.d_ptr > hole_start) {
349 dynamic->d_un.d_ptr += hole_size; 376 dynamic->d_un.d_ptr += hole_size;
350 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag 377 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
351 << " d_ptr adjusted to " << dynamic->d_un.d_ptr; 378 << " d_ptr adjusted to " << dynamic->d_un.d_ptr;
352 } 379 }
353 380
354 // If we are specifically resizing .rel.dyn, we need to make some added 381 // If we are specifically resizing dynamic relocations, we need to make
355 // adjustments to tags that indicate the counts of ARM relative 382 // some added adjustments to tags that indicate the counts of relative
356 // relocations in the shared object. 383 // relocations in the shared object.
357 if (!is_rel_dyn_resize) 384 if (!is_relocations_resize)
358 continue; 385 continue;
359 386
360 // DT_RELSZ is the overall size of relocations. Adjust by hole size. 387 // DT_RELSZ is the overall size of relocations. Adjust by hole size.
361 if (tag == DT_RELSZ) { 388 if (tag == DT_RELSZ) {
362 dynamic->d_un.d_val += hole_size; 389 dynamic->d_un.d_val += hole_size;
363 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag 390 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
364 << " d_val adjusted to " << dynamic->d_un.d_val; 391 << " d_val adjusted to " << dynamic->d_un.d_val;
365 } 392 }
366 393
367 // DT_RELCOUNT is the count of relative relocations. Packing reduces it 394 // DT_RELCOUNT is the count of relative relocations. Packing reduces it
368 // to the alignment padding, if any; unpacking restores it to its former 395 // to the alignment padding, if any; unpacking restores it to its former
369 // value. The crazy linker does not use it, but we update it anyway. 396 // value. The crazy linker does not use it, but we update it anyway.
370 if (tag == DT_RELCOUNT) { 397 if (tag == DT_RELCOUNT) {
371 // Cast sizeof to a signed type to avoid the division result being 398 // Cast sizeof to a signed type to avoid the division result being
372 // promoted into an unsigned size_t. 399 // promoted into an unsigned size_t.
373 const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(ELF::Rel)); 400 const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Rel));
374 dynamic->d_un.d_val += hole_size / sizeof_rel; 401 dynamic->d_un.d_val += hole_size / sizeof_rel;
375 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag 402 VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
376 << " d_val adjusted to " << dynamic->d_un.d_val; 403 << " d_val adjusted to " << dynamic->d_un.d_val;
377 } 404 }
378 405
379 // DT_RELENT doesn't change, but make sure it is what we expect. 406 // DT_RELENT doesn't change, but make sure it is what we expect.
380 if (tag == DT_RELENT) { 407 if (tag == DT_RELENT) {
381 CHECK(dynamic->d_un.d_val == sizeof(ELF::Rel)); 408 CHECK(dynamic->d_un.d_val == sizeof(Rel));
382 } 409 }
383 } 410 }
384 411
385 void* section_data = &dynamics[0]; 412 void* section_data = &dynamics[0];
386 size_t bytes = dynamics.size() * sizeof(dynamics[0]); 413 size_t bytes = dynamics.size() * sizeof(dynamics[0]);
387 RewriteSectionData(data, section_data, bytes); 414 RewriteSectionData(data, section_data, bytes);
388 } 415 }
389 416
390 // Helper for ResizeSection(). Adjust the .dynsym section for the hole. 417 // Helper for ResizeSection(). Adjust the .dynsym section for the hole.
391 // We need to adjust the values for the symbols represented in it. 418 // We need to adjust the values for the symbols represented in it.
(...skipping 21 matching lines...) Expand all
413 VLOG(1) << "dynsym[" << i << "] type=" << type 440 VLOG(1) << "dynsym[" << i << "] type=" << type
414 << " st_value adjusted to " << dynsym->st_value; 441 << " st_value adjusted to " << dynsym->st_value;
415 } 442 }
416 } 443 }
417 444
418 void* section_data = &dynsyms[0]; 445 void* section_data = &dynsyms[0];
419 size_t bytes = dynsyms.size() * sizeof(dynsyms[0]); 446 size_t bytes = dynsyms.size() * sizeof(dynsyms[0]);
420 RewriteSectionData(data, section_data, bytes); 447 RewriteSectionData(data, section_data, bytes);
421 } 448 }
422 449
423 // Helper for ResizeSection(). Adjust the .rel.plt section for the hole. 450 // Helper for ResizeSection(). Adjust the plt relocations section for the
424 // We need to adjust the offset of every relocation inside it that falls 451 // hole. We need to adjust the offset of every relocation inside it that
425 // beyond the hole start. 452 // falls beyond the hole start.
453 template <typename Rel>
426 void AdjustRelPltSectionForHole(Elf_Scn* relplt_section, 454 void AdjustRelPltSectionForHole(Elf_Scn* relplt_section,
427 ELF::Off hole_start, 455 ELF::Off hole_start,
428 ssize_t hole_size) { 456 ssize_t hole_size) {
429 Elf_Data* data = GetSectionData(relplt_section); 457 Elf_Data* data = GetSectionData(relplt_section);
430 458
431 const ELF::Rel* relplt_base = reinterpret_cast<ELF::Rel*>(data->d_buf); 459 const Rel* relplt_base = reinterpret_cast<Rel*>(data->d_buf);
432 std::vector<ELF::Rel> relplts( 460 std::vector<Rel> relplts(
433 relplt_base, 461 relplt_base,
434 relplt_base + data->d_size / sizeof(relplts[0])); 462 relplt_base + data->d_size / sizeof(relplts[0]));
435 463
436 for (size_t i = 0; i < relplts.size(); ++i) { 464 for (size_t i = 0; i < relplts.size(); ++i) {
437 ELF::Rel* relplt = &relplts[i]; 465 Rel* relplt = &relplts[i];
438 if (relplt->r_offset > hole_start) { 466 if (relplt->r_offset > hole_start) {
439 relplt->r_offset += hole_size; 467 relplt->r_offset += hole_size;
440 VLOG(1) << "relplt[" << i 468 VLOG(1) << "relplt[" << i
441 << "] r_offset adjusted to " << relplt->r_offset; 469 << "] r_offset adjusted to " << relplt->r_offset;
442 } 470 }
443 } 471 }
444 472
445 void* section_data = &relplts[0]; 473 void* section_data = &relplts[0];
446 size_t bytes = relplts.size() * sizeof(relplts[0]); 474 size_t bytes = relplts.size() * sizeof(relplts[0]);
447 RewriteSectionData(data, section_data, bytes); 475 RewriteSectionData(data, section_data, bytes);
(...skipping 21 matching lines...) Expand all
469 } 497 }
470 498
471 void* section_data = &symtab[0]; 499 void* section_data = &symtab[0];
472 size_t bytes = symtab.size() * sizeof(symtab[0]); 500 size_t bytes = symtab.size() * sizeof(symtab[0]);
473 RewriteSectionData(data, section_data, bytes); 501 RewriteSectionData(data, section_data, bytes);
474 } 502 }
475 503
476 // Resize a section. If the new size is larger than the current size, open 504 // Resize a section. If the new size is larger than the current size, open
477 // up a hole by increasing file offsets that come after the hole. If smaller 505 // up a hole by increasing file offsets that come after the hole. If smaller
478 // than the current size, remove the hole by decreasing those offsets. 506 // than the current size, remove the hole by decreasing those offsets.
507 template <typename Rel>
479 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { 508 void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) {
480 ELF::Shdr* section_header = ELF::getshdr(section); 509 ELF::Shdr* section_header = ELF::getshdr(section);
481 if (section_header->sh_size == new_size) 510 if (section_header->sh_size == new_size)
482 return; 511 return;
483 512
484 // Note if we are resizing the real .rel.dyn. If yes, then we have to 513 // Note if we are resizing the real dyn relocations. If yes, then we have
485 // massage d_un.d_val in the dynamic section where d_tag is DT_RELSZ and 514 // to massage d_un.d_val in the dynamic section where d_tag is DT_RELSZ and
486 // DT_RELCOUNT. 515 // DT_RELCOUNT.
487 size_t string_index; 516 size_t string_index;
488 elf_getshdrstrndx(elf, &string_index); 517 elf_getshdrstrndx(elf, &string_index);
489 const std::string section_name = 518 const std::string section_name =
490 elf_strptr(elf, string_index, section_header->sh_name); 519 elf_strptr(elf, string_index, section_header->sh_name);
491 const bool is_rel_dyn_resize = section_name == ".rel.dyn"; 520 const bool is_relocations_resize =
521 (section_name == ".rel.dyn" || section_name == ".rela.dyn");
492 522
493 // Require that the section size and the data size are the same. True 523 // Require that the section size and the data size are the same. True
494 // in practice for all sections we resize when packing or unpacking. 524 // in practice for all sections we resize when packing or unpacking.
495 Elf_Data* data = GetSectionData(section); 525 Elf_Data* data = GetSectionData(section);
496 CHECK(data->d_off == 0 && data->d_size == section_header->sh_size); 526 CHECK(data->d_off == 0 && data->d_size == section_header->sh_size);
497 527
498 // Require that the section is not zero-length (that is, has allocated 528 // Require that the section is not zero-length (that is, has allocated
499 // data that we can validly expand). 529 // data that we can validly expand).
500 CHECK(data->d_size && data->d_buf); 530 CHECK(data->d_size && data->d_buf);
501 531
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 // Find the dynamic program header entry. 564 // Find the dynamic program header entry.
535 for (size_t i = 0; i < elf_header->e_phnum; ++i) { 565 for (size_t i = 0; i < elf_header->e_phnum; ++i) {
536 ELF::Phdr* program_header = &elf_program_header[i]; 566 ELF::Phdr* program_header = &elf_program_header[i];
537 567
538 if (program_header->p_type == PT_DYNAMIC) { 568 if (program_header->p_type == PT_DYNAMIC) {
539 dynamic_program_header = program_header; 569 dynamic_program_header = program_header;
540 } 570 }
541 } 571 }
542 CHECK(dynamic_program_header); 572 CHECK(dynamic_program_header);
543 573
544 // Sections requiring special attention, and the .android.rel.dyn offset. 574 // Sections requiring special attention, and the packed android
575 // relocations offset.
545 Elf_Scn* dynamic_section = NULL; 576 Elf_Scn* dynamic_section = NULL;
546 Elf_Scn* dynsym_section = NULL; 577 Elf_Scn* dynsym_section = NULL;
547 Elf_Scn* relplt_section = NULL; 578 Elf_Scn* plt_relocations_section = NULL;
548 Elf_Scn* symtab_section = NULL; 579 Elf_Scn* symtab_section = NULL;
549 ELF::Off android_rel_dyn_offset = 0; 580 ELF::Off android_relocations_offset = 0;
550 581
551 // Find these sections, and the .android.rel.dyn offset. 582 // Find these sections, and the packed android relocations offset.
552 section = NULL; 583 section = NULL;
553 while ((section = elf_nextscn(elf, section)) != NULL) { 584 while ((section = elf_nextscn(elf, section)) != NULL) {
554 ELF::Shdr* section_header = ELF::getshdr(section); 585 ELF::Shdr* section_header = ELF::getshdr(section);
555 std::string name = elf_strptr(elf, string_index, section_header->sh_name); 586 std::string name = elf_strptr(elf, string_index, section_header->sh_name);
556 587
557 if (section_header->sh_offset == dynamic_program_header->p_offset) { 588 if (section_header->sh_offset == dynamic_program_header->p_offset) {
558 dynamic_section = section; 589 dynamic_section = section;
559 } 590 }
560 if (name == ".dynsym") { 591 if (name == ".dynsym") {
561 dynsym_section = section; 592 dynsym_section = section;
562 } 593 }
563 if (name == ".rel.plt") { 594 if (name == ".rel.plt" || name == ".rela.plt") {
564 relplt_section = section; 595 plt_relocations_section = section;
565 } 596 }
566 if (name == ".symtab") { 597 if (name == ".symtab") {
567 symtab_section = section; 598 symtab_section = section;
568 } 599 }
569 600
570 // Note .android.rel.dyn offset. 601 // Note packed android relocations offset.
571 if (name == ".android.rel.dyn") { 602 if (name == ".android.rel.dyn" || name == ".android.rela.dyn") {
572 android_rel_dyn_offset = section_header->sh_offset; 603 android_relocations_offset = section_header->sh_offset;
573 } 604 }
574 } 605 }
575 CHECK(dynamic_section != NULL); 606 CHECK(dynamic_section != NULL);
576 CHECK(dynsym_section != NULL); 607 CHECK(dynsym_section != NULL);
577 CHECK(relplt_section != NULL); 608 CHECK(plt_relocations_section != NULL);
578 CHECK(android_rel_dyn_offset != 0); 609 CHECK(android_relocations_offset != 0);
579 610
580 // Adjust the .dynamic section for the hole. Because we have to edit the 611 // Adjust the .dynamic section for the hole. Because we have to edit the
581 // current contents of .dynamic we disallow resizing it. 612 // current contents of .dynamic we disallow resizing it.
582 CHECK(section != dynamic_section); 613 CHECK(section != dynamic_section);
583 AdjustDynamicSectionForHole(dynamic_section, 614 AdjustDynamicSectionForHole<Rel>(dynamic_section,
584 is_rel_dyn_resize, 615 is_relocations_resize,
585 hole_start, 616 hole_start,
586 hole_size); 617 hole_size);
587 618
588 // Adjust the .dynsym section for the hole. 619 // Adjust the .dynsym section for the hole.
589 AdjustDynSymSectionForHole(dynsym_section, hole_start, hole_size); 620 AdjustDynSymSectionForHole(dynsym_section, hole_start, hole_size);
590 621
591 // Adjust the .rel.plt section for the hole. 622 // Adjust the plt relocations section for the hole.
592 AdjustRelPltSectionForHole(relplt_section, hole_start, hole_size); 623 AdjustRelPltSectionForHole<Rel>(plt_relocations_section,
624 hole_start,
625 hole_size);
593 626
594 // If present, adjust the .symtab section for the hole. If the shared 627 // If present, adjust the .symtab section for the hole. If the shared
595 // library was stripped then .symtab will be absent. 628 // library was stripped then .symtab will be absent.
596 if (symtab_section) 629 if (symtab_section)
597 AdjustSymTabSectionForHole(symtab_section, hole_start, hole_size); 630 AdjustSymTabSectionForHole(symtab_section, hole_start, hole_size);
598 } 631 }
599 632
600 // Find the first slot in a dynamics array with the given tag. The array 633 // Find the first slot in a dynamics array with the given tag. The array
601 // always ends with a free (unused) element, and which we exclude from the 634 // always ends with a free (unused) element, and which we exclude from the
602 // search. Returns dynamics->size() if not found. 635 // search. Returns dynamics->size() if not found.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 for (size_t i = slot; i < dynamics->size() - 1; ++i) { 673 for (size_t i = slot; i < dynamics->size() - 1; ++i) {
641 dynamics->at(i) = dynamics->at(i + 1); 674 dynamics->at(i) = dynamics->at(i + 1);
642 VLOG(1) << "dynamic[" << i 675 VLOG(1) << "dynamic[" << i
643 << "] overwritten with dynamic[" << i + 1 << "]"; 676 << "] overwritten with dynamic[" << i + 1 << "]";
644 } 677 }
645 678
646 // Ensure that the end sentinel is still present. 679 // Ensure that the end sentinel is still present.
647 CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL); 680 CHECK(dynamics->at(dynamics->size() - 1).d_tag == DT_NULL);
648 } 681 }
649 682
650 // Apply ARM relative relocations to the file data to which they refer. 683 // Apply relative relocations to the file data to which they refer.
651 // This relocates data into the area it will occupy after the hole in 684 // This relocates data into the area it will occupy after the hole in
652 // .rel.dyn is added or removed. 685 // the dynamic relocations is added or removed.
686 template <typename Rel>
653 void AdjustRelocationTargets(Elf* elf, 687 void AdjustRelocationTargets(Elf* elf,
654 ELF::Off hole_start, 688 ELF::Off hole_start,
655 size_t hole_size, 689 ssize_t hole_size,
656 const std::vector<ELF::Rel>& relocations) { 690 const std::vector<Rel>& relocations) {
657 Elf_Scn* section = NULL; 691 Elf_Scn* section = NULL;
658 while ((section = elf_nextscn(elf, section)) != NULL) { 692 while ((section = elf_nextscn(elf, section)) != NULL) {
659 const ELF::Shdr* section_header = ELF::getshdr(section); 693 const ELF::Shdr* section_header = ELF::getshdr(section);
660 694
661 // Identify this section's start and end addresses. 695 // Identify this section's start and end addresses.
662 const ELF::Addr section_start = section_header->sh_addr; 696 const ELF::Addr section_start = section_header->sh_addr;
663 const ELF::Addr section_end = section_start + section_header->sh_size; 697 const ELF::Addr section_end = section_start + section_header->sh_size;
664 698
665 Elf_Data* data = GetSectionData(section); 699 Elf_Data* data = GetSectionData(section);
666 700
667 // Ignore sections with no effective data. 701 // Ignore sections with no effective data.
668 if (data->d_buf == NULL) 702 if (data->d_buf == NULL)
669 continue; 703 continue;
670 704
671 // Create a copy-on-write pointer to the section's data. 705 // Create a copy-on-write pointer to the section's data.
672 uint8_t* area = reinterpret_cast<uint8_t*>(data->d_buf); 706 uint8_t* area = reinterpret_cast<uint8_t*>(data->d_buf);
673 707
674 for (size_t i = 0; i < relocations.size(); ++i) { 708 for (size_t i = 0; i < relocations.size(); ++i) {
675 const ELF::Rel* relocation = &relocations[i]; 709 const Rel* relocation = &relocations[i];
676 CHECK(ELF_R_TYPE(relocation->r_info) == ELF::kRelativeRelocationCode); 710 CHECK(ELF_R_TYPE(relocation->r_info) == ELF::kRelativeRelocationCode);
677 711
678 // See if this relocation points into the current section. 712 // See if this relocation points into the current section.
679 if (relocation->r_offset >= section_start && 713 if (relocation->r_offset >= section_start &&
680 relocation->r_offset < section_end) { 714 relocation->r_offset < section_end) {
681 ELF::Addr byte_offset = relocation->r_offset - section_start; 715 ELF::Addr byte_offset = relocation->r_offset - section_start;
682 ELF::Off* target = reinterpret_cast<ELF::Off*>(area + byte_offset); 716 ELF::Off* target = reinterpret_cast<ELF::Off*>(area + byte_offset);
683 717
684 // Is the relocation's target after the hole's start? 718 // Is the relocation's target after the hole's start?
685 if (*target > hole_start) { 719 if (*target > hole_start) {
(...skipping 13 matching lines...) Expand all
699 733
700 // If we applied any relocation to this section, write it back. 734 // If we applied any relocation to this section, write it back.
701 if (area != data->d_buf) { 735 if (area != data->d_buf) {
702 RewriteSectionData(data, area, data->d_size); 736 RewriteSectionData(data, area, data->d_size);
703 delete [] area; 737 delete [] area;
704 } 738 }
705 } 739 }
706 } 740 }
707 741
708 // Pad relocations with a given number of null relocations. 742 // Pad relocations with a given number of null relocations.
709 void PadRelocations(size_t count, 743 template <typename Rel>
710 std::vector<ELF::Rel>* relocations) { 744 void PadRelocations(size_t count, std::vector<Rel>* relocations);
745
746 template <>
747 void PadRelocations<ELF::Rel>(size_t count,
748 std::vector<ELF::Rel>* relocations) {
711 ELF::Rel null_relocation; 749 ELF::Rel null_relocation;
712 null_relocation.r_offset = 0; 750 null_relocation.r_offset = 0;
713 null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode); 751 null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
714 std::vector<ELF::Rel> padding(count, null_relocation); 752 std::vector<ELF::Rel> padding(count, null_relocation);
715 relocations->insert(relocations->end(), padding.begin(), padding.end()); 753 relocations->insert(relocations->end(), padding.begin(), padding.end());
716 } 754 }
717 755
756 template <>
757 void PadRelocations<ELF::Rela>(size_t count,
758 std::vector<ELF::Rela>* relocations) {
759 ELF::Rela null_relocation;
760 null_relocation.r_offset = 0;
761 null_relocation.r_info = ELF_R_INFO(0, ELF::kNoRelocationCode);
762 null_relocation.r_addend = 0;
763 std::vector<ELF::Rela> padding(count, null_relocation);
764 relocations->insert(relocations->end(), padding.begin(), padding.end());
765 }
766
718 // Adjust relocations so that the offset that they indicate will be correct 767 // Adjust relocations so that the offset that they indicate will be correct
719 // after the hole in .rel.dyn is added or removed (in effect, relocate the 768 // after the hole in the dynamic relocations is added or removed (in effect,
720 // relocations). 769 // relocate the relocations).
770 template <typename Rel>
721 void AdjustRelocations(ELF::Off hole_start, 771 void AdjustRelocations(ELF::Off hole_start,
722 size_t hole_size, 772 ssize_t hole_size,
723 std::vector<ELF::Rel>* relocations) { 773 std::vector<Rel>* relocations) {
724 for (size_t i = 0; i < relocations->size(); ++i) { 774 for (size_t i = 0; i < relocations->size(); ++i) {
725 ELF::Rel* relocation = &relocations->at(i); 775 Rel* relocation = &relocations->at(i);
726 if (relocation->r_offset > hole_start) { 776 if (relocation->r_offset > hole_start) {
727 relocation->r_offset += hole_size; 777 relocation->r_offset += hole_size;
728 VLOG(1) << "relocation[" << i 778 VLOG(1) << "relocation[" << i
729 << "] offset adjusted to " << relocation->r_offset; 779 << "] offset adjusted to " << relocation->r_offset;
730 } 780 }
731 } 781 }
732 } 782 }
733 783
734 } // namespace 784 } // namespace
735 785
736 // Remove ARM relative entries from .rel.dyn and write as packed data 786 // Remove relative entries from dynamic relocations and write as packed
737 // into .android.rel.dyn. 787 // data into android packed relocations.
738 bool ElfFile::PackRelocations() { 788 bool ElfFile::PackRelocations() {
739 // Load the ELF file into libelf. 789 // Load the ELF file into libelf.
740 if (!Load()) { 790 if (!Load()) {
741 LOG(ERROR) << "Failed to load as ELF"; 791 LOG(ERROR) << "Failed to load as ELF";
742 return false; 792 return false;
743 } 793 }
744 794
745 // Retrieve the current .rel.dyn section data. 795 // Retrieve the current dynamic relocations section data.
746 Elf_Data* data = GetSectionData(rel_dyn_section_); 796 Elf_Data* data = GetSectionData(relocations_section_);
747 797
748 // Convert data to a vector of Elf32 relocations. 798 if (relocations_type_ == REL) {
749 const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf); 799 // Convert data to a vector of relocations.
750 std::vector<ELF::Rel> relocations( 800 const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf);
751 relocations_base, 801 std::vector<ELF::Rel> relocations(
752 relocations_base + data->d_size / sizeof(relocations[0])); 802 relocations_base,
803 relocations_base + data->d_size / sizeof(relocations[0]));
753 804
754 std::vector<ELF::Rel> relative_relocations; 805 LOG(INFO) << "Relocations : REL";
755 std::vector<ELF::Rel> other_relocations; 806 return PackTypedRelocations<ELF::Rel>(relocations, data);
807 }
756 808
757 // Filter relocations into those that are ARM relative and others. 809 if (relocations_type_ == RELA) {
810 // Convert data to a vector of relocations with addends.
811 const ELF::Rela* relocations_base =
812 reinterpret_cast<ELF::Rela*>(data->d_buf);
813 std::vector<ELF::Rela> relocations(
814 relocations_base,
815 relocations_base + data->d_size / sizeof(relocations[0]));
816
817 LOG(INFO) << "Relocations : RELA";
818 return PackTypedRelocations<ELF::Rela>(relocations, data);
819 }
820
821 NOTREACHED();
822 return false;
823 }
824
825 // Helper for PackRelocations(). Rel type is one of ELF::Rel or ELF::Rela.
826 template <typename Rel>
827 bool ElfFile::PackTypedRelocations(const std::vector<Rel>& relocations,
828 Elf_Data* data) {
829 // Filter relocations into those that are relative and others.
830 std::vector<Rel> relative_relocations;
831 std::vector<Rel> other_relocations;
832
758 for (size_t i = 0; i < relocations.size(); ++i) { 833 for (size_t i = 0; i < relocations.size(); ++i) {
759 const ELF::Rel& relocation = relocations[i]; 834 const Rel& relocation = relocations[i];
760 if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) { 835 if (ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode) {
761 CHECK(ELF_R_SYM(relocation.r_info) == 0); 836 CHECK(ELF_R_SYM(relocation.r_info) == 0);
762 relative_relocations.push_back(relocation); 837 relative_relocations.push_back(relocation);
763 } else { 838 } else {
764 other_relocations.push_back(relocation); 839 other_relocations.push_back(relocation);
765 } 840 }
766 } 841 }
767 LOG(INFO) << "Relative : " << relative_relocations.size() << " entries"; 842 LOG(INFO) << "Relative : " << relative_relocations.size() << " entries";
768 LOG(INFO) << "Other : " << other_relocations.size() << " entries"; 843 LOG(INFO) << "Other : " << other_relocations.size() << " entries";
769 LOG(INFO) << "Total : " << relocations.size() << " entries"; 844 LOG(INFO) << "Total : " << relocations.size() << " entries";
770 845
771 // If no relative relocations then we have nothing packable. Perhaps 846 // If no relative relocations then we have nothing packable. Perhaps
772 // the shared object has already been packed? 847 // the shared object has already been packed?
773 if (relative_relocations.empty()) { 848 if (relative_relocations.empty()) {
774 LOG(ERROR) << "No relative relocations found (already packed?)"; 849 LOG(ERROR) << "No relative relocations found (already packed?)";
775 return false; 850 return false;
776 } 851 }
777 852
778 // Unless padding, pre-apply ARM relative relocations to account for the 853 // Unless padding, pre-apply relative relocations to account for the
779 // hole, and pre-adjust all relocation offsets accordingly. 854 // hole, and pre-adjust all relocation offsets accordingly.
780 if (!is_padding_rel_dyn_) { 855 if (!is_padding_relocations_) {
781 // Pre-calculate the size of the hole we will close up when we rewrite 856 // Pre-calculate the size of the hole we will close up when we rewrite
782 // .rel.dyn. We have to adjust relocation addresses to account for this. 857 // dynamic relocations. We have to adjust relocation addresses to
783 ELF::Shdr* section_header = ELF::getshdr(rel_dyn_section_); 858 // account for this.
859 ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
784 const ELF::Off hole_start = section_header->sh_offset; 860 const ELF::Off hole_start = section_header->sh_offset;
785 size_t hole_size = 861 ssize_t hole_size =
786 relative_relocations.size() * sizeof(relative_relocations[0]); 862 relative_relocations.size() * sizeof(relative_relocations[0]);
787 const size_t unaligned_hole_size = hole_size; 863 const ssize_t unaligned_hole_size = hole_size;
788 864
789 // Adjust the actual hole size to preserve alignment. 865 // Adjust the actual hole size to preserve alignment. We always adjust
790 hole_size -= hole_size % kPreserveAlignment; 866 // by a whole number of NONE-type relocations.
867 while (hole_size % kPreserveAlignment)
868 hole_size -= sizeof(relative_relocations[0]);
791 LOG(INFO) << "Compaction : " << hole_size << " bytes"; 869 LOG(INFO) << "Compaction : " << hole_size << " bytes";
792 870
793 // Adjusting for alignment may have removed any packing benefit. 871 // Adjusting for alignment may have removed any packing benefit.
794 if (hole_size == 0) { 872 if (hole_size == 0) {
795 LOG(INFO) << "Too few relative relocations to pack after alignment"; 873 LOG(INFO) << "Too few relative relocations to pack after alignment";
796 return false; 874 return false;
797 } 875 }
798 876
799 // Add null relocations to other_relocations to preserve alignment. 877 // Add null relocations to other_relocations to preserve alignment.
800 const size_t padding_bytes = unaligned_hole_size - hole_size; 878 const size_t padding_bytes = unaligned_hole_size - hole_size;
801 CHECK(padding_bytes % sizeof(other_relocations[0]) == 0); 879 CHECK(padding_bytes % sizeof(other_relocations[0]) == 0);
802 const size_t required = padding_bytes / sizeof(other_relocations[0]); 880 const size_t required = padding_bytes / sizeof(other_relocations[0]);
803 PadRelocations(required, &other_relocations); 881 PadRelocations(required, &other_relocations);
804 LOG(INFO) << "Alignment pad : " << required << " relocations"; 882 LOG(INFO) << "Alignment pad : " << required << " relocations";
805 883
806 // Apply relocations to all ARM relative data to relocate it into the 884 // Apply relocations to all relative data to relocate it into the
807 // area it will occupy once the hole in .rel.dyn is removed. 885 // area it will occupy once the hole in the dynamic relocations is removed.
808 AdjustRelocationTargets(elf_, hole_start, -hole_size, relative_relocations); 886 AdjustRelocationTargets<Rel>(
887 elf_, hole_start, -hole_size, relative_relocations);
809 // Relocate the relocations. 888 // Relocate the relocations.
810 AdjustRelocations(hole_start, -hole_size, &relative_relocations); 889 AdjustRelocations<Rel>(hole_start, -hole_size, &relative_relocations);
811 AdjustRelocations(hole_start, -hole_size, &other_relocations); 890 AdjustRelocations<Rel>(hole_start, -hole_size, &other_relocations);
812 } else { 891 } else {
813 // If padding, add NONE-type relocations to other_relocations to make it 892 // If padding, add NONE-type relocations to other_relocations to make it
814 // the same size as the the original relocations we read in. This makes 893 // the same size as the the original relocations we read in. This makes
815 // the ResizeSection() below a no-op. 894 // the ResizeSection() below a no-op.
816 const size_t required = relocations.size() - other_relocations.size(); 895 const size_t required = relocations.size() - other_relocations.size();
817 PadRelocations(required, &other_relocations); 896 PadRelocations(required, &other_relocations);
818 } 897 }
819 898
820 // Pack ARM relative relocations. 899 // Pack relative relocations.
821 const size_t initial_bytes = 900 const size_t initial_bytes =
822 relative_relocations.size() * sizeof(relative_relocations[0]); 901 relative_relocations.size() * sizeof(relative_relocations[0]);
823 LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes"; 902 LOG(INFO) << "Unpacked relative: " << initial_bytes << " bytes";
824 std::vector<uint8_t> packed; 903 std::vector<uint8_t> packed;
825 RelocationPacker packer; 904 RelocationPacker packer;
826 packer.PackRelativeRelocations(relative_relocations, &packed); 905 packer.PackRelativeRelocations(relative_relocations, &packed);
827 const void* packed_data = &packed[0]; 906 const void* packed_data = &packed[0];
828 const size_t packed_bytes = packed.size() * sizeof(packed[0]); 907 const size_t packed_bytes = packed.size() * sizeof(packed[0]);
829 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes"; 908 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes";
830 909
831 // If we have insufficient ARM relative relocations to form a run then 910 // If we have insufficient relative relocations to form a run then
832 // packing fails. 911 // packing fails.
833 if (packed.empty()) { 912 if (packed.empty()) {
834 LOG(INFO) << "Too few relative relocations to pack"; 913 LOG(INFO) << "Too few relative relocations to pack";
835 return false; 914 return false;
836 } 915 }
837 916
838 // Run a loopback self-test as a check that packing is lossless. 917 // Run a loopback self-test as a check that packing is lossless.
839 std::vector<ELF::Rel> unpacked; 918 std::vector<Rel> unpacked;
840 packer.UnpackRelativeRelocations(packed, &unpacked); 919 packer.UnpackRelativeRelocations(packed, &unpacked);
841 CHECK(unpacked.size() == relative_relocations.size()); 920 CHECK(unpacked.size() == relative_relocations.size());
842 CHECK(!memcmp(&unpacked[0], 921 CHECK(!memcmp(&unpacked[0],
843 &relative_relocations[0], 922 &relative_relocations[0],
844 unpacked.size() * sizeof(unpacked[0]))); 923 unpacked.size() * sizeof(unpacked[0])));
845 924
846 // Make sure packing saved some space. 925 // Make sure packing saved some space.
847 if (packed_bytes >= initial_bytes) { 926 if (packed_bytes >= initial_bytes) {
848 LOG(INFO) << "Packing relative relocations saves no space"; 927 LOG(INFO) << "Packing relative relocations saves no space";
849 return false; 928 return false;
850 } 929 }
851 930
852 // Rewrite the current .rel.dyn section to be only the ARM non-relative 931 // Rewrite the current dynamic relocations section to be only the ARM
853 // relocations, then shrink it to size. 932 // non-relative relocations, then shrink it to size.
854 const void* section_data = &other_relocations[0]; 933 const void* section_data = &other_relocations[0];
855 const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]); 934 const size_t bytes = other_relocations.size() * sizeof(other_relocations[0]);
856 ResizeSection(elf_, rel_dyn_section_, bytes); 935 ResizeSection<Rel>(elf_, relocations_section_, bytes);
857 RewriteSectionData(data, section_data, bytes); 936 RewriteSectionData(data, section_data, bytes);
858 937
859 // Rewrite the current .android.rel.dyn section to hold the packed 938 // Rewrite the current packed android relocations section to hold the packed
860 // ARM relative relocations. 939 // relative relocations.
861 data = GetSectionData(android_rel_dyn_section_); 940 data = GetSectionData(android_relocations_section_);
862 ResizeSection(elf_, android_rel_dyn_section_, packed_bytes); 941 ResizeSection<Rel>(elf_, android_relocations_section_, packed_bytes);
863 RewriteSectionData(data, packed_data, packed_bytes); 942 RewriteSectionData(data, packed_data, packed_bytes);
864 943
865 // Rewrite .dynamic to include two new tags describing .android.rel.dyn. 944 // Rewrite .dynamic to include two new tags describing the packed android
945 // relocations.
866 data = GetSectionData(dynamic_section_); 946 data = GetSectionData(dynamic_section_);
867 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); 947 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
868 std::vector<ELF::Dyn> dynamics( 948 std::vector<ELF::Dyn> dynamics(
869 dynamic_base, 949 dynamic_base,
870 dynamic_base + data->d_size / sizeof(dynamics[0])); 950 dynamic_base + data->d_size / sizeof(dynamics[0]));
871 // Use two of the spare slots to describe the .android.rel.dyn section. 951 // Use two of the spare slots to describe the packed section.
872 ELF::Shdr* section_header = ELF::getshdr(android_rel_dyn_section_); 952 ELF::Shdr* section_header = ELF::getshdr(android_relocations_section_);
873 const ELF::Dyn offset_dyn 953 const ELF::Dyn offset_dyn
874 = {DT_ANDROID_REL_OFFSET, {section_header->sh_offset}}; 954 = {DT_ANDROID_REL_OFFSET, {section_header->sh_offset}};
875 AddDynamicEntry(offset_dyn, &dynamics); 955 AddDynamicEntry(offset_dyn, &dynamics);
876 const ELF::Dyn size_dyn 956 const ELF::Dyn size_dyn
877 = {DT_ANDROID_REL_SIZE, {section_header->sh_size}}; 957 = {DT_ANDROID_REL_SIZE, {section_header->sh_size}};
878 AddDynamicEntry(size_dyn, &dynamics); 958 AddDynamicEntry(size_dyn, &dynamics);
879 const void* dynamics_data = &dynamics[0]; 959 const void* dynamics_data = &dynamics[0];
880 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); 960 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
881 RewriteSectionData(data, dynamics_data, dynamics_bytes); 961 RewriteSectionData(data, dynamics_data, dynamics_bytes);
882 962
883 Flush(); 963 Flush();
884 return true; 964 return true;
885 } 965 }
886 966
887 // Find packed ARM relative relocations in .android.rel.dyn, unpack them, 967 // Find packed relative relocations in the packed android relocations
888 // and rewrite the .rel.dyn section in so_file to contain unpacked data. 968 // section, unpack them, and rewrite the dynamic relocations section to
969 // contain unpacked data.
889 bool ElfFile::UnpackRelocations() { 970 bool ElfFile::UnpackRelocations() {
890 // Load the ELF file into libelf. 971 // Load the ELF file into libelf.
891 if (!Load()) { 972 if (!Load()) {
892 LOG(ERROR) << "Failed to load as ELF"; 973 LOG(ERROR) << "Failed to load as ELF";
893 return false; 974 return false;
894 } 975 }
895 976
896 // Retrieve the current .android.rel.dyn section data. 977 // Retrieve the current packed android relocations section data.
897 Elf_Data* data = GetSectionData(android_rel_dyn_section_); 978 Elf_Data* data = GetSectionData(android_relocations_section_);
898 979
899 // Convert data to a vector of bytes. 980 // Convert data to a vector of bytes.
900 const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf); 981 const uint8_t* packed_base = reinterpret_cast<uint8_t*>(data->d_buf);
901 std::vector<uint8_t> packed( 982 std::vector<uint8_t> packed(
902 packed_base, 983 packed_base,
903 packed_base + data->d_size / sizeof(packed[0])); 984 packed_base + data->d_size / sizeof(packed[0]));
904 985
905 // Properly packed data must begin with "APR1". 986 if (packed.size() > 3 &&
906 if (packed.empty() || 987 packed[0] == 'A' && packed[1] == 'P' &&
907 packed[0] != 'A' || packed[1] != 'P' || 988 packed[2] == 'R' && packed[3] == '1') {
908 packed[2] != 'R' || packed[3] != '1') { 989 // Signature is APR1, unpack relocations.
909 LOG(ERROR) << "Packed relative relocations not found (not packed?)"; 990 CHECK(relocations_type_ == REL);
910 return false; 991 LOG(INFO) << "Relocations : REL";
992 return UnpackTypedRelocations<ELF::Rel>(packed, data);
911 } 993 }
912 994
913 // Unpack the data to re-materialize the ARM relative relocations. 995 if (packed.size() > 3 &&
996 packed[0] == 'A' && packed[1] == 'P' &&
997 packed[2] == 'A' && packed[3] == '1') {
998 // Signature is APA1, unpack relocations with addends.
999 CHECK(relocations_type_ == RELA);
1000 LOG(INFO) << "Relocations : RELA";
1001 return UnpackTypedRelocations<ELF::Rela>(packed, data);
1002 }
1003
1004 LOG(ERROR) << "Packed relative relocations not found (not packed?)";
1005 return false;
1006 }
1007
1008 // Helper for UnpackRelocations(). Rel type is one of ELF::Rel or ELF::Rela.
1009 template <typename Rel>
1010 bool ElfFile::UnpackTypedRelocations(const std::vector<uint8_t>& packed,
1011 Elf_Data* data) {
1012 // Unpack the data to re-materialize the relative relocations.
914 const size_t packed_bytes = packed.size() * sizeof(packed[0]); 1013 const size_t packed_bytes = packed.size() * sizeof(packed[0]);
915 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes"; 1014 LOG(INFO) << "Packed relative: " << packed_bytes << " bytes";
916 std::vector<ELF::Rel> relative_relocations; 1015 std::vector<Rel> relative_relocations;
917 RelocationPacker packer; 1016 RelocationPacker packer;
918 packer.UnpackRelativeRelocations(packed, &relative_relocations); 1017 packer.UnpackRelativeRelocations(packed, &relative_relocations);
919 const size_t unpacked_bytes = 1018 const size_t unpacked_bytes =
920 relative_relocations.size() * sizeof(relative_relocations[0]); 1019 relative_relocations.size() * sizeof(relative_relocations[0]);
921 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes"; 1020 LOG(INFO) << "Unpacked relative: " << unpacked_bytes << " bytes";
922 1021
923 // Retrieve the current .rel.dyn section data. 1022 // Retrieve the current dynamic relocations section data.
924 data = GetSectionData(rel_dyn_section_); 1023 data = GetSectionData(relocations_section_);
925 1024
926 // Interpret data as Elf32 relocations. 1025 // Interpret data as Elf32 relocations.
927 const ELF::Rel* relocations_base = reinterpret_cast<ELF::Rel*>(data->d_buf); 1026 const Rel* relocations_base = reinterpret_cast<Rel*>(data->d_buf);
928 std::vector<ELF::Rel> relocations( 1027 std::vector<Rel> relocations(
929 relocations_base, 1028 relocations_base,
930 relocations_base + data->d_size / sizeof(relocations[0])); 1029 relocations_base + data->d_size / sizeof(relocations[0]));
931 1030
932 std::vector<ELF::Rel> other_relocations; 1031 std::vector<Rel> other_relocations;
933 size_t padding = 0; 1032 size_t padding = 0;
934 1033
935 // Filter relocations to locate any that are NONE-type. These will occur 1034 // Filter relocations to locate any that are NONE-type. These will occur
936 // if padding was turned on for packing. 1035 // if padding was turned on for packing.
937 for (size_t i = 0; i < relocations.size(); ++i) { 1036 for (size_t i = 0; i < relocations.size(); ++i) {
938 const ELF::Rel& relocation = relocations[i]; 1037 const Rel& relocation = relocations[i];
939 if (ELF_R_TYPE(relocation.r_info) != ELF::kNoRelocationCode) { 1038 if (ELF_R_TYPE(relocation.r_info) != ELF::kNoRelocationCode) {
940 other_relocations.push_back(relocation); 1039 other_relocations.push_back(relocation);
941 } else { 1040 } else {
942 ++padding; 1041 ++padding;
943 } 1042 }
944 } 1043 }
945 LOG(INFO) << "Relative : " << relative_relocations.size() << " entries"; 1044 LOG(INFO) << "Relative : " << relative_relocations.size() << " entries";
946 LOG(INFO) << "Other : " << other_relocations.size() << " entries"; 1045 LOG(INFO) << "Other : " << other_relocations.size() << " entries";
947 1046
948 // If we found the same number of null relocation entries in .rel.dyn as we 1047 // If we found the same number of null relocation entries in the dynamic
949 // hold as unpacked relative relocations, then this is a padded file. 1048 // relocations section as we hold as unpacked relative relocations, then
1049 // this is a padded file.
950 const bool is_padded = padding == relative_relocations.size(); 1050 const bool is_padded = padding == relative_relocations.size();
951 1051
952 // Unless padded, pre-apply ARM relative relocations to account for the 1052 // Unless padded, pre-apply relative relocations to account for the
953 // hole, and pre-adjust all relocation offsets accordingly. 1053 // hole, and pre-adjust all relocation offsets accordingly.
954 if (!is_padded) { 1054 if (!is_padded) {
955 // Pre-calculate the size of the hole we will open up when we rewrite 1055 // Pre-calculate the size of the hole we will open up when we rewrite
956 // .rel.dyn. We have to adjust relocation addresses to account for this. 1056 // dynamic relocations. We have to adjust relocation addresses to
957 ELF::Shdr* section_header = ELF::getshdr(rel_dyn_section_); 1057 // account for this.
1058 ELF::Shdr* section_header = ELF::getshdr(relocations_section_);
958 const ELF::Off hole_start = section_header->sh_offset; 1059 const ELF::Off hole_start = section_header->sh_offset;
959 size_t hole_size = 1060 ssize_t hole_size =
960 relative_relocations.size() * sizeof(relative_relocations[0]); 1061 relative_relocations.size() * sizeof(relative_relocations[0]);
961 1062
962 // Adjust the hole size for the padding added to preserve alignment. 1063 // Adjust the hole size for the padding added to preserve alignment.
963 hole_size -= padding * sizeof(other_relocations[0]); 1064 hole_size -= padding * sizeof(other_relocations[0]);
964 LOG(INFO) << "Expansion : " << hole_size << " bytes"; 1065 LOG(INFO) << "Expansion : " << hole_size << " bytes";
965 1066
966 // Apply relocations to all ARM relative data to relocate it into the 1067 // Apply relocations to all relative data to relocate it into the
967 // area it will occupy once the hole in .rel.dyn is opened. 1068 // area it will occupy once the hole in dynamic relocations is opened.
968 AdjustRelocationTargets(elf_, hole_start, hole_size, relative_relocations); 1069 AdjustRelocationTargets<Rel>(
1070 elf_, hole_start, hole_size, relative_relocations);
969 // Relocate the relocations. 1071 // Relocate the relocations.
970 AdjustRelocations(hole_start, hole_size, &relative_relocations); 1072 AdjustRelocations<Rel>(hole_start, hole_size, &relative_relocations);
971 AdjustRelocations(hole_start, hole_size, &other_relocations); 1073 AdjustRelocations<Rel>(hole_start, hole_size, &other_relocations);
972 } 1074 }
973 1075
974 // Rewrite the current .rel.dyn section to be the ARM relative relocations 1076 // Rewrite the current dynamic relocations section to be the relative
975 // followed by other relocations. This is the usual order in which we find 1077 // relocations followed by other relocations. This is the usual order in
976 // them after linking, so this action will normally put the entire .rel.dyn 1078 // which we find them after linking, so this action will normally put the
977 // section back to its pre-split-and-packed state. 1079 // entire dynamic relocations section back to its pre-split-and-packed state.
978 relocations.assign(relative_relocations.begin(), relative_relocations.end()); 1080 relocations.assign(relative_relocations.begin(), relative_relocations.end());
979 relocations.insert(relocations.end(), 1081 relocations.insert(relocations.end(),
980 other_relocations.begin(), other_relocations.end()); 1082 other_relocations.begin(), other_relocations.end());
981 const void* section_data = &relocations[0]; 1083 const void* section_data = &relocations[0];
982 const size_t bytes = relocations.size() * sizeof(relocations[0]); 1084 const size_t bytes = relocations.size() * sizeof(relocations[0]);
983 LOG(INFO) << "Total : " << relocations.size() << " entries"; 1085 LOG(INFO) << "Total : " << relocations.size() << " entries";
984 ResizeSection(elf_, rel_dyn_section_, bytes); 1086 ResizeSection<Rel>(elf_, relocations_section_, bytes);
985 RewriteSectionData(data, section_data, bytes); 1087 RewriteSectionData(data, section_data, bytes);
986 1088
987 // Nearly empty the current .android.rel.dyn section. Leaves a four-byte 1089 // Nearly empty the current packed android relocations section. Leaves a
988 // stub so that some data remains allocated to the section. This is a 1090 // four-byte stub so that some data remains allocated to the section.
989 // convenience which allows us to re-pack this file again without 1091 // This is a convenience which allows us to re-pack this file again without
990 // having to remove the section and then add a new small one with objcopy. 1092 // having to remove the section and then add a new small one with objcopy.
991 // The way we resize sections relies on there being some data in a section. 1093 // The way we resize sections relies on there being some data in a section.
992 data = GetSectionData(android_rel_dyn_section_); 1094 data = GetSectionData(android_relocations_section_);
993 ResizeSection(elf_, android_rel_dyn_section_, sizeof(kStubIdentifier)); 1095 ResizeSection<Rel>(
1096 elf_, android_relocations_section_, sizeof(kStubIdentifier));
994 RewriteSectionData(data, &kStubIdentifier, sizeof(kStubIdentifier)); 1097 RewriteSectionData(data, &kStubIdentifier, sizeof(kStubIdentifier));
995 1098
996 // Rewrite .dynamic to remove two tags describing .android.rel.dyn. 1099 // Rewrite .dynamic to remove two tags describing packed android relocations.
997 data = GetSectionData(dynamic_section_); 1100 data = GetSectionData(dynamic_section_);
998 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf); 1101 const ELF::Dyn* dynamic_base = reinterpret_cast<ELF::Dyn*>(data->d_buf);
999 std::vector<ELF::Dyn> dynamics( 1102 std::vector<ELF::Dyn> dynamics(
1000 dynamic_base, 1103 dynamic_base,
1001 dynamic_base + data->d_size / sizeof(dynamics[0])); 1104 dynamic_base + data->d_size / sizeof(dynamics[0]));
1002 RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics); 1105 RemoveDynamicEntry(DT_ANDROID_REL_OFFSET, &dynamics);
1003 RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics); 1106 RemoveDynamicEntry(DT_ANDROID_REL_SIZE, &dynamics);
1004 const void* dynamics_data = &dynamics[0]; 1107 const void* dynamics_data = &dynamics[0];
1005 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]); 1108 const size_t dynamics_bytes = dynamics.size() * sizeof(dynamics[0]);
1006 RewriteSectionData(data, dynamics_data, dynamics_bytes); 1109 RewriteSectionData(data, dynamics_data, dynamics_bytes);
(...skipping 16 matching lines...) Expand all
1023 1126
1024 // Clean up libelf, and truncate the output file to the number of bytes 1127 // Clean up libelf, and truncate the output file to the number of bytes
1025 // written by elf_update(). 1128 // written by elf_update().
1026 elf_end(elf_); 1129 elf_end(elf_);
1027 elf_ = NULL; 1130 elf_ = NULL;
1028 const int truncate = ftruncate(fd_, file_bytes); 1131 const int truncate = ftruncate(fd_, file_bytes);
1029 CHECK(truncate == 0); 1132 CHECK(truncate == 0);
1030 } 1133 }
1031 1134
1032 } // namespace relocation_packer 1135 } // namespace relocation_packer
OLDNEW
« no previous file with comments | « tools/relocation_packer/src/elf_file.h ('k') | tools/relocation_packer/src/elf_file_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698