• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/deoptimizer/relocator.h"
17 #include <climits>
18 #include <iomanip>
19 #include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h"
20 #include "ecmascript/message_string.h"
21 #if !WIN_OR_MAC_OR_IOS_PLATFORM
22 
23 namespace panda::ecmascript {
GetSymbol(const char * symbol) const24 std::optional<Elf64_Word> Relocator::GetSymbol(const char* symbol) const
25 {
26     ASSERT(symAndStrTabInfo_.symSize_ % sizeof(Elf64_Sym) == 0);
27     int n = symAndStrTabInfo_.symSize_ / sizeof(Elf64_Sym);
28     ASSERT(symAndStrTabInfo_.symAddr_ > 0 && symAndStrTabInfo_.symSize_ > 0);
29     Elf64_Sym *ptr = reinterpret_cast<Elf64_Sym *>(symAndStrTabInfo_.symAddr_);
30     for (int i = 0; i < n; i++) {
31         Elf64_Sym *cur = ptr + i;
32         const char *name = reinterpret_cast<char *>(symAndStrTabInfo_.strAddr_) + cur->st_name;
33         if (std::strcmp(symbol, name) == 0) {
34             return static_cast<Elf64_Word>(i);
35         }
36     }
37     return std::nullopt;
38 }
39 
Relocate(Elf64_Rela * sec,uintptr_t symbolAddr,uintptr_t patchAddr)40 bool Relocator::Relocate(Elf64_Rela *sec, uintptr_t symbolAddr, uintptr_t patchAddr)
41 {
42     bool ret = false;
43     ASSERT(reinterpret_cast<intptr_t>(sec) > 0);
44     Elf64_Word type = GetType(sec);
45     Elf64_Sxword addend = sec->r_addend;
46 
47     switch (type) {
48         case R_AARCH64_CALL26: {
49             /* S + A - P
50             S: (when used on its own) is the address of the symbol
51             A: is the addend for the relocation
52             P: is the address of the place beging relocated(derived from r_offset)
53             */
54             intptr_t imm = patchAddr + addend - symbolAddr;
55             if (BlInRange(imm)) {
56                 imm = (imm & 0x0FFFFFFC) >> 2; // 0x0FFFFFFC: get immediate file to bits [27:2]
57                 *(reinterpret_cast<uint32_t *>(symbolAddr)) = imm | panda::ecmascript::aarch64::CallOpCode::BL;
58                 ret = true;
59             }
60             break;
61         }
62         case R_X86_64_PLT32: {
63             /* S + A - P
64             S: (when used on its own) is the address of the symbol
65             A: is the addend for the relocation
66             P: is the address of the place beging relocated(derived from r_offset)
67             */
68             intptr_t v = patchAddr + addend - symbolAddr;
69             ASSERT((v >= INT_MIN) && (v <= INT_MAX));
70             *(reinterpret_cast<uint32_t *>(symbolAddr)) = v;
71             ret = true;
72             break;
73         }
74         default: {
75             LOG_COMPILER(FATAL) << " unsupported type:" << type;
76             return false;
77         }
78     }
79     return ret;
80 }
81 
HasSymStrTable() const82 bool Relocator::HasSymStrTable() const
83 {
84     return (symAndStrTabInfo_.symAddr_ >= 0) && (symAndStrTabInfo_.symSize_ >= 0)
85         && (symAndStrTabInfo_.strAddr_ >= 0) && (symAndStrTabInfo_.strSize_ >= 0);
86 }
87 
HasRelocateText() const88 bool Relocator::HasRelocateText() const
89 {
90     return (relocateTextInfo_.relaTextAddr_ > 0) && (relocateTextInfo_.relaTextSize_ > 0);
91 }
92 
RelocateBySymbolId(Elf64_Word symbolId,uintptr_t patchAddr)93 bool Relocator::RelocateBySymbolId(Elf64_Word symbolId, uintptr_t patchAddr)
94 {
95     bool ret = false;
96     ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
97     ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
98     size_t n  = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
99     Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
100     for (size_t i = 0; i < n; i++) {
101         Elf64_Rela *cur = ptr + i;
102         Elf64_Word id = GetSymbol(cur);
103         intptr_t symbolAddr = relocateTextInfo_.textAddr_ + static_cast<uintptr_t>(cur->r_offset);
104         if (id == symbolId) {
105             ret = Relocate(cur, symbolAddr, patchAddr);
106         }
107     }
108     return ret;
109 }
110 
RelocateBySymbol(const char * symbol,uintptr_t patchAddr)111 bool Relocator::RelocateBySymbol(const char* symbol, uintptr_t patchAddr)
112 {
113     if (!HasSymStrTable()) {
114         return false;
115     }
116     auto symId = GetSymbol(symbol);
117     if (!symId.has_value()) {
118         LOG_COMPILER(DEBUG) << " don't find symbol:" << symbol << " in symbol table.";
119         return false;
120     }
121     bool ret = RelocateBySymbolId(symId.value(), patchAddr);
122     return ret;
123 }
124 
DumpRelocateText()125 void Relocator::DumpRelocateText()
126 {
127     if (!HasRelocateText()) {
128         LOG_COMPILER(ERROR) << " input valid relocateText addr & size:";
129         return;
130     }
131     ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
132     ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
133     size_t n  = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
134     Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
135     static constexpr int leftAdjustment = 12;
136     LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
137                    << std::left << std::setw(leftAdjustment) << "Info(0x): "
138                    << std::left << std::setw(leftAdjustment) << "Type: "
139                    << std::left << std::setw(leftAdjustment) << "r_offset(0x): "
140                    << std::left << std::setw(leftAdjustment) << "addend: ";
141     for (size_t i = 0; i < n; i++) {
142         Elf64_Rela *cur = ptr + i;
143         Elf64_Word id = GetSymbol(cur);
144         Elf64_Word type = GetType(cur);
145         Elf64_Sxword addend = ptr->r_addend;
146         LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << id
147                 << std::left << std::setw(leftAdjustment) << std::hex << cur->r_info
148                 << std::left << std::setw(leftAdjustment) << std::dec << type
149                 << std::left << std::setw(leftAdjustment) << std::hex << static_cast<intptr_t>(cur->r_offset)
150                 << std::left << std::setw(leftAdjustment) << std::dec << static_cast<intptr_t>(addend);
151     }
152     if (!HasSymStrTable()) {
153         return;
154     }
155     ASSERT(symAndStrTabInfo_.symSize_ % sizeof(Elf64_Sym) == 0);
156     n = symAndStrTabInfo_.symSize_ / sizeof(Elf64_Sym);
157     ASSERT(symAndStrTabInfo_.symAddr_ > 0 && symAndStrTabInfo_.symSize_ > 0);
158     Elf64_Sym *symPtr = reinterpret_cast<Elf64_Sym *>(symAndStrTabInfo_.symAddr_);
159     LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
160                 << std::left << std::setw(leftAdjustment) << "binding: "
161                 << std::left << std::setw(leftAdjustment) << "Type: "
162                 << std::left << std::setw(leftAdjustment) << "st_name: "
163                 << std::left << std::setw(leftAdjustment) << "name: ";
164     for (size_t i = 0; i < n; i++) {
165         Elf64_Sym *cur = symPtr + i;
166         const char *name = reinterpret_cast<char *>(symAndStrTabInfo_.strAddr_) + cur->st_name;
167         unsigned char binding = GetBinding(cur);
168         unsigned char type = GetType(cur);
169         LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << i
170             << std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(binding)
171             << std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(type)
172             << std::left << std::setw(leftAdjustment) << std::dec << cur->st_name
173             << std::left << std::setw(leftAdjustment) << name;
174     }
175 }
176 
BlInRange(intptr_t imm)177 bool Relocator::BlInRange(intptr_t imm)
178 {
179     return -(1 << 27) <= imm && imm < (1 << 27);
180 }
181 } // namespace panda::ecmascript
182 #endif
183