OLD | NEW |
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 "crazy_linker_elf_relocations.h" | 5 #include "crazy_linker_elf_relocations.h" |
6 | 6 |
| 7 #include <assert.h> |
7 #include <errno.h> | 8 #include <errno.h> |
8 | 9 |
9 #include "crazy_linker_debug.h" | 10 #include "crazy_linker_debug.h" |
10 #include "crazy_linker_elf_symbols.h" | 11 #include "crazy_linker_elf_symbols.h" |
11 #include "crazy_linker_elf_view.h" | 12 #include "crazy_linker_elf_view.h" |
12 #include "crazy_linker_error.h" | 13 #include "crazy_linker_error.h" |
13 #include "crazy_linker_leb128.h" | 14 #include "crazy_linker_leb128.h" |
14 #include "crazy_linker_system.h" | 15 #include "crazy_linker_system.h" |
15 #include "crazy_linker_util.h" | 16 #include "crazy_linker_util.h" |
16 #include "linker_phdr.h" | 17 #include "linker_phdr.h" |
17 | 18 |
18 #define DEBUG_RELOCATIONS 0 | 19 #define DEBUG_RELOCATIONS 0 |
19 | 20 |
20 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 21 #define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
21 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) | 22 #define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) |
22 | 23 |
23 #ifndef DF_SYMBOLIC | 24 #ifndef DF_SYMBOLIC |
24 #define DF_SYMBOLIC 2 | 25 #define DF_SYMBOLIC 2 |
25 #endif | 26 #endif |
26 | 27 |
27 #ifndef DF_TEXTREL | 28 #ifndef DF_TEXTREL |
28 #define DF_TEXTREL 4 | 29 #define DF_TEXTREL 4 |
29 #endif | 30 #endif |
30 | 31 |
31 #ifndef DT_FLAGS | 32 #ifndef DT_FLAGS |
32 #define DT_FLAGS 30 | 33 #define DT_FLAGS 30 |
33 #endif | 34 #endif |
34 | 35 |
| 36 // Extension dynamic tags for Android packed relocations. |
| 37 #ifndef DT_LOOS |
| 38 #define DT_LOOS 0x6000000d |
| 39 #endif |
| 40 #ifndef DT_ANDROID_REL |
| 41 #define DT_ANDROID_REL (DT_LOOS + 2) |
| 42 #endif |
| 43 #ifndef DT_ANDROID_RELSZ |
| 44 #define DT_ANDROID_RELSZ (DT_LOOS + 3) |
| 45 #endif |
| 46 #ifndef DT_ANDROID_RELA |
| 47 #define DT_ANDROID_RELA (DT_LOOS + 4) |
| 48 #endif |
| 49 #ifndef DT_ANDROID_RELASZ |
| 50 #define DT_ANDROID_RELASZ (DT_LOOS + 5) |
| 51 #endif |
| 52 |
35 // Processor-specific relocation types supported by the linker. | 53 // Processor-specific relocation types supported by the linker. |
36 #ifdef __arm__ | 54 #ifdef __arm__ |
37 | 55 |
38 /* arm32 relocations */ | 56 /* arm32 relocations */ |
39 #define R_ARM_ABS32 2 | 57 #define R_ARM_ABS32 2 |
40 #define R_ARM_REL32 3 | 58 #define R_ARM_REL32 3 |
41 #define R_ARM_GLOB_DAT 21 | 59 #define R_ARM_GLOB_DAT 21 |
42 #define R_ARM_JUMP_SLOT 22 | 60 #define R_ARM_JUMP_SLOT 22 |
43 #define R_ARM_COPY 20 | 61 #define R_ARM_COPY 20 |
44 #define R_ARM_RELATIVE 23 | 62 #define R_ARM_RELATIVE 23 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 } | 179 } |
162 } | 180 } |
163 | 181 |
164 } // namespace | 182 } // namespace |
165 | 183 |
166 bool ElfRelocations::Init(const ElfView* view, Error* error) { | 184 bool ElfRelocations::Init(const ElfView* view, Error* error) { |
167 // Save these for later. | 185 // Save these for later. |
168 phdr_ = view->phdr(); | 186 phdr_ = view->phdr(); |
169 phdr_count_ = view->phdr_count(); | 187 phdr_count_ = view->phdr_count(); |
170 load_bias_ = view->load_bias(); | 188 load_bias_ = view->load_bias(); |
171 #if defined(__arm__) || defined(__aarch64__) | |
172 packed_relocations_ = view->packed_relocations(); | |
173 #endif | |
174 | 189 |
175 // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ | 190 // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ |
176 // then we require DT_PLTREL to agree. | 191 // then we require DT_PLTREL to agree. |
177 bool has_rela_relocations = false; | 192 bool has_rela_relocations = false; |
178 bool has_rel_relocations = false; | 193 bool has_rel_relocations = false; |
179 | 194 |
180 // Parse the dynamic table. | 195 // Parse the dynamic table. |
181 ElfView::DynamicIterator dyn(view); | 196 ElfView::DynamicIterator dyn(view); |
182 for (; dyn.HasNext(); dyn.GetNext()) { | 197 for (; dyn.HasNext(); dyn.GetNext()) { |
183 ELF::Addr dyn_value = dyn.GetValue(); | 198 ELF::Addr dyn_value = dyn.GetValue(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 if (relocations_size_) { | 239 if (relocations_size_) { |
225 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; | 240 *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; |
226 return false; | 241 return false; |
227 } | 242 } |
228 relocations_size_ = dyn_value; | 243 relocations_size_ = dyn_value; |
229 if (tag == DT_RELASZ) | 244 if (tag == DT_RELASZ) |
230 has_rela_relocations = true; | 245 has_rela_relocations = true; |
231 else | 246 else |
232 has_rel_relocations = true; | 247 has_rel_relocations = true; |
233 break; | 248 break; |
| 249 case DT_ANDROID_RELA: |
| 250 case DT_ANDROID_REL: |
| 251 RLOG(" %s addr=%p\n", |
| 252 (tag == DT_ANDROID_RELA) ? "DT_ANDROID_RELA" : "DT_ANDROID_REL", |
| 253 dyn_addr); |
| 254 if (android_relocations_) { |
| 255 *error = "Unsupported DT_ANDROID_RELA/DT_ANDROID_REL " |
| 256 "combination in dynamic section"; |
| 257 return false; |
| 258 } |
| 259 android_relocations_ = reinterpret_cast<uint8_t*>(dyn_addr); |
| 260 if (tag == DT_ANDROID_RELA) |
| 261 has_rela_relocations = true; |
| 262 else |
| 263 has_rel_relocations = true; |
| 264 break; |
| 265 case DT_ANDROID_RELASZ: |
| 266 case DT_ANDROID_RELSZ: |
| 267 RLOG(" %s size=%d\n", |
| 268 (tag == DT_ANDROID_RELASZ) |
| 269 ? "DT_ANDROID_RELASZ" : "DT_ANDROID_RELSZ", dyn_addr); |
| 270 if (android_relocations_size_) { |
| 271 *error = "Unsupported DT_ANDROID_RELASZ/DT_ANDROID_RELSZ " |
| 272 "combination in dyn section"; |
| 273 return false; |
| 274 } |
| 275 android_relocations_size_ = dyn_value; |
| 276 if (tag == DT_ANDROID_RELASZ) |
| 277 has_rela_relocations = true; |
| 278 else |
| 279 has_rel_relocations = true; |
| 280 break; |
234 case DT_PLTGOT: | 281 case DT_PLTGOT: |
235 // Only used on MIPS currently. Could also be used on other platforms | 282 // Only used on MIPS currently. Could also be used on other platforms |
236 // when lazy binding (i.e. RTLD_LAZY) is implemented. | 283 // when lazy binding (i.e. RTLD_LAZY) is implemented. |
237 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); | 284 RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); |
238 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); | 285 plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); |
239 break; | 286 break; |
240 case DT_TEXTREL: | 287 case DT_TEXTREL: |
241 RLOG(" DT_TEXTREL\n"); | 288 RLOG(" DT_TEXTREL\n"); |
242 has_text_relocations_ = true; | 289 has_text_relocations_ = true; |
243 break; | 290 break; |
244 case DT_SYMBOLIC: | 291 case DT_SYMBOLIC: |
245 RLOG(" DT_SYMBOLIC\n"); | 292 RLOG(" DT_SYMBOLIC\n"); |
246 has_symbolic_ = true; | 293 has_symbolic_ = true; |
247 break; | 294 break; |
248 case DT_FLAGS: | 295 case DT_FLAGS: |
249 if (dyn_value & DF_TEXTREL) | 296 if (dyn_value & DF_TEXTREL) |
250 has_text_relocations_ = true; | 297 has_text_relocations_ = true; |
251 if (dyn_value & DF_SYMBOLIC) | 298 if (dyn_value & DF_SYMBOLIC) |
252 has_symbolic_ = true; | 299 has_symbolic_ = true; |
253 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", | 300 RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", |
254 has_text_relocations_ ? "true" : "false", | 301 has_text_relocations_ ? "true" : "false", |
255 has_symbolic_ ? "true" : "false"); | 302 has_symbolic_ ? "true" : "false"); |
256 break; | 303 break; |
257 #if defined(__mips__) | 304 #if defined(__mips__) |
258 case DT_MIPS_SYMTABNO: | 305 case DT_MIPS_SYMTABNO: |
259 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); | 306 RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); |
260 mips_symtab_count_ = dyn_value; | 307 mips_symtab_count_ = dyn_value; |
261 break; | 308 break; |
262 | 309 |
263 case DT_MIPS_LOCAL_GOTNO: | 310 case DT_MIPS_LOCAL_GOTNO: |
264 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); | 311 RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); |
265 mips_local_got_count_ = dyn_value; | 312 mips_local_got_count_ = dyn_value; |
266 break; | 313 break; |
267 | 314 |
268 case DT_MIPS_GOTSYM: | 315 case DT_MIPS_GOTSYM: |
269 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); | 316 RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); |
270 mips_gotsym_ = dyn_value; | 317 mips_gotsym_ = dyn_value; |
271 break; | 318 break; |
272 #endif | 319 #endif |
273 default: | 320 default: |
274 ; | 321 ; |
275 } | 322 } |
276 } | 323 } |
277 | 324 |
278 if (has_rel_relocations && has_rela_relocations) { | 325 if (has_rel_relocations && has_rela_relocations) { |
279 *error = "Combining DT_REL and DT_RELA is not currently supported"; | 326 *error = "Combining relocations with and without addends is not " |
| 327 "currently supported"; |
280 return false; | 328 return false; |
281 } | 329 } |
282 | 330 |
283 // If DT_PLTREL did not explicitly assign relocations_type_, set it | 331 // If DT_PLTREL did not explicitly assign relocations_type_, set it |
284 // here based on the type of relocations found. | 332 // here based on the type of relocations found. |
285 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { | 333 if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { |
286 if (has_rel_relocations) | 334 if (has_rel_relocations) |
287 relocations_type_ = DT_REL; | 335 relocations_type_ = DT_REL; |
288 else if (has_rela_relocations) | 336 else if (has_rela_relocations) |
289 relocations_type_ = DT_RELA; | 337 relocations_type_ = DT_RELA; |
290 } | 338 } |
291 | 339 |
292 if (relocations_type_ == DT_REL && has_rela_relocations) { | 340 if (relocations_type_ == DT_REL && has_rela_relocations) { |
293 *error = "Found DT_RELA in dyn section, but DT_PLTREL is DT_REL"; | 341 *error = "Found relocations with addends in dyn section, " |
| 342 "but DT_PLTREL is DT_REL"; |
294 return false; | 343 return false; |
295 } | 344 } |
296 if (relocations_type_ == DT_RELA && has_rel_relocations) { | 345 if (relocations_type_ == DT_RELA && has_rel_relocations) { |
297 *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA"; | 346 *error = "Found relocations without addends in dyn section, " |
| 347 "but DT_PLTREL is DT_RELA"; |
298 return false; | 348 return false; |
299 } | 349 } |
300 | 350 |
301 return true; | 351 return true; |
302 } | 352 } |
303 | 353 |
304 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, | 354 bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, |
305 SymbolResolver* resolver, | 355 SymbolResolver* resolver, |
306 Error* error) { | 356 Error* error) { |
307 LOG("%s: Enter\n", __FUNCTION__); | 357 LOG("%s: Enter\n", __FUNCTION__); |
308 | 358 |
309 if (has_text_relocations_) { | 359 if (has_text_relocations_) { |
310 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 360 if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
311 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); | 361 error->Format("Can't unprotect loadable segments: %s", strerror(errno)); |
312 return false; | 362 return false; |
313 } | 363 } |
314 } | 364 } |
315 | 365 |
316 #if defined(__arm__) || defined(__aarch64__) | 366 if (!ApplyAndroidRelocations(symbols, resolver, error)) |
317 if (!ApplyPackedRelocations(error)) | |
318 return false; | 367 return false; |
319 #endif | |
320 | 368 |
321 if (relocations_type_ == DT_REL) { | 369 if (relocations_type_ == DT_REL) { |
322 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), | 370 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), |
323 relocations_size_ / sizeof(ELF::Rel), | 371 relocations_size_ / sizeof(ELF::Rel), |
324 symbols, | 372 symbols, |
325 resolver, | 373 resolver, |
326 error)) | 374 error)) |
327 return false; | 375 return false; |
328 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), | 376 if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), |
329 plt_relocations_size_ / sizeof(ELF::Rel), | 377 plt_relocations_size_ / sizeof(ELF::Rel), |
(...skipping 27 matching lines...) Expand all Loading... |
357 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { | 405 if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { |
358 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); | 406 error->Format("Can't reprotect loadable segments: %s", strerror(errno)); |
359 return false; | 407 return false; |
360 } | 408 } |
361 } | 409 } |
362 | 410 |
363 LOG("%s: Done\n", __FUNCTION__); | 411 LOG("%s: Done\n", __FUNCTION__); |
364 return true; | 412 return true; |
365 } | 413 } |
366 | 414 |
367 #if defined(__arm__) || defined(__aarch64__) | 415 // Helper class for Android packed relocations. Encapsulates the packing |
| 416 // flags used by Android for packed relocation groups. |
| 417 class AndroidPackedRelocationGroupFlags { |
| 418 public: |
| 419 explicit AndroidPackedRelocationGroupFlags(size_t flags) : flags_(flags) { } |
368 | 420 |
369 bool ElfRelocations::ForEachPackedRel(const uint8_t* packed_relocations, | 421 bool is_relocation_grouped_by_info() const { |
370 RelRelocationHandler handler, | 422 return hasFlag(RELOCATION_GROUPED_BY_INFO_FLAG); |
371 void* opaque) { | 423 } |
372 Leb128Decoder decoder(packed_relocations); | 424 bool is_relocation_grouped_by_offset_delta() const { |
373 | 425 return hasFlag(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG); |
374 // Find the count of pairs and the start address. | 426 } |
375 size_t pairs = decoder.Dequeue(); | 427 bool is_relocation_grouped_by_addend() const { |
376 const ELF::Addr start_address = decoder.Dequeue(); | 428 return hasFlag(RELOCATION_GROUPED_BY_ADDEND_FLAG); |
377 | 429 } |
378 // Emit initial relative relocation. | 430 bool is_relocation_group_has_addend() const { |
379 ELF::Rel relocation; | 431 return hasFlag(RELOCATION_GROUP_HAS_ADDEND_FLAG); |
380 relocation.r_offset = start_address; | |
381 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); | |
382 const ELF::Addr sym_addr = 0; | |
383 const bool resolved = false; | |
384 if (!handler(this, &relocation, opaque)) | |
385 return false; | |
386 | |
387 size_t unpacked_count = 1; | |
388 | |
389 // Emit relocations for each count-delta pair. | |
390 while (pairs) { | |
391 size_t count = decoder.Dequeue(); | |
392 const size_t delta = decoder.Dequeue(); | |
393 | |
394 // Emit count relative relocations with delta offset. | |
395 while (count) { | |
396 relocation.r_offset += delta; | |
397 if (!handler(this, &relocation, opaque)) | |
398 return false; | |
399 unpacked_count++; | |
400 count--; | |
401 } | |
402 pairs--; | |
403 } | 432 } |
404 | 433 |
405 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); | 434 private: |
| 435 bool hasFlag(size_t flag) const { return (flags_ & flag) != 0; } |
| 436 |
| 437 static const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1 << 0; |
| 438 static const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 1 << 1; |
| 439 static const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 1 << 2; |
| 440 static const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 1 << 3; |
| 441 |
| 442 const size_t flags_; |
| 443 }; |
| 444 |
| 445 bool ElfRelocations::ForEachAndroidRelocation(RelocationHandler handler, |
| 446 void* opaque) { |
| 447 // Skip over the "APS2" signature. |
| 448 Sleb128Decoder decoder(android_relocations_ + 4, |
| 449 android_relocations_size_ - 4); |
| 450 |
| 451 // Unpacking into a relocation with addend, both for REL and RELA, is |
| 452 // convenient at this point. If REL, the handler needs to take care of |
| 453 // any conversion before use. |
| 454 ELF::Rela relocation; |
| 455 memset(&relocation, 0, sizeof(relocation)); |
| 456 |
| 457 // Read the relocation count and initial offset. |
| 458 const size_t relocation_count = decoder.pop_front(); |
| 459 relocation.r_offset = decoder.pop_front(); |
| 460 |
| 461 LOG("%s: relocation_count=%d, initial r_offset=%p\n", |
| 462 __FUNCTION__, |
| 463 relocation_count, |
| 464 relocation.r_offset); |
| 465 |
| 466 size_t relocations_handled = 0; |
| 467 while (relocations_handled < relocation_count) { |
| 468 // Read the start of the group header to obtain its size and flags. |
| 469 const size_t group_size = decoder.pop_front(); |
| 470 AndroidPackedRelocationGroupFlags group_flags(decoder.pop_front()); |
| 471 |
| 472 // Read other group header fields, depending on the flags read above. |
| 473 size_t group_r_offset_delta = 0; |
| 474 if (group_flags.is_relocation_grouped_by_offset_delta()) |
| 475 group_r_offset_delta = decoder.pop_front(); |
| 476 |
| 477 if (group_flags.is_relocation_grouped_by_info()) |
| 478 relocation.r_info = decoder.pop_front(); |
| 479 |
| 480 if (group_flags.is_relocation_group_has_addend() && |
| 481 group_flags.is_relocation_grouped_by_addend()) |
| 482 relocation.r_addend += decoder.pop_front(); |
| 483 else if (!group_flags.is_relocation_group_has_addend()) |
| 484 relocation.r_addend = 0; |
| 485 |
| 486 // Expand the group into individual relocations. |
| 487 for (size_t group_index = 0; group_index < group_size; group_index++) { |
| 488 if (group_flags.is_relocation_grouped_by_offset_delta()) |
| 489 relocation.r_offset += group_r_offset_delta; |
| 490 else |
| 491 relocation.r_offset += decoder.pop_front(); |
| 492 |
| 493 if (!group_flags.is_relocation_grouped_by_info()) |
| 494 relocation.r_info = decoder.pop_front(); |
| 495 |
| 496 if (group_flags.is_relocation_group_has_addend() && |
| 497 !group_flags.is_relocation_grouped_by_addend()) |
| 498 relocation.r_addend += decoder.pop_front(); |
| 499 |
| 500 // Pass the relocation to the supplied handler function. If the handler |
| 501 // returns false we view this as failure and return false to our caller. |
| 502 if (!handler(this, &relocation, opaque)) { |
| 503 LOG("%s: failed handling relocation %d\n", |
| 504 __FUNCTION__, |
| 505 relocations_handled); |
| 506 return false; |
| 507 } |
| 508 |
| 509 relocations_handled++; |
| 510 } |
| 511 } |
| 512 |
| 513 LOG("%s: relocations_handled=%d\n", __FUNCTION__, relocations_handled); |
406 return true; | 514 return true; |
407 } | 515 } |
408 | 516 |
409 bool ElfRelocations::ForEachPackedRela(const uint8_t* packed_relocations, | 517 namespace { |
410 RelaRelocationHandler handler, | |
411 void* opaque) { | |
412 Sleb128Decoder decoder(packed_relocations); | |
413 | 518 |
414 // Find the count of pairs. | 519 // Validate the Android packed relocations signature. |
415 size_t pairs = decoder.Dequeue(); | 520 bool IsValidAndroidPackedRelocations(const uint8_t* android_relocations, |
| 521 size_t android_relocations_size) { |
| 522 if (android_relocations_size < 4) |
| 523 return false; |
416 | 524 |
417 ELF::Addr offset = 0; | 525 // Check for an initial APS2 Android packed relocations header. |
418 ELF::Sxword addend = 0; | 526 return (android_relocations[0] == 'A' && |
| 527 android_relocations[1] == 'P' && |
| 528 android_relocations[2] == 'S' && |
| 529 android_relocations[3] == '2'); |
| 530 } |
419 | 531 |
420 const ELF::Addr sym_addr = 0; | 532 // Narrow a Rela to its equivalent Rel. The r_addend field in the input |
421 const bool resolved = false; | 533 // Rela must be zero. |
| 534 void ConvertRelaToRel(const ELF::Rela* rela, ELF::Rel* rel) { |
| 535 assert(rela->r_addend == 0); |
| 536 rel->r_offset = rela->r_offset; |
| 537 rel->r_info = rela->r_info; |
| 538 } |
422 | 539 |
423 size_t unpacked_count = 0; | 540 } // namespace |
424 | 541 |
425 // Emit relocations for each deltas pair. | 542 // Args for ApplyAndroidRelocation handler function. |
426 while (pairs) { | 543 struct ApplyAndroidRelocationArgs { |
427 offset += decoder.Dequeue(); | 544 ELF::Addr relocations_type; |
428 addend += decoder.Dequeue(); | 545 const ElfSymbols* symbols; |
| 546 ElfRelocations::SymbolResolver* resolver; |
| 547 Error* error; |
| 548 }; |
429 | 549 |
430 ELF::Rela relocation; | 550 // Static ForEachAndroidRelocation() handler. |
431 relocation.r_offset = offset; | 551 bool ElfRelocations::ApplyAndroidRelocation(ElfRelocations* relocations, |
432 relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); | 552 const ELF::Rela* relocation, |
433 relocation.r_addend = addend; | 553 void* opaque) { |
434 if (!handler(this, &relocation, opaque)) | 554 // Unpack args from opaque. |
435 return false; | 555 ApplyAndroidRelocationArgs* args = |
436 unpacked_count++; | 556 reinterpret_cast<ApplyAndroidRelocationArgs*>(opaque); |
437 pairs--; | 557 const ELF::Addr relocations_type = args->relocations_type; |
| 558 const ElfSymbols* symbols = args->symbols; |
| 559 ElfRelocations::SymbolResolver* resolver = args->resolver; |
| 560 Error* error = args->error; |
| 561 |
| 562 // For REL relocations, convert from RELA to REL and apply the conversion. |
| 563 // For RELA relocations, apply RELA directly. |
| 564 if (relocations_type == DT_REL) { |
| 565 ELF::Rel converted; |
| 566 ConvertRelaToRel(relocation, &converted); |
| 567 return relocations->ApplyRelReloc(&converted, symbols, resolver, error); |
438 } | 568 } |
439 | 569 |
440 RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); | 570 if (relocations_type == DT_RELA) |
| 571 return relocations->ApplyRelaReloc(relocation, symbols, resolver, error); |
| 572 |
441 return true; | 573 return true; |
442 } | 574 } |
443 | 575 |
444 bool ElfRelocations::ApplyPackedRel(ElfRelocations* relocations, | 576 bool ElfRelocations::ApplyAndroidRelocations(const ElfSymbols* symbols, |
445 const ELF::Rel* relocation, | 577 SymbolResolver* resolver, |
446 void* opaque) { | 578 Error* error) { |
447 Error* error = reinterpret_cast<Error*>(opaque); | 579 if (!android_relocations_) |
448 const ELF::Addr sym_addr = 0; | 580 return true; |
449 const bool resolved = false; | 581 |
450 return relocations->ApplyRelReloc(relocation, sym_addr, resolved, error); | 582 if (!IsValidAndroidPackedRelocations(android_relocations_, |
| 583 android_relocations_size_)) |
| 584 return false; |
| 585 |
| 586 ApplyAndroidRelocationArgs args; |
| 587 args.relocations_type = relocations_type_; |
| 588 args.symbols = symbols; |
| 589 args.resolver = resolver; |
| 590 args.error = error; |
| 591 return ForEachAndroidRelocation(&ApplyAndroidRelocation, &args); |
451 } | 592 } |
452 | 593 |
453 bool ElfRelocations::ApplyPackedRels(const uint8_t* packed_relocations, | 594 bool ElfRelocations::ApplyResolvedRelaReloc(const ELF::Rela* rela, |
454 Error* error) { | 595 ELF::Addr sym_addr, |
455 void* opaque = error; | 596 bool resolved CRAZY_UNUSED, |
456 return ForEachPackedRel(packed_relocations, &ApplyPackedRel, opaque); | 597 Error* error) { |
457 } | |
458 | |
459 bool ElfRelocations::ApplyPackedRela(ElfRelocations* relocations, | |
460 const ELF::Rela* relocation, | |
461 void* opaque) { | |
462 Error* error = reinterpret_cast<Error*>(opaque); | |
463 const ELF::Addr sym_addr = 0; | |
464 const bool resolved = false; | |
465 return relocations->ApplyRelaReloc(relocation, sym_addr, resolved, error); | |
466 } | |
467 | |
468 bool ElfRelocations::ApplyPackedRelas(const uint8_t* packed_relocations, | |
469 Error* error) { | |
470 void* opaque = error; | |
471 return ForEachPackedRela(packed_relocations, &ApplyPackedRela, opaque); | |
472 } | |
473 | |
474 bool ElfRelocations::ApplyPackedRelocations(Error* error) { | |
475 if (!packed_relocations_) | |
476 return true; | |
477 | |
478 // Check for an initial APR1 header, packed relocations. | |
479 if (packed_relocations_[0] == 'A' && | |
480 packed_relocations_[1] == 'P' && | |
481 packed_relocations_[2] == 'R' && | |
482 packed_relocations_[3] == '1') { | |
483 return ApplyPackedRels(packed_relocations_ + 4, error); | |
484 } | |
485 | |
486 // Check for an initial APA1 header, packed relocations with addend. | |
487 if (packed_relocations_[0] == 'A' && | |
488 packed_relocations_[1] == 'P' && | |
489 packed_relocations_[2] == 'A' && | |
490 packed_relocations_[3] == '1') { | |
491 return ApplyPackedRelas(packed_relocations_ + 4, error); | |
492 } | |
493 | |
494 error->Format("Bad packed relocations ident, expected APR1 or APA1"); | |
495 return false; | |
496 } | |
497 #endif // __arm__ || __aarch64__ | |
498 | |
499 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, | |
500 ELF::Addr sym_addr, | |
501 bool resolved CRAZY_UNUSED, | |
502 Error* error) { | |
503 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); | 598 const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); |
504 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); | 599 const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); |
505 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; | 600 const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; |
506 | 601 |
507 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | 602 const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
508 | 603 |
509 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", | 604 RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", |
510 reloc, | 605 reloc, |
511 rela->r_offset, | 606 rela->r_offset, |
512 rela_type, | 607 rela_type, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 #endif // __x86_64__ | 679 #endif // __x86_64__ |
585 | 680 |
586 default: | 681 default: |
587 error->Format("Invalid relocation type (%d)", rela_type); | 682 error->Format("Invalid relocation type (%d)", rela_type); |
588 return false; | 683 return false; |
589 } | 684 } |
590 | 685 |
591 return true; | 686 return true; |
592 } | 687 } |
593 | 688 |
594 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, | 689 bool ElfRelocations::ApplyResolvedRelReloc(const ELF::Rel* rel, |
595 ELF::Addr sym_addr, | 690 ELF::Addr sym_addr, |
596 bool resolved CRAZY_UNUSED, | 691 bool resolved CRAZY_UNUSED, |
597 Error* error) { | 692 Error* error) { |
598 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 693 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
599 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); | 694 const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); |
600 | 695 |
601 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | 696 const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
602 | 697 |
603 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); | 698 RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); |
604 | 699 |
605 // Apply the relocation. | 700 // Apply the relocation. |
606 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); | 701 ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); |
607 switch (rel_type) { | 702 switch (rel_type) { |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 return true; | 840 return true; |
746 } | 841 } |
747 | 842 |
748 error->Format( | 843 error->Format( |
749 "Invalid weak relocation type (%d) for unknown symbol '%s'", | 844 "Invalid weak relocation type (%d) for unknown symbol '%s'", |
750 r, | 845 r, |
751 sym_name); | 846 sym_name); |
752 return false; | 847 return false; |
753 } | 848 } |
754 | 849 |
| 850 bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, |
| 851 const ElfSymbols* symbols, |
| 852 SymbolResolver* resolver, |
| 853 Error* error) { |
| 854 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
| 855 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); |
| 856 |
| 857 ELF::Addr sym_addr = 0; |
| 858 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
| 859 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", |
| 860 reloc, |
| 861 rel->r_offset, |
| 862 rel_type, |
| 863 rel_symbol); |
| 864 |
| 865 if (rel_type == 0) |
| 866 return true; |
| 867 |
| 868 bool resolved = false; |
| 869 |
| 870 // If this is a symbolic relocation, compute the symbol's address. |
| 871 if (__builtin_expect(rel_symbol != 0, 0)) { |
| 872 if (!ResolveSymbol(rel_type, |
| 873 rel_symbol, |
| 874 symbols, |
| 875 resolver, |
| 876 reloc, |
| 877 &sym_addr, |
| 878 error)) { |
| 879 return false; |
| 880 } |
| 881 resolved = true; |
| 882 } |
| 883 |
| 884 return ApplyResolvedRelReloc(rel, sym_addr, resolved, error); |
| 885 } |
| 886 |
755 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, | 887 bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, |
756 size_t rel_count, | 888 size_t rel_count, |
757 const ElfSymbols* symbols, | 889 const ElfSymbols* symbols, |
758 SymbolResolver* resolver, | 890 SymbolResolver* resolver, |
759 Error* error) { | 891 Error* error) { |
760 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); | 892 RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); |
761 | 893 |
762 if (!rel) | 894 if (!rel) |
763 return true; | 895 return true; |
764 | 896 |
765 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { | 897 for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { |
766 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 898 RLOG(" Relocation %d of %d:\n", rel_n + 1, rel_count); |
767 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | |
768 | 899 |
769 ELF::Addr sym_addr = 0; | 900 if (!ApplyRelReloc(rel, symbols, resolver, error)) |
770 ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | |
771 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
772 rel_n + 1, | |
773 rel_count, | |
774 reloc, | |
775 rel->r_offset, | |
776 rel_type, | |
777 rel_symbol); | |
778 | |
779 if (rel_type == 0) | |
780 continue; | |
781 | |
782 bool resolved = false; | |
783 | |
784 // If this is a symbolic relocation, compute the symbol's address. | |
785 if (__builtin_expect(rel_symbol != 0, 0)) { | |
786 if (!ResolveSymbol(rel_type, | |
787 rel_symbol, | |
788 symbols, | |
789 resolver, | |
790 reloc, | |
791 &sym_addr, | |
792 error)) { | |
793 return false; | |
794 } | |
795 resolved = true; | |
796 } | |
797 | |
798 if (!ApplyRelReloc(rel, sym_addr, resolved, error)) | |
799 return false; | 901 return false; |
800 } | 902 } |
801 | 903 |
802 return true; | 904 return true; |
803 } | 905 } |
804 | 906 |
| 907 bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, |
| 908 const ElfSymbols* symbols, |
| 909 SymbolResolver* resolver, |
| 910 Error* error) { |
| 911 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); |
| 912 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); |
| 913 |
| 914 ELF::Addr sym_addr = 0; |
| 915 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); |
| 916 RLOG(" reloc=%p offset=%p type=%d symbol=%d\n", |
| 917 reloc, |
| 918 rela->r_offset, |
| 919 rel_type, |
| 920 rel_symbol); |
| 921 |
| 922 if (rel_type == 0) |
| 923 return true; |
| 924 |
| 925 bool resolved = false; |
| 926 |
| 927 // If this is a symbolic relocation, compute the symbol's address. |
| 928 if (__builtin_expect(rel_symbol != 0, 0)) { |
| 929 if (!ResolveSymbol(rel_type, |
| 930 rel_symbol, |
| 931 symbols, |
| 932 resolver, |
| 933 reloc, |
| 934 &sym_addr, |
| 935 error)) { |
| 936 return false; |
| 937 } |
| 938 resolved = true; |
| 939 } |
| 940 |
| 941 return ApplyResolvedRelaReloc(rela, sym_addr, resolved, error); |
| 942 } |
| 943 |
805 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, | 944 bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, |
806 size_t rela_count, | 945 size_t rela_count, |
807 const ElfSymbols* symbols, | 946 const ElfSymbols* symbols, |
808 SymbolResolver* resolver, | 947 SymbolResolver* resolver, |
809 Error* error) { | 948 Error* error) { |
810 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); | 949 RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); |
811 | 950 |
812 if (!rela) | 951 if (!rela) |
813 return true; | 952 return true; |
814 | 953 |
815 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { | 954 for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { |
816 const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); | 955 RLOG(" Relocation %d of %d:\n", rel_n + 1, rela_count); |
817 const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); | |
818 | 956 |
819 ELF::Addr sym_addr = 0; | 957 if (!ApplyRelaReloc(rela, symbols, resolver, error)) |
820 ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); | |
821 RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", | |
822 rel_n + 1, | |
823 rela_count, | |
824 reloc, | |
825 rela->r_offset, | |
826 rel_type, | |
827 rel_symbol); | |
828 | |
829 if (rel_type == 0) | |
830 continue; | |
831 | |
832 bool resolved = false; | |
833 | |
834 // If this is a symbolic relocation, compute the symbol's address. | |
835 if (__builtin_expect(rel_symbol != 0, 0)) { | |
836 if (!ResolveSymbol(rel_type, | |
837 rel_symbol, | |
838 symbols, | |
839 resolver, | |
840 reloc, | |
841 &sym_addr, | |
842 error)) { | |
843 return false; | |
844 } | |
845 resolved = true; | |
846 } | |
847 | |
848 if (!ApplyRelaReloc(rela, sym_addr, resolved, error)) | |
849 return false; | 958 return false; |
850 } | 959 } |
851 | 960 |
852 return true; | 961 return true; |
853 } | 962 } |
854 | 963 |
855 #ifdef __mips__ | 964 #ifdef __mips__ |
856 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, | 965 bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, |
857 SymbolResolver* resolver, | 966 SymbolResolver* resolver, |
858 Error* error) { | 967 Error* error) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 #ifdef __mips__ | 1043 #ifdef __mips__ |
935 case R_MIPS_REL32: | 1044 case R_MIPS_REL32: |
936 *dst_ptr += map_delta; | 1045 *dst_ptr += map_delta; |
937 break; | 1046 break; |
938 #endif | 1047 #endif |
939 default: | 1048 default: |
940 ; | 1049 ; |
941 } | 1050 } |
942 } | 1051 } |
943 | 1052 |
944 #if defined(__arm__) || defined(__aarch64__) | 1053 void ElfRelocations::AdjustAndroidRelocation(const ELF::Rela* relocation, |
| 1054 size_t src_addr, |
| 1055 size_t dst_addr, |
| 1056 size_t map_addr, |
| 1057 size_t size) { |
| 1058 // Add this value to each source address to get the corresponding |
| 1059 // destination address. |
| 1060 const size_t dst_delta = dst_addr - src_addr; |
| 1061 const size_t map_delta = map_addr - src_addr; |
945 | 1062 |
946 struct AdjustRelocationArgs { | 1063 const ELF::Word rel_type = ELF_R_TYPE(relocation->r_info); |
| 1064 const ELF::Word rel_symbol = ELF_R_SYM(relocation->r_info); |
| 1065 ELF::Addr src_reloc = |
| 1066 static_cast<ELF::Addr>(relocation->r_offset + load_bias_); |
| 1067 |
| 1068 if (rel_type == 0 || rel_symbol != 0) { |
| 1069 // Ignore empty and symbolic relocations |
| 1070 return; |
| 1071 } |
| 1072 |
| 1073 if (src_reloc < src_addr || src_reloc >= src_addr + size) { |
| 1074 // Ignore entries that don't relocate addresses inside the source section. |
| 1075 return; |
| 1076 } |
| 1077 |
| 1078 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); |
| 1079 } |
| 1080 |
| 1081 // Args for ApplyAndroidRelocation handler function. |
| 1082 struct RelocateAndroidRelocationArgs { |
947 size_t src_addr; | 1083 size_t src_addr; |
948 size_t dst_addr; | 1084 size_t dst_addr; |
949 size_t map_addr; | 1085 size_t map_addr; |
950 size_t size; | 1086 size_t size; |
951 }; | 1087 }; |
952 | 1088 |
953 template<typename Rel> | 1089 // Static ForEachAndroidRelocation() handler. |
954 bool ElfRelocations::RelocatePackedRelocation(ElfRelocations* relocations, | 1090 bool ElfRelocations::RelocateAndroidRelocation(ElfRelocations* relocations, |
955 const Rel* rel, | 1091 const ELF::Rela* relocation, |
956 void* opaque) { | 1092 void* opaque) { |
957 AdjustRelocationArgs* args = reinterpret_cast<AdjustRelocationArgs*>(opaque); | 1093 // Unpack args from opaque, to obtain addrs and size; |
| 1094 RelocateAndroidRelocationArgs* args = |
| 1095 reinterpret_cast<RelocateAndroidRelocationArgs*>(opaque); |
958 const size_t src_addr = args->src_addr; | 1096 const size_t src_addr = args->src_addr; |
959 const size_t dst_addr = args->dst_addr; | 1097 const size_t dst_addr = args->dst_addr; |
960 const size_t map_addr = args->map_addr; | 1098 const size_t map_addr = args->map_addr; |
961 const size_t size = args->size; | 1099 const size_t size = args->size; |
962 | 1100 |
963 const size_t load_bias = relocations->load_bias_; | 1101 // Relocate the given relocation. Because the r_addend field is ignored |
964 | 1102 // in relocating RELA relocations we do not need to convert from REL to |
965 const size_t dst_delta = dst_addr - src_addr; | 1103 // RELA and supply alternative relocator functions; instead we can work |
966 const size_t map_delta = map_addr - src_addr; | 1104 // here directly on the RELA supplied by ForEachAndroidRelocation(), even |
967 | 1105 // on REL architectures. |
968 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 1106 relocations->AdjustAndroidRelocation(relocation, |
969 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | 1107 src_addr, |
970 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias); | 1108 dst_addr, |
971 | 1109 map_addr, |
972 if (rel_type == 0 || rel_symbol != 0) { | 1110 size); |
973 // Ignore empty and symbolic relocations | |
974 return true; | |
975 } | |
976 | |
977 if (src_reloc < src_addr || src_reloc >= src_addr + size) { | |
978 // Ignore entries that don't relocate addresses inside the source section. | |
979 return true; | |
980 } | |
981 | |
982 relocations->AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); | |
983 return true; | 1111 return true; |
984 } | 1112 } |
985 | 1113 |
986 template bool ElfRelocations::RelocatePackedRelocation<ELF::Rel>( | 1114 void ElfRelocations::RelocateAndroidRelocations(size_t src_addr, |
987 ElfRelocations* relocations, const ELF::Rel* rel, void* opaque); | 1115 size_t dst_addr, |
| 1116 size_t map_addr, |
| 1117 size_t size) { |
| 1118 if (!android_relocations_) |
| 1119 return; |
988 | 1120 |
989 template bool ElfRelocations::RelocatePackedRelocation<ELF::Rela>( | 1121 assert(IsValidAndroidPackedRelocations(android_relocations_, |
990 ElfRelocations* relocations, const ELF::Rela* rel, void* opaque); | 1122 android_relocations_size_)); |
991 | 1123 |
992 void ElfRelocations::RelocatePackedRels(const uint8_t* packed_relocations, | 1124 RelocateAndroidRelocationArgs args; |
993 size_t src_addr, | |
994 size_t dst_addr, | |
995 size_t map_addr, | |
996 size_t size) { | |
997 AdjustRelocationArgs args; | |
998 args.src_addr = src_addr; | 1125 args.src_addr = src_addr; |
999 args.dst_addr = dst_addr; | 1126 args.dst_addr = dst_addr; |
1000 args.map_addr = map_addr; | 1127 args.map_addr = map_addr; |
1001 args.size = size; | 1128 args.size = size; |
1002 ForEachPackedRel(packed_relocations, | 1129 ForEachAndroidRelocation(&RelocateAndroidRelocation, &args); |
1003 &RelocatePackedRelocation<ELF::Rel>, &args); | |
1004 } | 1130 } |
1005 | 1131 |
1006 void ElfRelocations::RelocatePackedRelas(const uint8_t* packed_relocations, | 1132 template<typename Rel> |
1007 size_t src_addr, | 1133 void ElfRelocations::RelocateRelocations(size_t src_addr, |
1008 size_t dst_addr, | 1134 size_t dst_addr, |
1009 size_t map_addr, | 1135 size_t map_addr, |
1010 size_t size) { | 1136 size_t size) { |
1011 AdjustRelocationArgs args; | |
1012 args.src_addr = src_addr; | |
1013 args.dst_addr = dst_addr; | |
1014 args.map_addr = map_addr; | |
1015 args.size = size; | |
1016 ForEachPackedRela(packed_relocations, | |
1017 &RelocatePackedRelocation<ELF::Rela>, &args); | |
1018 } | |
1019 | |
1020 void ElfRelocations::RelocatePackedRelocations(size_t src_addr, | |
1021 size_t dst_addr, | |
1022 size_t map_addr, | |
1023 size_t size) { | |
1024 if (!packed_relocations_) | |
1025 return; | |
1026 | |
1027 // Check for an initial APR1 header, packed relocations. | |
1028 if (packed_relocations_[0] == 'A' && | |
1029 packed_relocations_[1] == 'P' && | |
1030 packed_relocations_[2] == 'R' && | |
1031 packed_relocations_[3] == '1') { | |
1032 RelocatePackedRels(packed_relocations_ + 4, | |
1033 src_addr, dst_addr, map_addr, size); | |
1034 } | |
1035 | |
1036 // Check for an initial APA1 header, packed relocations with addend. | |
1037 if (packed_relocations_[0] == 'A' && | |
1038 packed_relocations_[1] == 'P' && | |
1039 packed_relocations_[2] == 'A' && | |
1040 packed_relocations_[3] == '1') { | |
1041 RelocatePackedRelas(packed_relocations_ + 4, | |
1042 src_addr, dst_addr, map_addr, size); | |
1043 } | |
1044 } | |
1045 | |
1046 #endif // __arm__ || __aarch64__ | |
1047 | |
1048 template<typename Rel> | |
1049 void ElfRelocations::RelocateRelocation(size_t src_addr, | |
1050 size_t dst_addr, | |
1051 size_t map_addr, | |
1052 size_t size) { | |
1053 // Add this value to each source address to get the corresponding | 1137 // Add this value to each source address to get the corresponding |
1054 // destination address. | 1138 // destination address. |
1055 const size_t dst_delta = dst_addr - src_addr; | 1139 const size_t dst_delta = dst_addr - src_addr; |
1056 const size_t map_delta = map_addr - src_addr; | 1140 const size_t map_delta = map_addr - src_addr; |
1057 | 1141 |
1058 // Ignore PLT relocations, which all target symbols (ignored here). | 1142 // Ignore PLT relocations, which all target symbols (ignored here). |
1059 const Rel* rel = reinterpret_cast<Rel*>(relocations_); | 1143 const Rel* rel = reinterpret_cast<Rel*>(relocations_); |
1060 const size_t relocations_count = relocations_size_ / sizeof(Rel); | 1144 const size_t relocations_count = relocations_size_ / sizeof(Rel); |
1061 const Rel* rel_limit = rel + relocations_count; | 1145 const Rel* rel_limit = rel + relocations_count; |
1062 | 1146 |
1063 for (; rel < rel_limit; ++rel) { | 1147 for (; rel < rel_limit; ++rel) { |
1064 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); | 1148 const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); |
1065 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); | 1149 const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); |
1066 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); | 1150 ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); |
1067 | 1151 |
1068 if (rel_type == 0 || rel_symbol != 0) { | 1152 if (rel_type == 0 || rel_symbol != 0) { |
1069 // Ignore empty and symbolic relocations | 1153 // Ignore empty and symbolic relocations |
1070 continue; | 1154 continue; |
1071 } | 1155 } |
1072 | 1156 |
1073 if (src_reloc < src_addr || src_reloc >= src_addr + size) { | 1157 if (src_reloc < src_addr || src_reloc >= src_addr + size) { |
1074 // Ignore entries that don't relocate addresses inside the source section. | 1158 // Ignore entries that don't relocate addresses inside the source section. |
1075 continue; | 1159 continue; |
1076 } | 1160 } |
1077 | 1161 |
1078 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); | 1162 AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); |
1079 } | 1163 } |
1080 } | 1164 } |
1081 | 1165 |
1082 template void ElfRelocations::RelocateRelocation<ELF::Rel>( | 1166 template void ElfRelocations::RelocateRelocations<ELF::Rel>( |
1083 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); | 1167 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); |
1084 | 1168 |
1085 template void ElfRelocations::RelocateRelocation<ELF::Rela>( | 1169 template void ElfRelocations::RelocateRelocations<ELF::Rela>( |
1086 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); | 1170 size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); |
1087 | 1171 |
1088 void ElfRelocations::CopyAndRelocate(size_t src_addr, | 1172 void ElfRelocations::CopyAndRelocate(size_t src_addr, |
1089 size_t dst_addr, | 1173 size_t dst_addr, |
1090 size_t map_addr, | 1174 size_t map_addr, |
1091 size_t size) { | 1175 size_t size) { |
1092 // First, a straight copy. | 1176 // First, a straight copy. |
1093 ::memcpy(reinterpret_cast<void*>(dst_addr), | 1177 ::memcpy(reinterpret_cast<void*>(dst_addr), |
1094 reinterpret_cast<void*>(src_addr), | 1178 reinterpret_cast<void*>(src_addr), |
1095 size); | 1179 size); |
1096 | 1180 |
1097 #if defined(__arm__) || defined(__aarch64__) | 1181 // Relocate android relocations. |
1098 // Relocate packed relative relocations. | 1182 RelocateAndroidRelocations(src_addr, dst_addr, map_addr, size); |
1099 RelocatePackedRelocations(src_addr, dst_addr, map_addr, size); | |
1100 #endif | |
1101 | 1183 |
1102 // Relocate relocations. | 1184 // Relocate relocations. |
1103 if (relocations_type_ == DT_REL) | 1185 if (relocations_type_ == DT_REL) |
1104 RelocateRelocation<ELF::Rel>(src_addr, dst_addr, map_addr, size); | 1186 RelocateRelocations<ELF::Rel>(src_addr, dst_addr, map_addr, size); |
1105 | 1187 |
1106 if (relocations_type_ == DT_RELA) | 1188 if (relocations_type_ == DT_RELA) |
1107 RelocateRelocation<ELF::Rela>(src_addr, dst_addr, map_addr, size); | 1189 RelocateRelocations<ELF::Rela>(src_addr, dst_addr, map_addr, size); |
1108 | 1190 |
1109 #ifdef __mips__ | 1191 #ifdef __mips__ |
1110 // Add this value to each source address to get the corresponding | 1192 // Add this value to each source address to get the corresponding |
1111 // destination address. | 1193 // destination address. |
1112 const size_t dst_delta = dst_addr - src_addr; | 1194 const size_t dst_delta = dst_addr - src_addr; |
1113 const size_t map_delta = map_addr - src_addr; | 1195 const size_t map_delta = map_addr - src_addr; |
1114 | 1196 |
1115 // Only relocate local GOT entries. | 1197 // Only relocate local GOT entries. |
1116 ELF::Addr* got = plt_got_; | 1198 ELF::Addr* got = plt_got_; |
1117 if (got) { | 1199 if (got) { |
1118 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { | 1200 for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { |
1119 size_t got_addr = reinterpret_cast<size_t>(&got[n]); | 1201 size_t got_addr = reinterpret_cast<size_t>(&got[n]); |
1120 if (got_addr < src_addr || got_addr >= src_addr + size) | 1202 if (got_addr < src_addr || got_addr >= src_addr + size) |
1121 continue; | 1203 continue; |
1122 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); | 1204 ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); |
1123 *dst_ptr += map_delta; | 1205 *dst_ptr += map_delta; |
1124 } | 1206 } |
1125 } | 1207 } |
1126 #endif | 1208 #endif |
1127 } | 1209 } |
1128 | 1210 |
1129 } // namespace crazy | 1211 } // namespace crazy |
OLD | NEW |