• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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/compiler/aot_file/gdb_jit.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "ecmascript/log_wrapper.h"
19 
20 #include <securec.h>
21 #include <mutex>
22 
23 #ifndef PANDA_TARGET_MACOS
24 // Keep in sync with gdb/gdb/jit.h
25 extern "C" {
26 typedef enum {
27     JIT_NOACTION = 0,
28     JIT_REGISTER_FN,
29     JIT_UNREGISTER_FN
30 } jit_actions_t;
31 
32 struct jit_code_entry {
33     struct jit_code_entry *next_entry;
34     struct jit_code_entry *prev_entry;
35     const char *symfile_addr;
36     uint64_t symfile_size;
37     const char *file_addr; // extend the standard
38 };
39 
40 struct jit_descriptor {
41     uint32_t version;
42     // This should be jit_actions_t, but we want to be specific about the
43     // bit-width.
44     uint32_t action_flag;
45     struct jit_code_entry *relevant_entry;
46     struct jit_code_entry *first_entry;
47 };
48 
49 // We put information about the JITed function in this global, which the
50 // debugger reads.  Make sure to specify the version statically, because the
51 // debugger checks the version before we can set it during runtime.
52 struct jit_descriptor __jit_debug_descriptor = {
53     1, JIT_NOACTION, nullptr, nullptr
54 };
55 
56 // Debuggers puts a breakpoint in this function.
__jit_debug_register_code()57 void __attribute__((noinline)) __jit_debug_register_code()
58 {
59     LOG_COMPILER(INFO) << "__jit_debug_register_code() is called.";
60 }
61 }
62 
63 std::mutex g_descMutex;
64 
65 namespace panda::ecmascript {
66 namespace jit_debug {
67 using namespace llvm::ELF;
68 
69 static bool RegisterStubAnToDebuggerImpl(const char *fileAddr);
70 
RegisterStubAnToDebugger(const char * fileAddr)71 void RegisterStubAnToDebugger(const char *fileAddr)
72 {
73     std::lock_guard<std::mutex> guard(g_descMutex);
74     auto entry = __jit_debug_descriptor.first_entry;
75     while (entry != nullptr && entry->file_addr != fileAddr) {
76         entry = entry->next_entry;
77     }
78     if (entry != nullptr) {
79         return;
80     }
81     if (RegisterStubAnToDebuggerImpl(fileAddr)) {
82         LOG_COMPILER(INFO) << "success to register stub.an to debugger.";
83     } else {
84         LOG_COMPILER(ERROR) << "Can't register stub.an to debugger.";
85     }
86 }
87 
UnregisterStubAnFromDebugger(const char * fileAddr)88 void UnregisterStubAnFromDebugger(const char *fileAddr)
89 {
90     std::lock_guard<std::mutex> guard(g_descMutex);
91     auto entry = __jit_debug_descriptor.first_entry;
92     while (entry != nullptr && entry->file_addr != fileAddr) {
93         entry = entry->next_entry;
94     }
95     if (entry == nullptr) {
96         return;
97     }
98     if (entry->prev_entry != nullptr) {
99         entry->prev_entry->next_entry = entry->next_entry;
100     }
101     if (entry->next_entry != nullptr) {
102         entry->next_entry->prev_entry = entry->prev_entry;
103     }
104     __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
105     __jit_debug_descriptor.relevant_entry = entry;
106     __jit_debug_register_code();
107     __jit_debug_descriptor.relevant_entry = nullptr;
108     delete entry->symfile_addr;
109     delete entry;
110 }
111 
112 template<typename T, typename U>
OffsetAlignUp(U * addr,uint64_t offset,uint32_t align)113 inline T OffsetAlignUp(U *addr, uint64_t offset, uint32_t align)
114 {
115     auto value = reinterpret_cast<uint64_t>(addr) + offset;
116     auto result = value;
117     if (align != 0 && (value % align != 0)) {
118         result = value + (align - (value % align));
119     }
120     return reinterpret_cast<T>(result);
121 }
122 
123 struct StubAnInfo {
124     uintptr_t fileAddr;
125     Elf64_Ehdr *ehdr;
126     Elf64_Shdr *shdrTab;
127     uint32_t shStrIdx;
128     Elf64_Shdr *shStrHdr;
129     Elf64_Shdr *textHdr;
130     Elf64_Shdr *asmstubHdr;
131     Elf64_Shdr *symtabHdr;
132     Elf64_Shdr *strtabHdr;
133     uint64_t bcStubBegin;
134     uint64_t bcStubEnd;
135     uint32_t symCnt;
136 };
137 
138 /*
139  * [0] file header
140  * [1] program header
141  * [2] shstrtab
142  * [3] strtab
143  * [4] symtab
144  * [5] .eh_frame
145  * [6] empty header
146  * [7] shstrtab-header
147  * [8] strtab-header
148  * [9] symtab-header
149  * [10] text-header
150  * [11] .eh_frame header
151  */
152 const char SHSTR[] = "\0.shstrtab\0.strtab\0.symtab\0.text\0.eh_frame";
153 const uint32_t SHSTRTAB_NAME = 1;
154 const uint32_t STRTAB_NAME = SHSTRTAB_NAME + strlen(".shstrtab") + 1;
155 const uint32_t SYMTAB_NAME = STRTAB_NAME + strlen(".strtab") + 1;
156 const uint32_t TEXT_NAME = SYMTAB_NAME + strlen(".symtab") + 1;
157 const uint32_t EH_FRAME_NAME = TEXT_NAME + strlen(".text") + 1;
158 
159 const uint32_t SHSTRTAB_HDR_IDX = 1;
160 const uint32_t STRTAB_HDR_IDX = 2;
161 const uint32_t SYMTAB_HDR_IDX = 3;
162 const uint32_t TEXT_HDR_IDX = 4;
163 
164 const uint32_t HEADER_CNT = 6;
165 
InfoGetBind(unsigned char info)166 inline int InfoGetBind(unsigned char info)
167 {
168     const uint32_t shift = 4;
169     return info >> shift;
170 }
171 
CollectStubAnInfo(uintptr_t fileAddr)172 StubAnInfo CollectStubAnInfo(uintptr_t fileAddr)
173 {
174     auto *ehdr = reinterpret_cast<Elf64_Ehdr *>(fileAddr);
175     auto *shdrTab = reinterpret_cast<Elf64_Shdr *>(fileAddr + ehdr->e_shoff);
176     uint32_t shStrIdx = ehdr->e_shstrndx;
177     Elf64_Shdr *shStrHdr = &shdrTab[shStrIdx];
178     const char *shstrtab = reinterpret_cast<const char *>(fileAddr + shStrHdr->sh_offset);
179     Elf64_Shdr *textHdr = nullptr;
180     Elf64_Shdr *asmstubHdr = nullptr;
181     Elf64_Shdr *symtabHdr = nullptr;
182     Elf64_Shdr *strtabHdr = nullptr;
183     for (uint32_t i = 0; i < ehdr->e_shnum; i++) {
184         Elf64_Shdr *shdr = &shdrTab[i];
185         const char *name = &shstrtab[shdr->sh_name];
186         if (strcmp(name, ".text") == 0) {
187             textHdr = shdr;
188         } else if (strcmp(name, ".ark_asmstub") == 0) {
189             asmstubHdr = shdr;
190         } else if (strcmp(name, ".symtab") == 0) {
191             symtabHdr = shdr;
192         } else if (strcmp(name, ".strtab") == 0) {
193             strtabHdr = shdr;
194         }
195     }
196     ASSERT(symtabHdr != nullptr);
197     Elf64_Sym *symtab = reinterpret_cast<Elf64_Sym *>(fileAddr + symtabHdr->sh_offset);
198     const char *strtab = reinterpret_cast<const char *>(fileAddr + strtabHdr->sh_offset);
199     uint32_t symCnt = 2;
200     uint64_t bcStubBegin = UINT64_MAX;
201     uint64_t bcStubEnd = 0;
202     for (uint32_t symIdx = 0; symIdx < symtabHdr->sh_size / symtabHdr->sh_entsize; symIdx++) {
203         Elf64_Sym *sym = symtab + symIdx;
204         if (InfoGetBind(sym->st_info) != STB_GLOBAL) {
205             continue;
206         }
207         if (strncmp(&strtab[sym->st_name], "BCStub", strlen("BCStub")) != 0) {
208             symCnt++;
209         } else {
210             if (sym->st_value < bcStubBegin) {
211                 bcStubBegin = sym->st_value;
212             }
213             if (sym->st_value + sym->st_size > bcStubEnd) {
214                 bcStubEnd = sym->st_value + sym->st_size;
215             }
216         }
217     }
218     return StubAnInfo {
219         fileAddr, ehdr, shdrTab, shStrIdx, shStrHdr, textHdr, asmstubHdr, symtabHdr, strtabHdr,
220         bcStubBegin, bcStubEnd, symCnt
221     };
222 }
223 
CopyStrTab(uintptr_t baseAddr,const StubAnInfo & info)224 bool CopyStrTab(uintptr_t baseAddr, const StubAnInfo &info)
225 {
226     Elf64_Ehdr *newEhdr = reinterpret_cast<Elf64_Ehdr *>(baseAddr);
227     Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
228     char *shStrBuff = reinterpret_cast<char *>(newPhdr + 1);
229     if (memcpy_s(shStrBuff, sizeof(SHSTR), SHSTR, sizeof(SHSTR)) != EOK) {
230         return false;
231     }
232     char *newStrtab = shStrBuff + sizeof(SHSTR);
233     if (memcpy_s(newStrtab, info.strtabHdr->sh_size,
234         reinterpret_cast<void *>(info.fileAddr + info.strtabHdr->sh_offset), info.strtabHdr->sh_size) != EOK) {
235         return false;
236     }
237     const char bcStubName[] = "BCStubInterpreterRoutine";
238     if (memcpy_s((newStrtab + 1), sizeof(bcStubName), bcStubName, sizeof(bcStubName)) != EOK) {
239         return false;
240     }
241     return true;
242 }
243 
ConstructSymTab(Elf64_Sym * newSymtab,const StubAnInfo & info)244 void ConstructSymTab(Elf64_Sym *newSymtab, const StubAnInfo &info)
245 {
246     Elf64_Sym *symtab = reinterpret_cast<Elf64_Sym *>(info.fileAddr + info.symtabHdr->sh_offset);
247     const char *strtab = reinterpret_cast<const char *>(info.fileAddr + info.strtabHdr->sh_offset);
248     memset_s(newSymtab, sizeof(Elf64_Sym), 0, sizeof(Elf64_Sym));
249     uint32_t newSymIdx = 1;
250     for (uint32_t symIdx = 0; symIdx < info.symtabHdr->sh_size / info.symtabHdr->sh_entsize; symIdx++) {
251         Elf64_Sym *src = symtab + symIdx;
252         if (InfoGetBind(src->st_info) == STB_GLOBAL
253             && strncmp(&strtab[src->st_name], "BCStub", strlen("BCStub")) != 0) {
254             auto dst = newSymtab + newSymIdx;
255             newSymIdx++;
256             *dst = *src;
257             dst->st_shndx = TEXT_HDR_IDX;
258             dst->st_value -= info.textHdr->sh_offset;
259         }
260     }
261     auto bcSym = newSymtab + newSymIdx;
262     bcSym->st_name = 1;
263     bcSym->st_info = newSymtab[1].st_info;
264     bcSym->st_other = newSymtab[1].st_other;
265     bcSym->st_shndx = TEXT_HDR_IDX;
266     bcSym->st_value = info.bcStubBegin - info.textHdr->sh_offset;
267     ASSERT(info.bcStubEnd >= info.bcStubBegin);
268     bcSym->st_size = info.bcStubEnd - info.bcStubBegin;
269 }
270 
ConstructEhdrAndPhdr(Elf64_Ehdr * newEhdr,Elf64_Shdr * newShdrtab,uintptr_t baseAddr,const StubAnInfo & info)271 void ConstructEhdrAndPhdr(Elf64_Ehdr *newEhdr, Elf64_Shdr *newShdrtab, uintptr_t baseAddr, const StubAnInfo &info)
272 {
273     Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
274     {
275         *newEhdr = *info.ehdr;
276         newEhdr->e_flags = info.ehdr->e_flags;
277         newEhdr->e_machine = info.ehdr->e_machine;
278         if (memcpy_s(newEhdr->e_ident, sizeof(info.ehdr->e_ident),
279                      info.ehdr->e_ident, sizeof(info.ehdr->e_ident)) != EOK) {
280             return;
281         }
282         newEhdr->e_version = 1;
283         newEhdr->e_phoff = sizeof(Elf64_Ehdr);
284         newEhdr->e_shoff = reinterpret_cast<uintptr_t>(newShdrtab) - baseAddr;
285         newEhdr->e_ehsize = sizeof(Elf64_Ehdr);
286         newEhdr->e_phentsize = sizeof(Elf64_Phdr);
287         newEhdr->e_phnum = 1;
288         newEhdr->e_shentsize = sizeof(Elf64_Shdr);
289         newEhdr->e_shnum = HEADER_CNT;
290         newEhdr->e_shstrndx = SHSTRTAB_HDR_IDX;
291         newEhdr->e_type = ET_REL;
292         newEhdr->e_entry = 0;
293     }
294     uintptr_t textAddr = info.textHdr->sh_offset + info.fileAddr;
295     uint64_t textSize = info.asmstubHdr->sh_offset + info.asmstubHdr->sh_size - info.textHdr->sh_offset;
296     {
297         newPhdr->p_type = PT_LOAD;
298         newPhdr->p_flags = PF_X | PF_R;
299         newPhdr->p_offset = textAddr - info.fileAddr;
300         newPhdr->p_vaddr = textAddr;
301         newPhdr->p_paddr = textAddr;
302         newPhdr->p_filesz = textSize;
303         newPhdr->p_memsz = textSize;
304         newPhdr->p_align = 0x1000;
305     }
306 }
307 
ConstructShdrTab(Elf64_Shdr * newShdrTab,Elf64_Sym * newSymtab,uintptr_t baseAddr,void * ehFrame,uint32_t ehFrameSize,const StubAnInfo & info)308 void ConstructShdrTab(Elf64_Shdr *newShdrTab, Elf64_Sym *newSymtab, uintptr_t baseAddr, void *ehFrame,
309                       uint32_t ehFrameSize, const StubAnInfo &info)
310 {
311     Elf64_Shdr hdr{};
312     Elf64_Shdr *emptyShdr = newShdrTab;
313     Elf64_Shdr *newShstrHdr = emptyShdr + 1;
314     Elf64_Shdr *newStrtabHdr = newShstrHdr + 1;
315     Elf64_Shdr *newSymHdr = newStrtabHdr + 1;
316     Elf64_Shdr *newTextHdr = newSymHdr + 1;
317     Elf64_Shdr *ehFrameHdr = newTextHdr + 1;
318     *emptyShdr = hdr;
319 
320     newShstrHdr->sh_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr);
321     newShstrHdr->sh_size = sizeof(SHSTR);
322     newShstrHdr->sh_name = SHSTRTAB_NAME;
323     newShstrHdr->sh_addr = newStrtabHdr->sh_offset + baseAddr;
324     newShstrHdr->sh_type = SHT_STRTAB;
325     newShstrHdr->sh_flags = SHF_ALLOC;
326 
327     newStrtabHdr->sh_offset = newShstrHdr->sh_offset + newShstrHdr->sh_size;
328     newStrtabHdr->sh_size = info.strtabHdr->sh_size;
329     newStrtabHdr->sh_name = STRTAB_NAME;
330     newStrtabHdr->sh_addr = newStrtabHdr->sh_offset + baseAddr;
331     newStrtabHdr->sh_addralign = 1;
332     newStrtabHdr->sh_type = SHT_STRTAB;
333     newStrtabHdr->sh_flags = SHF_ALLOC;
334     newStrtabHdr->sh_link = SHSTRTAB_HDR_IDX;
335 
336     *newSymHdr = *info.symtabHdr;
337     newSymHdr->sh_offset = reinterpret_cast<uintptr_t>(newSymtab) - baseAddr;
338     newSymHdr->sh_size = info.symCnt * info.symtabHdr->sh_entsize;
339     newSymHdr->sh_entsize = info.symtabHdr->sh_entsize;
340     newSymHdr->sh_addralign = info.symtabHdr->sh_addralign;
341     newSymHdr->sh_name = SYMTAB_NAME;
342     newSymHdr->sh_addr = reinterpret_cast<uintptr_t>(newSymtab);
343     newSymHdr->sh_link = STRTAB_HDR_IDX;
344 
345     newTextHdr->sh_offset = 0;
346     newTextHdr->sh_size = info.asmstubHdr->sh_offset + info.asmstubHdr->sh_size - info.textHdr->sh_offset;
347     newTextHdr->sh_name = TEXT_NAME;
348     newTextHdr->sh_addr = info.fileAddr + info.textHdr->sh_offset;
349     newTextHdr->sh_addralign = sizeof(uint32_t);
350     newTextHdr->sh_type = SHT_NOBITS;
351     newTextHdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
352     newTextHdr->sh_link = SYMTAB_HDR_IDX;
353 
354     ehFrameHdr->sh_offset = reinterpret_cast<uintptr_t>(ehFrame) - baseAddr;
355     ehFrameHdr->sh_size = ehFrameSize;
356     ehFrameHdr->sh_name = EH_FRAME_NAME;
357     ehFrameHdr->sh_addr = reinterpret_cast<uintptr_t>(ehFrame);
358     ehFrameHdr->sh_addralign = sizeof(uintptr_t);
359     ehFrameHdr->sh_type = SHT_PROGBITS;
360     ehFrameHdr->sh_flags = SHF_ALLOC;
361     ehFrameHdr->sh_link = TEXT_HDR_IDX;
362 }
363 
CreateDebuggerElf(uintptr_t fileAddr,void ** result,uint64_t * elfSize)364 bool CreateDebuggerElf(uintptr_t fileAddr, void **result, uint64_t *elfSize)
365 {
366     auto info = CollectStubAnInfo(fileAddr);
367     std::vector<uint8_t> ehFrame {
368             0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x4, 0x78, 0x1e, 0x0, 0x0, 0x0,
369             0x0, 0x0, 0x0, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x73, 0xab,
370             0xff, 0xff, 0x0, 0x0, 0x30, 0x2c, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1d, 0x0, 0x10,
371             0x1e, 0x17, 0x8d, 0x0, 0x12, 0x8, 0x18, 0x1c, 0x6, 0x8, 0x0, 0x29, 0x28, 0x7, 0x0, 0x8,
372             0x10, 0x1c, 0x6, 0x2f, 0xee, 0xff, 0x8, 0x8, 0x22, 0x10, 0x1d, 0x17, 0x8d, 0x0, 0x12, 0x8,
373             0x18, 0x1c, 0x6, 0x8, 0x0, 0x29, 0x28, 0x7, 0x0, 0x8, 0x10, 0x1c, 0x6, 0x2f, 0xee, 0xff,
374             0x8, 0x0, 0x22,
375     };
376     const uint32_t addrOff = 28;
377     const uint32_t lenOff = 36;
378     auto writeU64 = [&ehFrame](uint32_t idx, uint64_t data) {
379         for (uint32_t i = 0; i < sizeof(uint64_t); i++) {
380             ehFrame[idx + i] = (data >> (8 * i)) & 0xff;
381         }
382     };
383     writeU64(addrOff, info.bcStubBegin + fileAddr);
384     ASSERT(info.bcStubEnd >= info.bcStubBegin);
385     writeU64(lenOff, info.bcStubEnd - info.bcStubBegin);
386 
387     uint32_t totalSize = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) + sizeof(SHSTR) + info.strtabHdr->sh_size;
388     totalSize += info.symtabHdr->sh_entsize * info.symCnt + sizeof(Elf64_Sym); // for align
389     totalSize += ehFrame.size() + sizeof(uintptr_t);
390     totalSize += sizeof(Elf64_Shdr) * HEADER_CNT + sizeof(Elf64_Shdr); // for align
391 
392     char *buffer = new char[totalSize];
393     Elf64_Ehdr *newEhdr = reinterpret_cast<Elf64_Ehdr *>(buffer);
394     Elf64_Phdr *newPhdr = reinterpret_cast<Elf64_Phdr *>(newEhdr + 1);
395     const char *shStrBuff = reinterpret_cast<const char *>(newPhdr + 1);
396     const char *newStrtab = shStrBuff + sizeof(SHSTR);
397     if (!CopyStrTab(reinterpret_cast<uintptr_t>(buffer), info)) {
398         delete[] buffer;
399         return false;
400     }
401 
402     auto newSymtab = OffsetAlignUp<Elf64_Sym *>(newStrtab, info.strtabHdr->sh_size, info.symtabHdr->sh_addralign);
403     ConstructSymTab(newSymtab, info);
404 
405     auto ehFrameBuffer = OffsetAlignUp<char *>(newSymtab, info.symtabHdr->sh_entsize * info.symCnt, sizeof(uintptr_t));
406     if (memcpy_s(ehFrameBuffer, ehFrame.size(), ehFrame.data(), ehFrame.size()) != EOK) {
407         delete[] buffer;
408         return false;
409     }
410 
411     auto newShdrtab = OffsetAlignUp<Elf64_Shdr *>(ehFrameBuffer, ehFrame.size(), sizeof(uintptr_t));
412     ConstructEhdrAndPhdr(newEhdr, newShdrtab, reinterpret_cast<uintptr_t>(buffer), info);
413     ConstructShdrTab(newShdrtab, newSymtab, reinterpret_cast<uintptr_t>(buffer), ehFrameBuffer, ehFrame.size(), info);
414 
415     *result = reinterpret_cast<void *>(buffer);
416     *elfSize = totalSize;
417     return true;
418 }
419 
RegisterStubAnToDebuggerImpl(const char * fileAddr)420 static bool RegisterStubAnToDebuggerImpl(const char *fileAddr)
421 {
422     auto *entry = new jit_code_entry;
423     if (!CreateDebuggerElf(reinterpret_cast<uintptr_t>(fileAddr),
424         reinterpret_cast<void **>(const_cast<char **>(&entry->symfile_addr)), &entry->symfile_size)) {
425         delete entry;
426         return false;
427     }
428     entry->prev_entry = nullptr;
429     entry->file_addr = fileAddr;
430 
431     // Insert this entry at the head of the list.
432     jit_code_entry *nextEntry = __jit_debug_descriptor.first_entry;
433     entry->next_entry = nextEntry;
434     if (nextEntry) {
435         nextEntry->prev_entry = entry;
436     }
437 
438     __jit_debug_descriptor.first_entry = entry;
439     __jit_debug_descriptor.relevant_entry = entry;
440     __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
441     __jit_debug_register_code();
442     return true;
443 }
444 
445 }
446 }
447 #else
448 namespace panda::ecmascript {
449 namespace jit_debug {
RegisterStubAnToDebugger(const char * fileAddr)450 void RegisterStubAnToDebugger(const char *fileAddr)
451 {
452     LOG_COMPILER(INFO) << "MACOS doesn't support RegisterStubAnToDebugger, fileAddr is" << fileAddr;
453 }
454 
UnregisterStubAnFromDebugger(const char * fileAddr)455 void UnregisterStubAnFromDebugger(const char *fileAddr)
456 {
457     LOG_COMPILER(INFO) << "MACOS doesn't support RegisterStubAnToDebugger, fileAddr is" << fileAddr;
458 }
459 }
460 }
461 #endif
462