Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/MinGW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lgmon");

if (Args.hasArg(options::OPT_pthread))
if (!Args.hasArg(options::OPT_no_pthread))
CmdArgs.push_back("-lpthread");

if (Sanitize.needsAsanRt()) {
Expand Down
2 changes: 2 additions & 0 deletions lld/MinGW/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
// Ignored options
def: Joined<["-"], "O">;
def: F<"as-needed">;
def: F<"default-image-base-high">;
def: F<"default-image-base-low">;
def: F<"disable-auto-image-base">;
def: F<"enable-auto-image-base">;
def: F<"end-group">;
Expand Down
5 changes: 4 additions & 1 deletion llvm/cmake/modules/Findzstd.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ else()
set(zstd_STATIC_LIBRARY_SUFFIX "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")
endif()

find_package(zstd CONFIG QUIET)
if(NOT zstd_FOUND)
find_path(zstd_INCLUDE_DIR NAMES zstd.h)
find_library(zstd_LIBRARY NAMES zstd zstd_static)
find_library(zstd_STATIC_LIBRARY NAMES
Expand All @@ -27,6 +29,7 @@ find_package_handle_standard_args(
zstd DEFAULT_MSG
zstd_LIBRARY zstd_INCLUDE_DIR
)
endif()

if(zstd_FOUND)
if(zstd_LIBRARY MATCHES "${zstd_STATIC_LIBRARY_SUFFIX}$" AND NOT zstd_LIBRARY MATCHES "\\.dll\\.a$")
Expand All @@ -38,7 +41,7 @@ if(zstd_FOUND)
# IMPORTED_LOCATION is the path to the DLL and IMPORTED_IMPLIB is the "library".
get_filename_component(zstd_DIRNAME "${zstd_LIBRARY}" DIRECTORY)
if(NOT "${CMAKE_INSTALL_LIBDIR}" STREQUAL "" AND NOT "${CMAKE_INSTALL_BINDIR}" STREQUAL "")
string(REGEX REPLACE "${CMAKE_INSTALL_LIBDIR}$" "${CMAKE_INSTALL_BINDIR}" zstd_DIRNAME "${zstd_DIRNAME}")
string(REGEX REPLACE "\\${CMAKE_INSTALL_LIBDIR}$" "${CMAKE_INSTALL_BINDIR}" zstd_DIRNAME "${zstd_DIRNAME}")
endif()
get_filename_component(zstd_BASENAME "${zstd_LIBRARY}" NAME)
string(REGEX REPLACE "\\${CMAKE_LINK_LIBRARY_SUFFIX}$" "${CMAKE_SHARED_LIBRARY_SUFFIX}" zstd_BASENAME "${zstd_BASENAME}")
Expand Down
2 changes: 1 addition & 1 deletion llvm/cmake/modules/GetHostTriple.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function( get_host_triple var )
else()
set( value "i686-pc-windows-msvc" )
endif()
elseif( MINGW AND NOT MSYS )
elseif( MINGW )
# CMake doesn't provide COMPILER_ARCHITECTURE_ID for Clang/GCC,
# but it does for MSVC.
if( CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "ARM.*" )
Expand Down
53 changes: 53 additions & 0 deletions llvm/include/llvm/ExecutionEngine/Orc/SEHFrameRegistrationPlugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//===- SEHFrameRegistrationPlugin.h - Register COFF EH info in-process -*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Register and deregister .pdata sections in-process using RtlAddFunctionTable
// and RtlDeleteFunctionTable.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_ORC_SEHFRAMEREGISTRATIONPLUGIN_H
#define LLVM_EXECUTIONENGINE_ORC_SEHFRAMEREGISTRATIONPLUGIN_H

#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h"

namespace llvm::orc {

/// Registers .pdata sections with the Windows unwinder via RtlAddFunctionTable.
///
/// This plugin enables SEH-based stack unwinding for JIT'd code on Windows
/// by registering unwind metadata at finalization and deregistering it on
/// deallocation.
class LLVM_ABI SEHFrameRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
public:
/// Adds a pass to PassConfig that registers .pdata sections in LG with the
/// OS unwinder.
void modifyPassConfig(MaterializationResponsibility &MR,
jitlink::LinkGraph &LG,
jitlink::PassConfiguration &PassConfig) override;

Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}

Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
return Error::success();
}

void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
ResourceKey SrcKey) override {}

private:
/// Registers .pdata sections in G with the OS unwinder.
/// Returns an error if registration setup fails.
Error registerFrameInfo(jitlink::LinkGraph &G);
};

} // namespace llvm::orc

