• 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             ASSERT(-(1 << 27) <= imm && imm < (1 << 27));  // 27: "Check that -2^27 <= result < 2^27".
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             break;
59         }
60         case R_X86_64_PLT32: {
61             /* S + A - P
62             S: (when used on its own) is the address of the symbol
63             A: is the addend for the relocation
64             P: is the address of the place beging relocated(derived from r_offset)
65             */
66             intptr_t v = patchAddr + addend - symbolAddr;
67             ASSERT((v >= INT_MIN) && (v <= INT_MAX));
68             *(reinterpret_cast<uint32_t *>(symbolAddr)) = v;
69             ret = true;
70             break;
71         }
72         default: {
73             LOG_COMPILER(FATAL) << " unsupported type:" << type;
74             return false;
75         }
76     }
77     return ret;
78 }
79 
HasSymStrTable() const80 bool Relocator::HasSymStrTable() const
81 {
82     return (symAndStrTabInfo_.symAddr_ >= 0) && (symAndStrTabInfo_.symSize_ >= 0)
83         && (symAndStrTabInfo_.strAddr_ >= 0) && (symAndStrTabInfo_.strSize_ >= 0);
84 }
85 
HasRelocateText() const86 bool Relocator::HasRelocateText() const
87 {
88     return (relocateTextInfo_.relaTextAddr_ > 0) && (relocateTextInfo_.relaTextSize_ > 0);
89 }
90 
RelocateBySymbolId(Elf64_Word symbolId,uintptr_t patchAddr)91 bool Relocator::RelocateBySymbolId(Elf64_Word symbolId, uintptr_t patchAddr)
92 {
93     bool ret = false;
94     ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
95     ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
96     size_t n  = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
97     Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
98     for (size_t i = 0; i < n; i++) {
99         Elf64_Rela *cur = ptr + i;
100         Elf64_Word id = GetSymbol(cur);
101         intptr_t symbolAddr = relocateTextInfo_.textAddr_ + static_cast<uintptr_t>(cur->r_offset);
102         if (id == symbolId) {
103             ret = Relocate(cur, symbolAddr, patchAddr);
104         }
105     }
106     return ret;
107 }
108 
RelocateBySymbol(const char * symbol,uintptr_t patchAddr)109 bool Relocator::RelocateBySymbol(const char* symbol, uintptr_t patchAddr)
110 {
111     if (!HasSymStrTable()) {
112         return false;
113     }
114     auto symId = GetSymbol(symbol);
115     if (!symId.has_value()) {
116         LOG_COMPILER(DEBUG) << " don't find symbol:" << symbol << " in symbol table.";
117         return false;
118     }
119     bool ret = RelocateBySymbolId(symId.value(), patchAddr);
120     return ret;
121 }
122 
DumpRelocateText()123 void Relocator::DumpRelocateText()
124 {
125     if (!HasRelocateText()) {
126         LOG_COMPILER(ERROR) << " input valid relocateText addr & size:";
127         return;
128     }
129     ASSERT(relocateTextInfo_.relaTextSize_ % sizeof(Elf64_Rela) == 0);
130     ASSERT(relocateTextInfo_.relaTextAddr_ > 0 && relocateTextInfo_.relaTextSize_ > 0);
131     size_t n  = relocateTextInfo_.relaTextSize_ / sizeof(Elf64_Rela);
132     Elf64_Rela *ptr = reinterpret_cast<Elf64_Rela *>(relocateTextInfo_.relaTextAddr_);
133     static constexpr int leftAdjustment = 12;
134     LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
135                    << std::left << std::setw(leftAdjustment) << "Info(0x): "
136                    << std::left << std::setw(leftAdjustment) << "Type: "
137                    << std::left << std::setw(leftAdjustment) << "r_offset(0x): "
138                    << std::left << std::setw(leftAdjustment) << "addend: ";
139     for (size_t i = 0; i < n; i++) {
140         Elf64_Rela *cur = ptr + i;
141         Elf64_Word id = GetSymbol(cur);
142         Elf64_Word type = GetType(cur);
143         Elf64_Sxword addend = ptr->r_addend;
144         LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << id
145                 << std::left << std::setw(leftAdjustment) << std::hex << cur->r_info
146                 << std::left << std::setw(leftAdjustment) << std::dec << type
147                 << std::left << std::setw(leftAdjustment) << std::hex << static_cast<intptr_t>(cur->r_offset)
148                 << std::left << std::setw(leftAdjustment) << std::dec << static_cast<intptr_t>(addend);
149     }
150     if (!HasSymStrTable()) {
151         return;
152     }
153     ASSERT(symAndStrTabInfo_.symSize_ % sizeof(Elf64_Sym) == 0);
154     n = symAndStrTabInfo_.symSize_ / sizeof(Elf64_Sym);
155     ASSERT(symAndStrTabInfo_.symAddr_ > 0 && symAndStrTabInfo_.symSize_ > 0);
156     Elf64_Sym *symPtr = reinterpret_cast<Elf64_Sym *>(symAndStrTabInfo_.symAddr_);
157     LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << "symbolId "
158                 << std::left << std::setw(leftAdjustment) << "binding: "
159                 << std::left << std::setw(leftAdjustment) << "Type: "
160                 << std::left << std::setw(leftAdjustment) << "st_name: "
161                 << std::left << std::setw(leftAdjustment) << "name: ";
162     for (size_t i = 0; i < n; i++) {
163         Elf64_Sym *cur = symPtr + i;
164         const char *name = reinterpret_cast<char *>(symAndStrTabInfo_.strAddr_) + cur->st_name;
165         unsigned char binding = GetBinding(cur);
166         unsigned char type = GetType(cur);
167         LOG_COMPILER(DEBUG) << std::left << std::setw(leftAdjustment) << i
168             << std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(binding)
169             << std::left << std::setw(leftAdjustment) << std::dec << static_cast<int>(type)
170             << std::left << std::setw(leftAdjustment) << std::dec << cur->st_name
171             << std::left << std::setw(leftAdjustment) << name;
172     }
173 }
174 } // namespace panda::ecmascript
175 #endif