Skip to content

Commit

Permalink
Merge pull request #256 from Xilinx/bump_to_2e271ceff668
Browse files Browse the repository at this point in the history
Bump with conflict resolution to 2e271ce (1)
  • Loading branch information
mgehre-amd authored Aug 15, 2024
2 parents 2d24671 + 6710e4d commit a26d9f2
Show file tree
Hide file tree
Showing 1,040 changed files with 27,651 additions and 10,844 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/llvm-project-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ jobs:
else
builddir="$(pwd)"/build
fi
if [ "${{ runner.os }}" == "macOS" ]; then
# Workaround test failure on some lld tests on MacOS
# https://github.com/llvm/llvm-project/issues/81967
extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON"
fi
echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT"
cmake -G Ninja \
-B "$builddir" \
Expand Down
126 changes: 93 additions & 33 deletions bolt/lib/Rewrite/LinuxKernelRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ static cl::opt<bool> DumpParavirtualPatchSites(
"dump-para-sites", cl::desc("dump Linux kernel paravitual patch sites"),
cl::init(false), cl::Hidden, cl::cat(BoltCategory));

static cl::opt<bool>
DumpPCIFixups("dump-pci-fixups",
cl::desc("dump Linux kernel PCI fixup table"),
cl::init(false), cl::Hidden, cl::cat(BoltCategory));

static cl::opt<bool> DumpStaticCalls("dump-static-calls",
cl::desc("dump Linux kernel static calls"),
cl::init(false), cl::Hidden,
Expand Down Expand Up @@ -181,6 +186,10 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Size of bug_entry struct.
static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12;

/// .pci_fixup section.
ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16;

/// Insert an LKMarker for a given code pointer \p PC from a non-code section
/// \p SectionName.
void insertLKMarker(uint64_t PC, uint64_t SectionOffset,
Expand All @@ -190,9 +199,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Process linux kernel special sections and their relocations.
void processLKSections();

/// Process special linux kernel section, .pci_fixup.
void processLKPCIFixup();

/// Process __ksymtab and __ksymtab_gpl.
void processLKKSymtab(bool IsGPL = false);

Expand Down Expand Up @@ -226,6 +232,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Read alternative instruction info from .altinstructions.
Error readAltInstructions();

/// Read .pci_fixup
Error readPCIFixupTable();

/// Mark instructions referenced by kernel metadata.
Error markInstructions();

Expand Down Expand Up @@ -256,6 +265,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
if (Error E = readAltInstructions())
return E;

if (Error E = readPCIFixupTable())
return E;

return Error::success();
}

Expand Down Expand Up @@ -318,41 +330,11 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset,
}

void LinuxKernelRewriter::processLKSections() {
processLKPCIFixup();
processLKKSymtab();
processLKKSymtab(true);
processLKSMPLocks();
}

/// Process .pci_fixup section of Linux Kernel.
/// This section contains a list of entries for different PCI devices and their
/// corresponding hook handler (code pointer where the fixup
/// code resides, usually on x86_64 it is an entry PC relative 32 bit offset).
/// Documentation is in include/linux/pci.h.
void LinuxKernelRewriter::processLKPCIFixup() {
ErrorOr<BinarySection &> SectionOrError =
BC.getUniqueSectionByName(".pci_fixup");
if (!SectionOrError)
return;

const uint64_t SectionSize = SectionOrError->getSize();
const uint64_t SectionAddress = SectionOrError->getAddress();
assert((SectionSize % 16) == 0 && ".pci_fixup size is not a multiple of 16");

for (uint64_t I = 12; I + 4 <= SectionSize; I += 16) {
const uint64_t PC = SectionAddress + I;
ErrorOr<uint64_t> Offset = BC.getSignedValueAtAddress(PC, 4);
assert(Offset && "cannot read value from .pci_fixup");
const int32_t SignedOffset = *Offset;
const uint64_t HookupAddress = PC + SignedOffset;
BinaryFunction *HookupFunction =
BC.getBinaryFunctionAtAddress(HookupAddress);
assert(HookupFunction && "expected function for entry in .pci_fixup");
BC.addRelocation(PC, HookupFunction->getSymbol(), Relocation::getPC32(), 0,
*Offset);
}
}