#endif // LLVM_EXECUTIONENGINE_ORC_SEHFRAMEREGISTRATIONPLUGIN_H
4 changes: 1 addition & 3 deletions llvm/lib/ExecutionEngine/JITLink/COFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,12 @@ Symbol *GetImageBaseSymbol::operator()(LinkGraph &G) {
if (ImageBase)
return *ImageBase;

// __ImageBase is only ever external (generic platform) or absolute (COFFPlatform).
auto IBN = G.intern(ImageBaseName);
ImageBase = G.findExternalSymbolByName(IBN);
if (*ImageBase)
return *ImageBase;
ImageBase = G.findAbsoluteSymbolByName(IBN);
if (*ImageBase)
return *ImageBase;
ImageBase = G.findDefinedSymbolByName(IBN);
if (*ImageBase)
return *ImageBase;

Expand Down
27 changes: 24 additions & 3 deletions llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,16 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
return make_error<JITLinkError>(
"COMDAT export request already exists before symbol " +
formatv("{0:d}", SymIndex));
return createCOMDATExportRequest(SymIndex, Symbol, Definition);

if (auto Err = createCOMDATExportRequest(SymIndex, Symbol, Definition).takeError())
return Err;

// Return a local symbol so relocations can resolve against this index.
// COMDAT sections without an export (e.g. .xdata$*) keep this symbol,
// while those with one will get it replaced in exportCOMDATSymbol.
return &G->addDefinedSymbol(
*B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
}
return make_error<JITLinkError>("Unsupported storage class " +
formatv("{0:d}", Symbol.getStorageClass()) +
Expand All @@ -550,9 +559,13 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
// Second symbol is COMDAT symbol which usually defines the external name and
// data type.
//
// Since two symbols always come in a specific order, we initiate pending COMDAT
// Since two symbols usually come in a specific order, we initiate pending COMDAT
// export request when we encounter the first symbol and actually exports it
// when we process the second symbol.
// when we process the second symbol. However, some COMDAT sections (e.g.
// .xdata$*, .pdata$*) only have the section definition symbol with no
// export following. The caller SHOULD register a local symbol for the first
// symbol's index unconditionally so that relocations targeting it can
// resolve regardless of whether an export symbol follows.
//
// Process the first symbol of COMDAT sequence.
Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
Expand Down Expand Up @@ -604,6 +617,9 @@ Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
}

// Process the second symbol of COMDAT sequence.
//
// Replaces the local placeholder registered for the first symbol's
// index.
Expected<Symbol *>
COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
orc::SymbolStringPtr SymbolName,
Expand All @@ -623,6 +639,11 @@ COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
<< "\" in section " << Symbol.getSectionNumber() << "\n";
dbgs() << " " << *GSym << "\n";
});

// Clear the first symbol's provisional placeholder so
// setGraphSymbol can replace it.
GraphSymbols[PendingComdatExport->SymbolIndex] = nullptr;

setGraphSymbol(Symbol.getSectionNumber(), PendingComdatExport->SymbolIndex,
*GSym);
DefinedSymbols[SymbolName] = GSym;
Expand Down
106 changes: 106 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,106 @@ class COFFLinkGraphLowering_x86_64 {
GetImageBaseSymbol GetImageBase;
DenseMap<Section *, orc::ExecutorAddr> SectionStartCache;
};

// A LinkGraph pass that resolves __ImageBase for COFF x86_64 graphs
class COFFImageBaseResolution_x86_64 {
public:
// Resolves __ImageBase to the lowest allocated section address in G
Error operator()(LinkGraph &G) {
GetImageBaseSymbol GetImageBase;

auto ImageBase = GetImageBase(G);
if (ImageBase) {
orc::ExecutorAddr Base(~uint64_t(0));
for (auto &Sec : G.sections()) {
if (Sec.empty())
continue;
SectionRange SR(Sec);
Base = std::min(Base, SR.getStart());
}
assert(ImageBase && "__ImageBase symbol must be defined");
ImageBase->getAddressable().setAddress(Base);
}
return Error::success();
}
};

// Creates executable stubs for Pointer32NB edges targeting external
// symbols whose image relative offset from __ImageBase would exceed
// 32 bits.
class COFFPointer32NBStubsManager : public llvm::jitlink::TableManager<COFFPointer32NBStubsManager> {
public:
// Returns section name for ADDR32NB stubs in the link graph.
static StringRef getSectionName() { return "$__STUBS_ADDR32NB"; }

// Constructs a stub manager using GOT for indirect jump targets.
COFFPointer32NBStubsManager(LinkGraph &, x86_64::GOTTableManager &GOT) : GOT(GOT) {
}

// Checks edge E on block B in graph G. If E is a Pointer32NB
// targeting an external, redirects it to a nearby stub. Returns
// true if handled.
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
if (E.getKind() == EdgeKind_coff_x86_64::Pointer32NB && !E.getTarget().isDefined()) {
DEBUG_WITH_TYPE("jitlink", {
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
<< B->getFixupAddress(E) << " (" << B->getAddress() << " + "
<< formatv("{0:x}", E.getOffset()) << ")\n";
});

E.setTarget(getEntryForTarget(G, E.getTarget()));
return true;
}
return false;
}

// Creates an executable stub in G that jumps to Target via a GOT
// entry. Returns an anonymous symbol pointing to the stub.
Symbol &createEntry(LinkGraph &G, Symbol &Target) {
return x86_64::createAnonymousPointerJumpStub(G, getStubsSection(G),
GOT.getEntryForTarget(G, Target));
}

