diff --git a/compiler-rt/lib/orc/macho_ehframe_registration.cpp b/compiler-rt/lib/orc/macho_ehframe_registration.cpp new file mode 100644 index 000000000000..d0ea7e70201c --- /dev/null +++ b/compiler-rt/lib/orc/macho_ehframe_registration.cpp @@ -0,0 +1,68 @@ +//===- ehframe_registration.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains code required to load the rest of the MachO runtime. +// +//===----------------------------------------------------------------------===// + +#include "adt.h" +#include "c_api.h" +#include "common.h" + +using namespace __orc_rt; + +// eh-frame registration functions. +// We expect these to be available for all processes. +extern "C" void __register_frame(const void *); +extern "C" void __deregister_frame(const void *); + +namespace { + +template +void walkEHFrameSection(span EHFrameSection, + HandleFDEFn HandleFDE) { + const char *CurCFIRecord = EHFrameSection.data(); + uint64_t Size = *reinterpret_cast(CurCFIRecord); + + while (CurCFIRecord != EHFrameSection.end() && Size != 0) { + const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); + if (Size == 0xffffffff) + Size = *reinterpret_cast(CurCFIRecord + 4) + 12; + else + Size += 4; + uint32_t Offset = *reinterpret_cast(OffsetField); + + if (Offset != 0) + HandleFDE(CurCFIRecord); + + CurCFIRecord += Size; + Size = *reinterpret_cast(CurCFIRecord); + } +} + +} // end anonymous namespace + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_register_ehframe_section(char *ArgData, size_t ArgSize) { + // NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer + // is taken to be the range of the eh-frame section. + bool HasError = false; + walkEHFrameSection(span(ArgData, ArgSize), __register_frame); + return __orc_rt_CreateCWrapperFunctionResultFromRange((char*)&HasError, + sizeof(HasError)); +} + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_deregister_ehframe_section(char *ArgData, size_t ArgSize) { + // NOTE: Does not use SPS to deserialize arg buffer, instead the arg buffer + // is taken to be the range of the eh-frame section. + bool HasError = false; + walkEHFrameSection(span(ArgData, ArgSize), __deregister_frame); + return __orc_rt_CreateCWrapperFunctionResultFromRange((char*)&HasError, + sizeof(HasError)); +}