blob: c6a8cf620ab2f7d3ea1c7e921f12e06743265fa2 [file] [log] [blame]
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08003 * All rights reserved.
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -08004 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -08005 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080014 *
Dimitry Ivanovbcc4da92017-02-15 15:31:13 -080015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080027 */
28
Elliott Hughescbc80ba2018-02-13 14:26:29 -080029#pragma once
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080030
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080031#include <string.h>
32
Ryan Prichard339ecef2020-01-02 16:36:06 -080033#include "linker.h"
34#include "linker_sleb128.h"
35
Dmitriy Ivanov20d89cb2015-03-30 18:43:38 -070036const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1;
37const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2;
38const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4;
39const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080040
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080041#if defined(USE_RELA)
Ryan Prichard339ecef2020-01-02 16:36:06 -080042typedef ElfW(Rela) rel_t;
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080043#else
Ryan Prichard339ecef2020-01-02 16:36:06 -080044typedef ElfW(Rel) rel_t;
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080045#endif
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080046
Ryan Prichard339ecef2020-01-02 16:36:06 -080047template <typename F>
48inline bool for_all_packed_relocs(sleb128_decoder decoder, F&& callback) {
49 const size_t num_relocs = decoder.pop_front();
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080050
Ryan Prichard339ecef2020-01-02 16:36:06 -080051 rel_t reloc = {
52 .r_offset = decoder.pop_front(),
53 };
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080054
Ryan Prichard339ecef2020-01-02 16:36:06 -080055 for (size_t idx = 0; idx < num_relocs; ) {
56 const size_t group_size = decoder.pop_front();
57 const size_t group_flags = decoder.pop_front();
Dmitriy Ivanovfa26eee2015-02-03 16:06:47 -080058
Ryan Prichard339ecef2020-01-02 16:36:06 -080059 size_t group_r_offset_delta = 0;
60
61 if (group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) {
62 group_r_offset_delta = decoder.pop_front();
63 }
64 if (group_flags & RELOCATION_GROUPED_BY_INFO_FLAG) {
65 reloc.r_info = decoder.pop_front();
66 }
67
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080068#if defined(USE_RELA)
Ryan Prichard339ecef2020-01-02 16:36:06 -080069 const size_t group_flags_reloc = group_flags & (RELOCATION_GROUP_HAS_ADDEND_FLAG |
70 RELOCATION_GROUPED_BY_ADDEND_FLAG);
71 if (group_flags_reloc == RELOCATION_GROUP_HAS_ADDEND_FLAG) {
72 // Each relocation has an addend. This is the default situation with lld's current encoder.
73 } else if (group_flags_reloc == (RELOCATION_GROUP_HAS_ADDEND_FLAG |
74 RELOCATION_GROUPED_BY_ADDEND_FLAG)) {
75 reloc.r_addend += decoder.pop_front();
76 } else {
77 reloc.r_addend = 0;
78 }
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080079#else
Ryan Prichard339ecef2020-01-02 16:36:06 -080080 if (__predict_false(group_flags & RELOCATION_GROUP_HAS_ADDEND_FLAG)) {
81 // This platform does not support rela, and yet we have it encoded in android_rel section.
82 async_safe_fatal("unexpected r_addend in android.rel section");
83 }
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080084#endif
Dmitriy Ivanov18a69562015-02-04 16:05:30 -080085
Ryan Prichard339ecef2020-01-02 16:36:06 -080086 for (size_t i = 0; i < group_size; ++i) {
87 if (group_flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) {
88 reloc.r_offset += group_r_offset_delta;
89 } else {
90 reloc.r_offset += decoder.pop_front();
91 }
92 if ((group_flags & RELOCATION_GROUPED_BY_INFO_FLAG) == 0) {
93 reloc.r_info = decoder.pop_front();
94 }
95#if defined(USE_RELA)
96 if (group_flags_reloc == RELOCATION_GROUP_HAS_ADDEND_FLAG) {
97 reloc.r_addend += decoder.pop_front();
98 }
99#endif
100 if (!callback(reloc)) {
101 return false;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -0800102 }
103 }
104
Ryan Prichard339ecef2020-01-02 16:36:06 -0800105 idx += group_size;
Dmitriy Ivanov18a69562015-02-04 16:05:30 -0800106 }
107
Ryan Prichard339ecef2020-01-02 16:36:06 -0800108 return true;
109}