xref: /aosp_15_r20/art/dex2oat/linker/relative_patcher.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_DEX2OAT_LINKER_RELATIVE_PATCHER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_DEX2OAT_LINKER_RELATIVE_PATCHER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <vector>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
23*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
26*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace art {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker class CompiledMethod;
31*795d594fSAndroid Build Coastguard Worker class OutputStream;
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker namespace debug {
34*795d594fSAndroid Build Coastguard Worker struct MethodDebugInfo;
35*795d594fSAndroid Build Coastguard Worker }  // namespace debug
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker namespace linker {
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker class LinkerPatch;
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker /**
42*795d594fSAndroid Build Coastguard Worker  * @class RelativePatcherThunkProvider
43*795d594fSAndroid Build Coastguard Worker  * @brief Interface for providing method offsets for relative call targets.
44*795d594fSAndroid Build Coastguard Worker  */
45*795d594fSAndroid Build Coastguard Worker class RelativePatcherThunkProvider {
46*795d594fSAndroid Build Coastguard Worker  public:
47*795d594fSAndroid Build Coastguard Worker   /**
48*795d594fSAndroid Build Coastguard Worker    * Get the code and debug name of a thunk needed by the given linker patch.
49*795d594fSAndroid Build Coastguard Worker    *
50*795d594fSAndroid Build Coastguard Worker    * @param patch The patch for which we need to retrieve the thunk code.
51*795d594fSAndroid Build Coastguard Worker    * @param code A variable to receive the code of the thunk. This code must not be empty.
52*795d594fSAndroid Build Coastguard Worker    * @param debug_name A variable to receive the debug name of the thunk.
53*795d594fSAndroid Build Coastguard Worker    */
54*795d594fSAndroid Build Coastguard Worker   virtual void GetThunkCode(const LinkerPatch& patch,
55*795d594fSAndroid Build Coastguard Worker                             /*out*/ ArrayRef<const uint8_t>* code,
56*795d594fSAndroid Build Coastguard Worker                             /*out*/ std::string* debug_name) = 0;
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker  protected:
~RelativePatcherThunkProvider()59*795d594fSAndroid Build Coastguard Worker   virtual ~RelativePatcherThunkProvider() { }
60*795d594fSAndroid Build Coastguard Worker };
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker /**
63*795d594fSAndroid Build Coastguard Worker  * @class RelativePatcherTargetProvider
64*795d594fSAndroid Build Coastguard Worker  * @brief Interface for providing method offsets for relative call targets.
65*795d594fSAndroid Build Coastguard Worker  */
66*795d594fSAndroid Build Coastguard Worker class RelativePatcherTargetProvider {
67*795d594fSAndroid Build Coastguard Worker  public:
68*795d594fSAndroid Build Coastguard Worker   /**
69*795d594fSAndroid Build Coastguard Worker    * Find the offset of the target method of a relative call if known.
70*795d594fSAndroid Build Coastguard Worker    *
71*795d594fSAndroid Build Coastguard Worker    * The process of assigning target method offsets includes calls to the relative patcher's
72*795d594fSAndroid Build Coastguard Worker    * ReserveSpace() which in turn can use FindMethodOffset() to determine if a method already
73*795d594fSAndroid Build Coastguard Worker    * has an offset assigned and, if so, what's that offset. If the offset has not yet been
74*795d594fSAndroid Build Coastguard Worker    * assigned or if it's too far for the particular architecture's relative call,
75*795d594fSAndroid Build Coastguard Worker    * ReserveSpace() may need to allocate space for a special dispatch thunk.
76*795d594fSAndroid Build Coastguard Worker    *
77*795d594fSAndroid Build Coastguard Worker    * @param ref the target method of the relative call.
78*795d594fSAndroid Build Coastguard Worker    * @return true in the first element of the pair if the method was found, false otherwise;
79*795d594fSAndroid Build Coastguard Worker    *         if found, the second element specifies the offset.
80*795d594fSAndroid Build Coastguard Worker    */
81*795d594fSAndroid Build Coastguard Worker   virtual std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) = 0;
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker  protected:
~RelativePatcherTargetProvider()84*795d594fSAndroid Build Coastguard Worker   virtual ~RelativePatcherTargetProvider() { }
85*795d594fSAndroid Build Coastguard Worker };
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker /**
88*795d594fSAndroid Build Coastguard Worker  * @class RelativePatcher
89*795d594fSAndroid Build Coastguard Worker  * @brief Interface for architecture-specific link-time patching of PC-relative references.
90*795d594fSAndroid Build Coastguard Worker  */
91*795d594fSAndroid Build Coastguard Worker class RelativePatcher {
92*795d594fSAndroid Build Coastguard Worker  public:
93*795d594fSAndroid Build Coastguard Worker   static std::unique_ptr<RelativePatcher> Create(
94*795d594fSAndroid Build Coastguard Worker       InstructionSet instruction_set,
95*795d594fSAndroid Build Coastguard Worker       const InstructionSetFeatures* features,
96*795d594fSAndroid Build Coastguard Worker       RelativePatcherThunkProvider* thunk_provider,
97*795d594fSAndroid Build Coastguard Worker       RelativePatcherTargetProvider* target_provider);
98*795d594fSAndroid Build Coastguard Worker 
~RelativePatcher()99*795d594fSAndroid Build Coastguard Worker   virtual ~RelativePatcher() { }
100*795d594fSAndroid Build Coastguard Worker 
CodeAlignmentSize()101*795d594fSAndroid Build Coastguard Worker   uint32_t CodeAlignmentSize() const {
102*795d594fSAndroid Build Coastguard Worker     return size_code_alignment_;
103*795d594fSAndroid Build Coastguard Worker   }
104*795d594fSAndroid Build Coastguard Worker 
RelativeCallThunksSize()105*795d594fSAndroid Build Coastguard Worker   uint32_t RelativeCallThunksSize() const {
106*795d594fSAndroid Build Coastguard Worker     return size_relative_call_thunks_;
107*795d594fSAndroid Build Coastguard Worker   }
108*795d594fSAndroid Build Coastguard Worker 
MiscThunksSize()109*795d594fSAndroid Build Coastguard Worker   uint32_t MiscThunksSize() const {
110*795d594fSAndroid Build Coastguard Worker     return size_misc_thunks_;
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   // Reserve space for thunks if needed before a method, return adjusted offset.
114*795d594fSAndroid Build Coastguard Worker   virtual uint32_t ReserveSpace(uint32_t offset,
115*795d594fSAndroid Build Coastguard Worker                                 const CompiledMethod* compiled_method,
116*795d594fSAndroid Build Coastguard Worker                                 MethodReference method_ref) = 0;
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker   // Reserve space for thunks if needed after the last method, return adjusted offset.
119*795d594fSAndroid Build Coastguard Worker   // The caller may use this method to preemptively force thunk space reservation and
120*795d594fSAndroid Build Coastguard Worker   // then resume reservation for more methods. This is useful when there is a gap in
121*795d594fSAndroid Build Coastguard Worker   // the .text segment, for example when going to the next oat file for multi-image.
122*795d594fSAndroid Build Coastguard Worker   virtual uint32_t ReserveSpaceEnd(uint32_t offset) = 0;
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker   // Write relative call thunks if needed, return adjusted offset. Returns 0 on write failure.
125*795d594fSAndroid Build Coastguard Worker   virtual uint32_t WriteThunks(OutputStream* out, uint32_t offset) = 0;
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   // Patch method code. The input displacement is relative to the patched location,
128*795d594fSAndroid Build Coastguard Worker   // the patcher may need to adjust it if the correct base is different.
129*795d594fSAndroid Build Coastguard Worker   virtual void PatchCall(std::vector<uint8_t>* code,
130*795d594fSAndroid Build Coastguard Worker                          uint32_t literal_offset,
131*795d594fSAndroid Build Coastguard Worker                          uint32_t patch_offset,
132*795d594fSAndroid Build Coastguard Worker                          uint32_t target_offset) = 0;
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker   // Patch a reference to a dex cache location.
135*795d594fSAndroid Build Coastguard Worker   virtual void PatchPcRelativeReference(std::vector<uint8_t>* code,
136*795d594fSAndroid Build Coastguard Worker                                         const LinkerPatch& patch,
137*795d594fSAndroid Build Coastguard Worker                                         uint32_t patch_offset,
138*795d594fSAndroid Build Coastguard Worker                                         uint32_t target_offset) = 0;
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker   // Patch a call to an entrypoint trampoline.
141*795d594fSAndroid Build Coastguard Worker   virtual void PatchEntrypointCall(std::vector<uint8_t>* code,
142*795d594fSAndroid Build Coastguard Worker                                    const LinkerPatch& patch,
143*795d594fSAndroid Build Coastguard Worker                                    uint32_t patch_offset) = 0;
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   // Patch a branch to a Baker read barrier thunk.
146*795d594fSAndroid Build Coastguard Worker   virtual void PatchBakerReadBarrierBranch(std::vector<uint8_t>* code,
147*795d594fSAndroid Build Coastguard Worker                                            const LinkerPatch& patch,
148*795d594fSAndroid Build Coastguard Worker                                            uint32_t patch_offset) = 0;
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker   virtual std::vector<debug::MethodDebugInfo> GenerateThunkDebugInfo(
151*795d594fSAndroid Build Coastguard Worker       uint32_t executable_offset) = 0;
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker  protected:
RelativePatcher()154*795d594fSAndroid Build Coastguard Worker   RelativePatcher()
155*795d594fSAndroid Build Coastguard Worker       : size_code_alignment_(0u),
156*795d594fSAndroid Build Coastguard Worker         size_relative_call_thunks_(0u),
157*795d594fSAndroid Build Coastguard Worker         size_misc_thunks_(0u) {
158*795d594fSAndroid Build Coastguard Worker   }
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   bool WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta);
161*795d594fSAndroid Build Coastguard Worker   bool WriteThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk);
162*795d594fSAndroid Build Coastguard Worker   bool WriteMiscThunk(OutputStream* out, const ArrayRef<const uint8_t>& thunk);
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker  private:
165*795d594fSAndroid Build Coastguard Worker   uint32_t size_code_alignment_;
166*795d594fSAndroid Build Coastguard Worker   uint32_t size_relative_call_thunks_;
167*795d594fSAndroid Build Coastguard Worker   uint32_t size_misc_thunks_;
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(RelativePatcher);
170*795d594fSAndroid Build Coastguard Worker };
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker }  // namespace linker
173*795d594fSAndroid Build Coastguard Worker }  // namespace art
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker #endif  // ART_DEX2OAT_LINKER_RELATIVE_PATCHER_H_
176