public:
// Returns the executable stub section in G, creating it on first
// call.
Section &getStubsSection(LinkGraph &G) {
if (!StubsSection)
StubsSection = &G.createSection(getSectionName(),
orc::MemProt::Read | orc::MemProt::Exec);
return *StubsSection;
}

// Shared GOT for indirect jump targets.
x86_64::GOTTableManager &GOT;
// Lazily created stub section.
Section *StubsSection = nullptr;
};

// Create stubs in G for external references: PLT stubs for calls (PCRel32)
// and ADDR32NB stubs for image-relative pointers (Pointer32NB). Always succeeds.
Error buildTables_COFF_x86_64(LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");

x86_64::GOTTableManager GOT(G);
x86_64::PLTTableManager PLT(G, GOT);
COFFPointer32NBStubsManager COFFPtr32NB(G, GOT);

// Mark calls to externals as BranchPCRel32 so PLTTableManager will create
// stubs for them. Without this, it ignores COFF's PCRel32 edge kind.
for (auto *B : G.blocks()) {
for (auto &E : B->edges()) {
if (E.getKind() == EdgeKind_coff_x86_64::PCRel32 &&
!E.getTarget().isDefined()) {
E.setKind(x86_64::BranchPCRel32);
}
}
}

visitExistingEdges(G, PLT, COFFPtr32NB);
return Error::success();
}

} // namespace

namespace llvm {
Expand Down Expand Up @@ -303,6 +403,12 @@ void link_COFF_x86_64(std::unique_ptr<LinkGraph> G,
} else
Config.PrePrunePasses.push_back(markAllSymbolsLive);

// Add an in place GOT/PLT stub build pass for external calls.
Config.PostPrunePasses.push_back(buildTables_COFF_x86_64);

// Add ImageBase resolution pass, needed by Lowering and other downstream passes.
Config.PreFixupPasses.push_back(COFFImageBaseResolution_x86_64());

// Add COFF edge lowering passes.
Config.PreFixupPasses.push_back(COFFLinkGraphLowering_x86_64());
}
Expand Down
51 changes: 28 additions & 23 deletions llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,44 @@

namespace llvm {
namespace jitlink {
/// This pass adds keep-alive edge from SEH frame sections
/// to the parent function content block.
/// This pass adds keep-alive edges from SEH frame sections
/// to parent function content blocks.
class SEHFrameKeepAlivePass {
public:
SEHFrameKeepAlivePass(StringRef SEHFrameSectionName)
: SEHFrameSectionName(SEHFrameSectionName) {}
/// SEHFrameSectionNamePrefix to match against graph sections
SEHFrameKeepAlivePass(StringRef SEHFrameSectionNamePrefix)
: SEHFrameSectionNamePrefix(SEHFrameSectionNamePrefix) {}

/// Adds keep alive edges in G for all sections matching
/// SEHFrameSectionNamePrefix
Error operator()(LinkGraph &G) {
auto *S = G.findSectionByName(SEHFrameSectionName);
if (!S)
return Error::success();

// Simply consider every block pointed by seh frame block as parants.
// This adds some unnecessary keep-alive edges to unwind info blocks,
// (xdata) but these blocks are usually dead by default, so they wouldn't
// count for the fate of seh frame block.
for (auto *B : S->blocks()) {
auto &DummySymbol = G.addAnonymousSymbol(*B, 0, 0, false, false);
SetVector<Block *> Children;
for (auto &E : B->edges()) {
auto &Sym = E.getTarget();
if (!Sym.isDefined())
continue;
Children.insert(&Sym.getBlock());
for (auto &S : G.sections()) {
if (!S.getName().starts_with(SEHFrameSectionNamePrefix))
continue;

// Simply consider every block pointed by seh frame block as parents.
// This adds some unnecessary keep-alive edges to unwind info blocks,
// (xdata) but these blocks are usually dead by default, so they wouldn't
// count for the fate of seh frame block.
for (auto *B : S.blocks()) {
auto &DummySymbol = G.addAnonymousSymbol(*B, 0, 0, false, false);
SetVector<Block *> Children;
for (auto &E : B->edges()) {
auto &Sym = E.getTarget();
if (!Sym.isDefined())
continue;
Children.insert(&Sym.getBlock());
}
for (auto *Child : Children)
Child->addEdge(Edge(Edge::KeepAlive, 0, DummySymbol, 0));
}
for (auto *Child : Children)
Child->addEdge(Edge(Edge::KeepAlive, 0, DummySymbol, 0));
}
return Error::success();
}

private:
StringRef SEHFrameSectionName;
/// Sections starting with this prefix are kept alive
StringRef SEHFrameSectionNamePrefix;
};

} // end namespace jitlink
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ add_llvm_component_library(LLVMOrcJIT
OrcV2CBindings.cpp
RTDyldObjectLinkingLayer.cpp
SectCreate.cpp
SEHFrameRegistrationPlugin.cpp
SelfExecutorProcessControl.cpp
SimpleRemoteEPC.cpp
SimpleRemoteMemoryMapper.cpp
Expand Down
Loading