Skip to content

Commit 8e49591

Browse files
Merge branch 'main' into llrint-fix
2 parents 97b3514 + cef490d commit 8e49591

File tree

786 files changed

+31782
-21665
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

786 files changed

+31782
-21665
lines changed

.ci/generate_test_report_lib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def plural(num_tests):
267267
report.extend(
268268
[
269269
"",
270-
"All tests passed but another part of the build **failed**. "
270+
"All executed tests passed, but another part of the build **failed**. "
271271
"Information about the build failure could not be automatically "
272272
"obtained.",
273273
"",
@@ -278,7 +278,7 @@ def plural(num_tests):
278278
report.extend(
279279
[
280280
"",
281-
"All tests passed but another part of the build **failed**. Click on "
281+
"All executed tests passed, but another part of the build **failed**. Click on "
282282
"a failure below to see the details.",
283283
"",
284284
]

.ci/generate_test_report_lib_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def test_no_failures_build_failed(self):
343343
344344
* 1 test passed
345345
346-
All tests passed but another part of the build **failed**. Information about the build failure could not be automatically obtained.
346+
All executed tests passed, but another part of the build **failed**. Information about the build failure could not be automatically obtained.
347347
348348
Download the build's log file to see the details.
349349
@@ -390,7 +390,7 @@ def test_no_failures_build_failed_ninja_log(self):
390390
391391
* 1 test passed
392392
393-
All tests passed but another part of the build **failed**. Click on a failure below to see the details.
393+
All executed tests passed, but another part of the build **failed**. Click on a failure below to see the details.
394394
395395
<details>
396396
<summary>test/4.stamp</summary>
@@ -476,7 +476,7 @@ def test_no_failures_multiple_build_failed_ninja_log(self):
476476
477477
* 1 test passed
478478
479-
All tests passed but another part of the build **failed**. Click on a failure below to see the details.
479+
All executed tests passed, but another part of the build **failed**. Click on a failure below to see the details.
480480
481481
<details>
482482
<summary>touch test/2.stamp</summary>
@@ -978,7 +978,7 @@ def test_generate_report_end_to_end(self):
978978
979979
* 1 test passed
980980
981-
All tests passed but another part of the build **failed**. Click on a failure below to see the details.
981+
All executed tests passed, but another part of the build **failed**. Click on a failure below to see the details.
982982
983983
<details>
984984
<summary>test/4.stamp</summary>

.github/workflows/libc-overlay-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations.
1717
fail-fast: false
1818
matrix:
19-
os: [ubuntu-24.04, ubuntu-24.04-arm, windows-2022, windows-2025, macos-14]
19+
os: [ubuntu-24.04, ubuntu-24.04-arm, windows-2022, windows-2025, macos-15]
2020
include:
2121
# TODO: add linux gcc when it is fixed
2222
- os: ubuntu-24.04
@@ -35,7 +35,7 @@ jobs:
3535
compiler:
3636
c_compiler: clang-cl
3737
cpp_compiler: clang-cl
38-
- os: macos-14
38+
- os: macos-15
3939
compiler:
4040
c_compiler: clang
4141
cpp_compiler: clang++

.github/workflows/release-documentation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,4 @@ jobs:
9292
git config user.name "llvmbot"
9393
git commit -a -m "Add ${{ inputs.release-version }} documentation"
9494
git push --force "https://[email protected]/llvmbot/www-releases.git" HEAD:refs/heads/${{ inputs.release-version }}
95-
gh pr create -f -B main -H ${{ inputs.release-version }} -R llvmbot/www-releases
95+
gh pr create -f -B main -H llvmbot:${{ inputs.release-version }}

bolt/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,26 @@ $ merge-fdata *.fdata > combined.fdata
202202
Use `combined.fdata` for **Step 3** above to generate a universally optimized
203203
binary.
204204

205+
## Identifying a Binary Modified By BOLT
206+
207+
A binary that has been modified by BOLT will include a `bolt_info` note and may
208+
have extra sections with `bolt` in their name.
209+
210+
You can use `readelf` to find these:
211+
```
212+
$ readelf -S <your-binary> | grep bolt
213+
[11] .bolt.org.eh_frame PROGBITS <...>
214+
<...>
215+
[39] .note.bolt_info NOTE <...>
216+
```
217+
The note can be displayed with:
218+
```
219+
$ readelf -p .note.bolt_info <your-binary>
220+
String dump of section '.note.bolt_info':
221+
<...>
222+
[ 10] BOLT revision: <...>
223+
```
224+
205225
## License
206226

207227
BOLT is licensed under the [Apache License v2.0 with LLVM Exceptions](./LICENSE.TXT).

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -943,10 +943,11 @@ class BinaryContext {
943943
/// that should be used by the branch. For example, main or secondary entry
944944
/// point.
945945
///
946-
/// If \p Address is an invalid destination, such as a constant island, return
947-
/// nullptr and mark \p BF as ignored, since we cannot properly handle a
948-
/// branch to a constant island.
949-
MCSymbol *handleExternalBranchTarget(uint64_t Address, BinaryFunction &BF);
946+
/// This function also performs validations: If \p Address points to an
947+
/// invalid instruction or lies within a constant island, return nullptr and
948+
/// mark both \p Source and \p Target as ignored.
949+
MCSymbol *handleExternalBranchTarget(uint64_t Address, BinaryFunction &Source,
950+
BinaryFunction &Target);
950951

951952
/// Analyze memory contents at the given \p Address and return the type of
952953
/// memory contents (such as a possible jump table).

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,10 @@ class BinaryFunction {
385385
/// True if the function should not have an associated symbol table entry.
386386
bool IsAnonymous{false};
387387

388+
/// Indicates whether branch validation has already been performed,
389+
/// to avoid redundant processing.
390+
bool NeedBranchValidation{true};
391+
388392
/// Name for the section this function code should reside in.
389393
std::string CodeSectionName;
390394

@@ -2320,6 +2324,11 @@ class BinaryFunction {
23202324
/// zero-value bytes.
23212325
bool isZeroPaddingAt(uint64_t Offset) const;
23222326

2327+
/// Validate if the target of any internal direct branch/call is a valid
2328+
/// executable instruction.
2329+
/// Return true if all the targets are valid, false otherwise.
2330+
bool validateInternalBranches();
2331+
23232332
/// Check that entry points have an associated instruction at their
23242333
/// offsets after disassembly.
23252334
void postProcessEntryPoints();

bolt/lib/Core/BinaryContext.cpp

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -531,20 +531,40 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
531531
}
532532

533533
MCSymbol *BinaryContext::handleExternalBranchTarget(uint64_t Address,
534-
BinaryFunction &BF) {
535-
if (BF.isInConstantIsland(Address)) {
536-
BF.setIgnored();
537-
this->outs() << "BOLT-WARNING: ignoring entry point at address 0x"
538-
<< Twine::utohexstr(Address)
539-
<< " in constant island of function " << BF << '\n';
540-
return nullptr;
534+
BinaryFunction &Source,
535+
BinaryFunction &Target) {
536+
const uint64_t Offset = Address - Target.getAddress();
537+
assert(Offset < Target.getSize() &&
538+
"Address should be inside the referenced function");
539+
540+
bool IsValid = true;
541+
if (Source.NeedBranchValidation) {
542+
if (Target.CurrentState == BinaryFunction::State::Disassembled &&
543+
!Target.getInstructionAtOffset(Offset)) {
544+
this->errs()
545+
<< "BOLT-WARNING: corrupted control flow detected in function "
546+
<< Source
547+
<< ": an external branch/call targets an invalid instruction "
548+
<< "in function " << Target << " at address 0x"
549+
<< Twine::utohexstr(Address) << "; ignoring both functions\n";
550+
IsValid = false;
551+
}
552+
if (Target.isInConstantIsland(Address)) {
553+
this->errs() << "BOLT-WARNING: ignoring entry point at address 0x"
554+
<< Twine::utohexstr(Address)
555+
<< " in constant island of function " << Target << '\n';
556+
IsValid = false;
557+
}
541558
}
542559

543-
const uint64_t Offset = Address - BF.getAddress();
544-
assert(Offset < BF.getSize() &&
545-
"Address should be inside the referenced function");
560+
if (!IsValid) {
561+
Source.NeedBranchValidation = false;
562+
Source.setIgnored();
563+
Target.setIgnored();
564+
return nullptr;
565+
}
546566

547-
return Offset ? BF.addEntryPointAtOffset(Offset) : BF.getSymbol();
567+
return Offset ? Target.addEntryPointAtOffset(Offset) : Target.getSymbol();
548568
}
549569

550570
MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
@@ -1433,7 +1453,7 @@ void BinaryContext::processInterproceduralReferences() {
14331453

14341454
// Create an extra entry point if needed. Can also render the target
14351455
// function ignored if the reference is invalid.
1436-
handleExternalBranchTarget(Address, *TargetFunction);
1456+
handleExternalBranchTarget(Address, Function, *TargetFunction);
14371457

14381458
continue;
14391459
}
@@ -1868,6 +1888,9 @@ void BinaryContext::preprocessDebugInfo() {
18681888

18691889
preprocessDWODebugInfo();
18701890

1891+
// Check if required DWO files are missing.
1892+
uint64_t NumMissingDWOs = 0;
1893+
18711894
// Populate MCContext with DWARF files from all units.
18721895
StringRef GlobalPrefix = AsmInfo->getPrivateGlobalPrefix();
18731896
for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
@@ -1889,19 +1912,23 @@ void BinaryContext::preprocessDebugInfo() {
18891912
std::optional<MD5::MD5Result> Checksum;
18901913
if (LineTable->Prologue.ContentTypes.HasMD5)
18911914
Checksum = LineTable->Prologue.FileNames[0].Checksum;
1892-
std::optional<const char *> Name =
1915+
const char *Name =
18931916
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
18941917
if (std::optional<uint64_t> DWOID = CU->getDWOId()) {
18951918
auto Iter = DWOCUs.find(*DWOID);
18961919
if (Iter == DWOCUs.end()) {
1897-
this->errs() << "BOLT-ERROR: DWO CU was not found for " << Name
1898-
<< '\n';
1899-
exit(1);
1920+
const char *DWOName =
1921+
dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_dwo_name),
1922+
"<missing DW_AT_dwo_name>");
1923+
this->errs() << "BOLT-ERROR: unable to load " << DWOName
1924+
<< " for DWO_id 0x" << Twine::utohexstr(*DWOID) << '\n';
1925+
NumMissingDWOs++;
1926+
continue;
19001927
}
19011928
Name = dwarf::toString(
19021929
Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
19031930
}
1904-
BinaryLineTable.setRootFile(CU->getCompilationDir(), *Name, Checksum,
1931+
BinaryLineTable.setRootFile(CU->getCompilationDir(), Name, Checksum,
19051932
std::nullopt);
19061933
}
19071934

@@ -1936,6 +1963,14 @@ void BinaryContext::preprocessDebugInfo() {
19361963
DwarfVersion));
19371964
}
19381965
}
1966+
1967+
if (NumMissingDWOs) {
1968+
this->errs() << "BOLT-ERROR: " << NumMissingDWOs
1969+
<< " required DWO file(s) not found. Unable to update debug"
1970+
" info. Use --comp-dir-override to locate the file(s) or"
1971+
" --update-debug-sections=0 to remove debug info\n";
1972+
exit(1);
1973+
}
19391974
}
19401975

19411976
bool BinaryContext::shouldEmit(const BinaryFunction &Function) const {

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,8 +1038,10 @@ MCSymbol *BinaryFunction::getOrCreateLocalLabel(uint64_t Address) {
10381038

10391039
// For AArch64, check if this address is part of a constant island.
10401040
if (BC.isAArch64()) {
1041-
if (MCSymbol *IslandSym = getOrCreateIslandAccess(Address))
1041+
if (MCSymbol *IslandSym = getOrCreateIslandAccess(Address)) {
1042+
Labels[Offset] = IslandSym;
10421043
return IslandSym;
1044+
}
10431045
}
10441046

10451047
if (Offset == getSize())
@@ -1692,7 +1694,7 @@ bool BinaryFunction::scanExternalRefs() {
16921694
// Get a reference symbol for the function when address is a valid code
16931695
// reference.
16941696
BranchTargetSymbol =
1695-
BC.handleExternalBranchTarget(TargetAddress, *TargetFunction);
1697+
BC.handleExternalBranchTarget(TargetAddress, *this, *TargetFunction);
16961698
if (!BranchTargetSymbol)
16971699
continue;
16981700
}
@@ -1900,6 +1902,36 @@ bool BinaryFunction::scanExternalRefs() {
19001902
return Success;
19011903
}
19021904

1905+
bool BinaryFunction::validateInternalBranches() {
1906+
if (!isSimple() || TrapsOnEntry)
1907+
return true;
1908+
1909+
for (const auto &KV : Labels) {
1910+
MCSymbol *Label = KV.second;
1911+
if (getSecondaryEntryPointSymbol(Label))
1912+
continue;
1913+
1914+
const uint32_t Offset = KV.first;
1915+
// Skip empty functions and out-of-bounds offsets,
1916+
// as they may not be disassembled.
1917+
if (!Offset || (Offset > getSize()))
1918+
continue;
1919+
1920+
if (!getInstructionAtOffset(Offset) ||
1921+
isInConstantIsland(getAddress() + Offset)) {
1922+
BC.errs() << "BOLT-WARNING: corrupted control flow detected in function "
1923+
<< *this << ": an internal branch/call targets an invalid "
1924+
<< "instruction at address 0x"
1925+
<< Twine::utohexstr(getAddress() + Offset)
1926+
<< "; ignoring this function\n";
1927+
setIgnored();
1928+
return false;
1929+
}
1930+
}
1931+
1932+
return true;
1933+
}
1934+
19031935
void BinaryFunction::postProcessEntryPoints() {
19041936
if (!isSimple())
19051937
return;

bolt/lib/Passes/PAuthGadgetScanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ class SrcSafetyAnalysis {
547547

548548
// Being trusted is a strictly stronger property than being
549549
// safe-to-dereference.
550-
assert(!Next.TrustedRegs.test(Next.SafeToDerefRegs) &&
550+
assert(Next.TrustedRegs.subsetOf(Next.SafeToDerefRegs) &&
551551
"SafeToDerefRegs should contain all TrustedRegs");
552552

553553
return Next;

0 commit comments

Comments
 (0)