65 changes: 20 additions & 45 deletions llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
#include <optional>
Expand Down Expand Up @@ -246,25 +247,6 @@ class MachOPlatformCompleteBootstrapMaterializationUnit
ExecutorAddr MachOHeaderAddr;
};

StringRef DataCommonSectionName = "__DATA,__common";
StringRef DataDataSectionName = "__DATA,__data";
StringRef EHFrameSectionName = "__TEXT,__eh_frame";
StringRef CompactUnwindInfoSectionName = "__TEXT,__unwind_info";
StringRef ModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef ObjCClassListSectionName = "__DATA,__objc_classlist";
StringRef ObjCImageInfoSectionName = "__DATA,__objc_image_info";
StringRef ObjCSelRefsSectionName = "__DATA,__objc_selrefs";
StringRef Swift5ProtoSectionName = "__TEXT,__swift5_proto";
StringRef Swift5ProtosSectionName = "__TEXT,__swift5_protos";
StringRef Swift5TypesSectionName = "__TEXT,__swift5_types";
StringRef ThreadBSSSectionName = "__DATA,__thread_bss";
StringRef ThreadDataSectionName = "__DATA,__thread_data";
StringRef ThreadVarsSectionName = "__DATA,__thread_vars";

StringRef InitSectionNames[] = {
ModInitFuncSectionName, ObjCSelRefsSectionName, ObjCClassListSectionName,
Swift5ProtosSectionName, Swift5ProtoSectionName, Swift5TypesSectionName};

} // end anonymous namespace

namespace llvm {
Expand Down Expand Up @@ -398,15 +380,6 @@ MachOPlatform::standardRuntimeUtilityAliases() {
StandardRuntimeUtilityAliases);
}

bool MachOPlatform::isInitializerSection(StringRef SegName,
StringRef SectName) {
for (auto &Name : InitSectionNames) {
if (Name.startswith(SegName) && Name.substr(7) == SectName)
return true;
}
return false;
}

