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 "c_api.h"
15 #include "common.h"
16 
17 using namespace __orc_rt;
18 
19 // eh-frame registration functions.
20 // We expect these to be available for all processes.
21 extern "C" void __register_frame(const void *);
22 extern "C" void __deregister_frame(const void *);
23 
24 namespace {
25 
26 template <typename HandleFDEFn>
27 void walkEHFrameSection(span<const char> EHFrameSection,
28                         HandleFDEFn HandleFDE) {
29   const char *CurCFIRecord = EHFrameSection.data();
30   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
31 
32   while (CurCFIRecord != EHFrameSection.end() && Size != 0) {
33     const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
34     if (Size == 0xffffffff)
35       Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
36     else
37       Size += 4;
38     uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
39 
40     if (Offset != 0)
41       HandleFDE(CurCFIRecord);
42 
43     CurCFIRecord += Size;
44     Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
45   }
46 }
47 
48 } // end anonymous namespace
49 
50 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
51 __orc_rt_macho_register_ehframe_section(char *ArgData, size_t ArgSize) {
52   // NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer
53   // is taken to be the range of the eh-frame section.
54   bool HasError = false;
55   walkEHFrameSection(span<const char>(ArgData, ArgSize), __register_frame);
56   return __orc_rt_CreateCWrapperFunctionResultFromRange((char*)&HasError,
57                                                         sizeof(HasError));
58 }
59 
60 ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
61 __orc_rt_macho_deregister_ehframe_section(char *ArgData, size_t ArgSize) {
62   // NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer
63   // is taken to be the range of the eh-frame section.
64   bool HasError = false;
65   walkEHFrameSection(span<const char>(ArgData, ArgSize), __deregister_frame);
66   return __orc_rt_CreateCWrapperFunctionResultFromRange((char*)&HasError,
67                                                         sizeof(HasError));
68 }
69