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