/// Process __ksymtab[_gpl] sections of Linux Kernel.
/// This section lists all the vmlinux symbols that kernel modules can access.
///
Expand Down Expand Up @@ -1283,6 +1265,84 @@ Error LinuxKernelRewriter::readAltInstructions() {
return Error::success();
}

/// When the Linux kernel needs to handle an error associated with a given PCI
/// device, it uses a table stored in .pci_fixup section to locate a fixup code
/// specific to the vendor and the problematic device. The section contains a
/// list of the following structures defined in include/linux/pci.h:
///
/// struct pci_fixup {
/// u16 vendor; /* Or PCI_ANY_ID */
/// u16 device; /* Or PCI_ANY_ID */
/// u32 class; /* Or PCI_ANY_ID */
/// unsigned int class_shift; /* should be 0, 8, 16 */
/// int hook_offset;
/// };
///
/// Normally, the hook will point to a function start and we don't have to
/// update the pointer if we are not relocating functions. Hence, while reading
/// the table we validate this assumption. If a function has a fixup code in the
/// middle of its body, we issue a warning and ignore it.
Error LinuxKernelRewriter::readPCIFixupTable() {
PCIFixupSection = BC.getUniqueSectionByName(".pci_fixup");
if (!PCIFixupSection)
return Error::success();

if (PCIFixupSection->getSize() % PCI_FIXUP_ENTRY_SIZE)
return createStringError(errc::executable_format_error,
"PCI fixup table size error");

const uint64_t Address = PCIFixupSection->getAddress();
DataExtractor DE = DataExtractor(PCIFixupSection->getContents(),
BC.AsmInfo->isLittleEndian(),
BC.AsmInfo->getCodePointerSize());
uint64_t EntryID = 0;
DataExtractor::Cursor Cursor(0);
while (Cursor && !DE.eof(Cursor)) {
const uint16_t Vendor = DE.getU16(Cursor);
const uint16_t Device = DE.getU16(Cursor);
const uint32_t Class = DE.getU32(Cursor);
const uint32_t ClassShift = DE.getU32(Cursor);
const uint64_t HookAddress =
Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);

if (!Cursor)
return createStringError(errc::executable_format_error,
"out of bounds while reading .pci_fixup: %s",
toString(Cursor.takeError()).c_str());

++EntryID;

if (opts::DumpPCIFixups) {
BC.outs() << "PCI fixup entry: " << EntryID << "\n\tVendor 0x"
<< Twine::utohexstr(Vendor) << "\n\tDevice: 0x"
<< Twine::utohexstr(Device) << "\n\tClass: 0x"
<< Twine::utohexstr(Class) << "\n\tClassShift: 0x"
<< Twine::utohexstr(ClassShift) << "\n\tHookAddress: 0x"
<< Twine::utohexstr(HookAddress) << '\n';
}

BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(HookAddress);
if (!BF && opts::Verbosity) {
BC.outs() << "BOLT-INFO: no function matches address 0x"
<< Twine::utohexstr(HookAddress)
<< " of hook from .pci_fixup\n";
}

if (!BF || !BC.shouldEmit(*BF))
continue;

if (const uint64_t Offset = HookAddress - BF->getAddress()) {
BC.errs() << "BOLT-WARNING: PCI fixup detected in the middle of function "
<< *BF << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
BF->setSimple(false);
}
}

BC.outs() << "BOLT-INFO: parsed " << EntryID << " PCI fixup entries\n";

return Error::success();
}

} // namespace

std::unique_ptr<MetadataRewriter>
Expand Down
41 changes: 41 additions & 0 deletions bolt/test/X86/linux-pci-fixup.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# REQUIRES: system-linux

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie
# RUN: llvm-bolt %t.exe --print-normalized -o %t.out |& FileCheck %s