bool MachOPlatform::supportedTarget(const Triple &TT) {
switch (TT.getArch()) {
case Triple::aarch64:
Expand Down Expand Up @@ -902,7 +875,7 @@ Error MachOPlatform::MachOPlatformPlugin::preserveInitSections(
jitlink::LinkGraph &G, MaterializationResponsibility &MR) {

JITLinkSymbolSet InitSectionSymbols;
for (auto &InitSectionName : InitSectionNames) {
for (auto &InitSectionName : MachOInitSectionNames) {
// Skip non-init sections.
auto *InitSection = G.findSectionByName(InitSectionName);
if (!InitSection)
Expand Down Expand Up @@ -944,22 +917,22 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
// OR
// (2) We already have a recorded __objc_imageinfo for this JITDylib,
// in which case we just verify it.
auto *ObjCImageInfo = G.findSectionByName(ObjCImageInfoSectionName);
auto *ObjCImageInfo = G.findSectionByName(MachOObjCImageInfoSectionName);
if (!ObjCImageInfo)
return Error::success();

auto ObjCImageInfoBlocks = ObjCImageInfo->blocks();

// Check that the section is not empty if present.
if (ObjCImageInfoBlocks.empty())
return make_error<StringError>("Empty " + ObjCImageInfoSectionName +
return make_error<StringError>("Empty " + MachOObjCImageInfoSectionName +
" section in " + G.getName(),
inconvertibleErrorCode());

// Check that there's only one block in the section.
if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end())
return make_error<StringError>("Multiple blocks in " +
ObjCImageInfoSectionName +
MachOObjCImageInfoSectionName +
" section in " + G.getName(),
inconvertibleErrorCode());

Expand All @@ -971,7 +944,7 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
for (auto &E : B->edges())
if (E.getTarget().isDefined() &&
&E.getTarget().getBlock().getSection() == ObjCImageInfo)
return make_error<StringError>(ObjCImageInfoSectionName +
return make_error<StringError>(MachOObjCImageInfoSectionName +
" is referenced within file " +
G.getName(),
inconvertibleErrorCode());
Expand Down Expand Up @@ -1024,7 +997,7 @@ Error MachOPlatform::MachOPlatformPlugin::fixTLVSectionsAndEdges(
}

// Store key in __thread_vars struct fields.
if (auto *ThreadDataSec = G.findSectionByName(ThreadVarsSectionName)) {
if (auto *ThreadDataSec = G.findSectionByName(MachOThreadVarsSectionName)) {
std::optional<uint64_t> Key;
{
std::lock_guard<std::mutex> Lock(MP.PlatformMutex);
Expand Down Expand Up @@ -1098,10 +1071,11 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
}
};

if (Section *EHFrameSec = G.findSectionByName(EHFrameSectionName))
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);

if (Section *CUInfoSec = G.findSectionByName(CompactUnwindInfoSectionName))
if (Section *CUInfoSec =
G.findSectionByName(MachOCompactUnwindInfoSectionName))
ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);

// If we didn't find any pointed-to code-blocks then there's no need to
Expand Down Expand Up @@ -1150,10 +1124,10 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
// Get a pointer to the thread data section if there is one. It will be used
// below.
jitlink::Section *ThreadDataSection =
G.findSectionByName(ThreadDataSectionName);
G.findSectionByName(MachOThreadDataSectionName);

// Handle thread BSS section if there is one.
if (auto *ThreadBSSSection = G.findSectionByName(ThreadBSSSectionName)) {
if (auto *ThreadBSSSection = G.findSectionByName(MachOThreadBSSSectionName)) {
// If there's already a thread data section in this graph then merge the
// thread BSS section content into it, otherwise just treat the thread
// BSS section as the thread data section.
Expand All @@ -1166,8 +1140,9 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
SmallVector<std::pair<StringRef, ExecutorAddrRange>, 8> MachOPlatformSecs;

// Collect data sections to register.
StringRef DataSections[] = {DataDataSectionName, DataCommonSectionName,
EHFrameSectionName};
StringRef DataSections[] = {MachODataDataSectionName,
MachODataCommonSectionName,
MachOEHFrameSectionName};
for (auto &SecName : DataSections) {
if (auto *Sec = G.findSectionByName(SecName)) {
jitlink::SectionRange R(*Sec);
Expand All @@ -1181,16 +1156,16 @@ Error MachOPlatform::MachOPlatformPlugin::registerObjectPlatformSections(
if (ThreadDataSection) {
jitlink::SectionRange R(*ThreadDataSection);
if (!R.empty())
MachOPlatformSecs.push_back({ThreadDataSectionName, R.getRange()});
MachOPlatformSecs.push_back({MachOThreadDataSectionName, R.getRange()});
}

// If any platform sections were found then add an allocation action to call
// the registration function.
StringRef PlatformSections[] = {
ModInitFuncSectionName, ObjCClassListSectionName,
ObjCImageInfoSectionName, ObjCSelRefsSectionName,
Swift5ProtoSectionName, Swift5ProtosSectionName,
Swift5TypesSectionName,
MachOModInitFuncSectionName, MachOObjCClassListSectionName,
MachOObjCImageInfoSectionName, MachOObjCSelRefsSectionName,
MachOSwift5ProtoSectionName, MachOSwift5ProtosSectionName,
MachOSwift5TypesSectionName,
};

for (auto &SecName : PlatformSections) {
Expand Down
24 changes: 4 additions & 20 deletions llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
Expand Down Expand Up @@ -85,7 +86,7 @@ getMachOObjectFileSymbolInfo(ExecutionSession &ES,
}
auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl());
auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl()));
if (MachOPlatform::isInitializerSection(SegName, SecName)) {
if (isMachOInitializerSection(SegName, SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
Expand Down Expand Up @@ -138,7 +139,7 @@ getELFObjectFileSymbolInfo(ExecutionSession &ES,
SymbolStringPtr InitSymbol;
for (auto &Sec : Obj.sections()) {
if (auto SecName = Sec.getName()) {
if (ELFNixPlatform::isInitializerSection(*SecName)) {
if (isELFInitializerSection(*SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
Expand Down Expand Up @@ -219,7 +220,7 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
SymbolStringPtr InitSymbol;
for (auto &Sec : Obj.sections()) {
if (auto SecName = Sec.getName()) {
if (COFFPlatform::isInitializerSection(*SecName)) {
if (isCOFFInitializerSection(*SecName)) {
addInitSymbol(I, ES, Obj.getFileName());
break;
}
Expand Down Expand Up @@ -287,22 +288,5 @@ getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
return getGenericObjectFileSymbolInfo(ES, **Obj);
}

bool hasInitializerSection(jitlink::LinkGraph &G) {
bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
bool IsElf = G.getTargetTriple().isOSBinFormatELF();
if (!IsMachO && !IsElf)
return false;

for (auto &Sec : G.sections()) {
if (IsMachO && std::apply(MachOPlatform::isInitializerSection,
Sec.getName().split(",")))
return true;
if (IsElf && ELFNixPlatform::isInitializerSection(Sec.getName()))
return true;
}

return false;
}

} // End namespace orc.
} // End namespace llvm.
17 changes: 17 additions & 0 deletions llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "llvm/Support/MemoryBuffer.h"
#include <string>
#include <vector>
Expand All @@ -22,6 +23,22 @@ using namespace llvm::orc;

namespace {

bool hasInitializerSection(jitlink::LinkGraph &G) {
bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
bool IsElf = G.getTargetTriple().isOSBinFormatELF();
if (!IsMachO && !IsElf)
return false;

for (auto &Sec : G.sections()) {
if (IsMachO && isMachOInitializerSection(Sec.getName()))
return true;
if (IsElf && isELFInitializerSection(Sec.getName()))
return true;
}

return false;
}

JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
JITSymbolFlags Flags;

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ExecutionEngine/Orc/Shared/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_llvm_component_library(LLVMOrcShared
AllocationActions.cpp
ObjectFormats.cpp
OrcError.cpp
OrcRTBridge.cpp
SimpleRemoteEPCUtils.cpp
Expand Down
74 changes: 74 additions & 0 deletions llvm/lib/ExecutionEngine/Orc/Shared/ObjectFormats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===---------- ObjectFormats.cpp - Object format details for ORC ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// ORC-specific object format details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"

namespace llvm {
namespace orc {

StringRef MachODataCommonSectionName = "__DATA,__common";
StringRef MachODataDataSectionName = "__DATA,__data";
StringRef MachOEHFrameSectionName = "__TEXT,__eh_frame";
StringRef MachOCompactUnwindInfoSectionName = "__TEXT,__unwind_info";
StringRef MachOModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef MachOObjCClassListSectionName = "__DATA,__objc_classlist";
StringRef MachOObjCImageInfoSectionName = "__DATA,__objc_image_info";
StringRef MachOObjCSelRefsSectionName = "__DATA,__objc_selrefs";
StringRef MachOSwift5ProtoSectionName = "__TEXT,__swift5_proto";
StringRef MachOSwift5ProtosSectionName = "__TEXT,__swift5_protos";
StringRef MachOSwift5TypesSectionName = "__TEXT,__swift5_types";
StringRef MachOThreadBSSSectionName = "__DATA,__thread_bss";
StringRef MachOThreadDataSectionName = "__DATA,__thread_data";
StringRef MachOThreadVarsSectionName = "__DATA,__thread_vars";

StringRef MachOInitSectionNames[6] = {
MachOModInitFuncSectionName, MachOObjCSelRefsSectionName,
MachOObjCClassListSectionName, MachOSwift5ProtosSectionName,
MachOSwift5ProtoSectionName, MachOSwift5TypesSectionName};

StringRef ELFEHFrameSectionName = ".eh_frame";
StringRef ELFInitArrayFuncSectionName = ".init_array";

StringRef ELFThreadBSSSectionName = ".tbss";
StringRef ELFThreadDataSectionName = ".tdata";

bool isMachOInitializerSection(StringRef SegName, StringRef SecName) {
for (auto &InitSection : MachOInitSectionNames) {
// Loop below assumes all MachO init sectios have a length-6
// segment name.
assert(InitSection[6] == ',' && "Init section seg name has length != 6");
if (InitSection.starts_with(SegName) && InitSection.substr(7) == SecName)
return true;
}
return false;
}

bool isMachOInitializerSection(StringRef QualifiedName) {
for (auto &InitSection : MachOInitSectionNames)
if (InitSection == QualifiedName)
return true;
return false;
}

bool isELFInitializerSection(StringRef SecName) {
if (SecName.consume_front(ELFInitArrayFuncSectionName) &&
(SecName.empty() || SecName[0] == '.'))
return true;
return false;
}

bool isCOFFInitializerSection(StringRef SecName) {
return SecName.startswith(".CRT");
}

} // namespace orc
} // namespace llvm
3 changes: 0 additions & 3 deletions llvm/unittests/ExecutionEngine/JITLink/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
JITLink
Object
OrcJIT
OrcShared
OrcTargetProcess
RuntimeDyld
Support
TargetParser
)
Expand Down
66 changes: 23 additions & 43 deletions llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,47 +712,27 @@ TEST(LinkGraphTest, SplitBlock) {
}
}

struct InitSymbolsTestParams {
InitSymbolsTestParams(StringRef Triple, StringRef Section,
bool ExpectedHasInitializerSection)
: Triple(Triple), Section(Section),
ExpectedHasInitializerSection(ExpectedHasInitializerSection) {}

StringRef Triple;
StringRef Section;
bool ExpectedHasInitializerSection;
};

class InitSymbolsTestFixture
: public ::testing::TestWithParam<InitSymbolsTestParams> {};

TEST_P(InitSymbolsTestFixture, InitSymbolSections) {
InitSymbolsTestParams Params = GetParam();
auto Graph = std::make_unique<LinkGraph>(
"foo", Triple(Params.Triple), 8, support::little, getGenericEdgeKindName);
Graph->createSection(Params.Section,
orc::MemProt::Read | orc::MemProt::Write);
EXPECT_EQ(orc::hasInitializerSection(*Graph),
Params.ExpectedHasInitializerSection);
}
TEST(LinkGraphTest, IsCStringBlockTest) {
// Check that the LinkGraph::splitBlock test works as expected.
LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
getGenericEdgeKindName);
auto &Sec =
G.createSection("__data", orc::MemProt::Read | orc::MemProt::Write);

INSTANTIATE_TEST_SUITE_P(
InitSymbolsTests, InitSymbolsTestFixture,
::testing::Values(
InitSymbolsTestParams("x86_64-apple-darwin", "__DATA,__objc_selrefs",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__DATA,__mod_init_func",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__DATA,__objc_classlist",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__TEXT,__swift5_proto",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__TEXT,__swift5_protos",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__TEXT,__swift5_types",
true),
InitSymbolsTestParams("x86_64-apple-darwin", "__DATA,__not_an_init_sec",
false),
InitSymbolsTestParams("x86_64-unknown-linux", ".init_array", true),
InitSymbolsTestParams("x86_64-unknown-linux", ".init_array.0", true),
InitSymbolsTestParams("x86_64-unknown-linux", ".text", false)));
ArrayRef<char> CString = "hello, world!";
ArrayRef<char> NotACString = {0, 1, 0, 1, 0};

auto &CStringBlock =
G.createContentBlock(Sec, CString, orc::ExecutorAddr(), 1, 0);
auto &NotACStringBlock =
G.createContentBlock(Sec, NotACString, orc::ExecutorAddr(), 1, 0);
auto &SizeOneZeroFillBlock =
G.createZeroFillBlock(Sec, 1, orc::ExecutorAddr(), 1, 0);
auto &LargerZeroFillBlock =
G.createZeroFillBlock(Sec, 2, orc::ExecutorAddr(), 1, 0);

EXPECT_TRUE(isCStringBlock(CStringBlock));
EXPECT_FALSE(isCStringBlock(NotACStringBlock));
EXPECT_TRUE(isCStringBlock(SizeOneZeroFillBlock));
EXPECT_FALSE(isCStringBlock(LargerZeroFillBlock));
}
1 change: 1 addition & 0 deletions llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_llvm_unittest(OrcJITTests
LookupAndRecordAddrsTest.cpp
MapperJITLinkMemoryManagerTest.cpp
MemoryMapperTest.cpp
ObjectFormatsTest.cpp
ObjectLinkingLayerTest.cpp
OrcCAPITest.cpp
OrcTestCommon.cpp
Expand Down
33 changes: 33 additions & 0 deletions llvm/unittests/ExecutionEngine/Orc/ObjectFormatsTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-------- ObjectLinkingLayerTest.cpp - ObjectLinkingLayer tests -------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace llvm::orc;

namespace {

TEST(ObjectFormatsTest, MachOInitializerSections) {
EXPECT_TRUE(isMachOInitializerSection("__DATA,__objc_selrefs"));
EXPECT_TRUE(isMachOInitializerSection("__DATA,__mod_init_func"));
EXPECT_TRUE(isMachOInitializerSection("__DATA,__objc_classlist"));
EXPECT_TRUE(isMachOInitializerSection("__TEXT,__swift5_proto"));
EXPECT_TRUE(isMachOInitializerSection("__TEXT,__swift5_protos"));
EXPECT_TRUE(isMachOInitializerSection("__TEXT,__swift5_types"));
EXPECT_FALSE(isMachOInitializerSection("__DATA,__not_an_init_sec"));
}

TEST(ObjectFormatsTest, ELFInitializerSections) {
EXPECT_TRUE(isELFInitializerSection(".init_array"));
EXPECT_TRUE(isELFInitializerSection(".init_array.0"));
EXPECT_FALSE(isELFInitializerSection(".text"));
}

} // end anonymous namespace