1 //===- ehframe_registration.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code required to load the rest of the MachO runtime.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "adt.h"
14 #include "common.h"
15 #include "executor_address.h"
16 #include "orc/c_api.h"
17 #include "wrapper_function_utils.h"
18 
19 using namespace __orc_rt;
20 
21 // eh-frame registration functions.
22 // We expect these to be available for all processes.
23 extern "C" void __register_frame(const void *);
24 extern "C" void __deregister_frame(const void *);
25 
26 namespace {
27 
28 template <typename HandleFDEFn>
walkEHFrameSection(span<const char> EHFrameSection,HandleFDEFn HandleFDE)29 void walkEHFrameSection(span<const char> EHFrameSection,
30                         HandleFDEFn HandleFDE) {
31   const char *CurCFIRecord = EHFrameSection.data();
32   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
33 
34   while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
35     const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
36     if (Size == 0xffffffff)
37       Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
38     else
39       Size += 4;
40     uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
41 
42     if (Offset != 0)
43       HandleFDE(CurCFIRecord);
44 
45     CurCFIRecord += Size;
46     Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
47   }
48 }
49 
50 } // end anonymous namespace
51 
52 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_register_ehframe_section(char * ArgData,size_t ArgSize)53 __orc_rt_macho_register_ehframe_section(char *ArgData, size_t ArgSize) {
54   return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
55              ArgData, ArgSize,
56              [](ExecutorAddrRange FrameSection) -> Error {
57                walkEHFrameSection(FrameSection.toSpan<const char>(),
58                                   __register_frame);
59                return Error::success();
60              })
61       .release();
62 }
63 
64 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
__orc_rt_macho_deregister_ehframe_section(char * ArgData,size_t ArgSize)65 __orc_rt_macho_deregister_ehframe_section(char *ArgData, size_t ArgSize) {
66   return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
67              ArgData, ArgSize,
68              [](ExecutorAddrRange FrameSection) -> Error {
69                walkEHFrameSection(FrameSection.toSpan<const char>(),
70                                   __deregister_frame);
71                return Error::success();
72              })
73       .release();
74 }
75