## Check that BOLT correctly parses the Linux kernel .pci_fixup section and
## verify that PCI fixup hook in the middle of a function is detected.

# CHECK: BOLT-INFO: Linux kernel binary detected
# CHECK: BOLT-WARNING: PCI fixup detected in the middle of function _start
# CHECK: BOLT-INFO: parsed 2 PCI fixup entries

.text
.globl _start
.type _start, %function
_start:
nop
.L0:
ret
.size _start, .-_start

## PCI fixup table.
.section .pci_fixup,"a",@progbits

.short 0x8086 # vendor
.short 0xbeef # device
.long 0xffffffff # class
.long 0x0 # class shift
.long _start - . # fixup

.short 0x8086 # vendor
.short 0xbad # device
.long 0xffffffff # class
.long 0x0 # class shift
.long .L0 - . # fixup

## Fake Linux Kernel sections.
.section __ksymtab,"a",@progbits
.section __ksymtab_gpl,"a",@progbits
28 changes: 28 additions & 0 deletions clang-tools-extra/clangd/unittests/SelectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "SourceCode.h"
#include "TestTU.h"
#include "support/TestTracer.h"
#include "clang/AST/ASTConcept.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/Casting.h"
#include "gmock/gmock.h"
Expand Down Expand Up @@ -893,6 +894,33 @@ TEST(SelectionTest, DeclContextLambda) {
EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod());
}

TEST(SelectionTest, UsingConcepts) {
llvm::Annotations Test(R"cpp(
namespace ns {
template <typename T>
concept Foo = true;
}
using ns::Foo;
template <Fo^o... T, Fo^o auto U>
auto Func(Fo^o auto V) -> Fo^o decltype(auto) {
Fo^o auto W = V;
return W;
}
)cpp");
auto TU = TestTU::withCode(Test.code());
TU.ExtraArgs.emplace_back("-std=c++2c");
auto AST = TU.build();
for (auto Point : Test.points()) {
auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),
Point, Point);
auto *C = ST.commonAncestor()->ASTNode.get<ConceptReference>();
EXPECT_TRUE(C && C->getFoundDecl() &&
C->getFoundDecl()->getKind() == Decl::UsingShadow);
}
}

} // namespace
} // namespace clangd
} // namespace clang
4 changes: 1 addition & 3 deletions clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,7 @@ TEST(WalkAST, Concepts) {
testWalk(Concept, "template<typename T> requires ^Foo<T> void func() {}");
testWalk(Concept, "template<typename T> void func() requires ^Foo<T> {}");
testWalk(Concept, "void func(^Foo auto x) {}");
// FIXME: Foo should be explicitly referenced.
testWalk("template<typename T> concept Foo = true;",
"void func() { ^Foo auto x = 1; }");
testWalk(Concept, "void func() { ^Foo auto x = 1; }");
}

TEST(WalkAST, FriendDecl) {
Expand Down
2 changes: 2 additions & 0 deletions clang/cmake/caches/Fuchsia.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH
LLDB_EMBED_PYTHON_HOME
LLDB_PYTHON_HOME
LLDB_PYTHON_RELATIVE_PATH
LLDB_TEST_USE_VENDOR_PACKAGES
LLDB_TEST_USER_ARGS
Python3_EXECUTABLE
Python3_LIBRARIES
Python3_INCLUDE_DIRS
Expand Down
15 changes: 15 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3443,6 +3443,21 @@ Query for this feature with ``__has_builtin(__builtin_debugtrap)``.
Query for this feature with ``__has_builtin(__builtin_trap)``.
``__builtin_arm_trap``
------------------
``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which also accepts a compile-time constant value, encoded directly into the trap instruction for later inspection.
**Syntax**:
.. code-block:: c++
__builtin_arm_trap(const unsigned short payload)
**Description**
``__builtin_arm_trap`` is lowered to the ``llvm.aarch64.break`` builtin, and then to ``brk #payload``.
``__builtin_nondeterministic_value``
------------------------------------
Expand Down
Loading

0 comments on commit a26d9f2

Please sign in to comment.