Skip to content

[BOLT] Add --custom-allocation-vma flag #136385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 19, 2025
Merged
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
25 changes: 25 additions & 0 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ UseGnuStack("use-gnu-stack",
cl::ZeroOrMore,
cl::cat(BoltCategory));

static cl::opt<uint64_t> CustomAllocationVMA(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want this flag to be at the top level or hidden?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a good idea to put it hidden. Let me do that.

"custom-allocation-vma",
cl::desc("use a custom address at which new code will be put, "
"bypassing BOLT's logic to detect where to put code"),
cl::Hidden, cl::cat(BoltCategory));

static cl::opt<bool>
SequentialDisassembly("sequential-disassembly",
cl::desc("performs disassembly sequentially"),
Expand Down Expand Up @@ -592,6 +598,25 @@ Error RewriteInstance::discoverStorage() {

FirstNonAllocatableOffset = NextAvailableOffset;

if (opts::CustomAllocationVMA) {
// If user specified a custom address where we should start writing new
// data, honor that.
NextAvailableAddress = opts::CustomAllocationVMA;
// Sanity check the user-supplied address and emit warnings if something
// seems off.
for (const ELF64LE::Phdr &Phdr : PHs) {
switch (Phdr.p_type) {
case ELF::PT_LOAD:
if (NextAvailableAddress >= Phdr.p_vaddr &&
NextAvailableAddress < Phdr.p_vaddr + Phdr.p_memsz) {
BC->errs() << "BOLT-WARNING: user-supplied allocation vma 0x"
<< Twine::utohexstr(NextAvailableAddress)
<< " conflicts with ELF segment at 0x"
<< Twine::utohexstr(Phdr.p_vaddr) << "\n";
}
}
}
}
NextAvailableAddress = alignTo(NextAvailableAddress, BC->PageAlign);
NextAvailableOffset = alignTo(NextAvailableOffset, BC->PageAlign);

Expand Down
46 changes: 46 additions & 0 deletions bolt/test/X86/high-segments.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Check that we are able to rewrite binaries when we fail to identify a
// suitable location to put new code and user supplies a custom one via
// --custom-allocation-vma. This happens more obviously if the binary has
// segments mapped to very high addresses.

// In this example, my.reserved.section is mapped to a segment to be loaded
// at address 0x10000000000, while regular text should be at 0x200000. We
// pick a vma in the middle at 0x700000 to carve space for BOLT to put data,
// since BOLT's usual route of allocating after the last segment will put
// code far away and that will blow up relocations from main.

// RUN: split-file %s %t
// RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o
// RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-T %t/main.ls
// RUN: llvm-bolt %t.exe -o %t.bolt --custom-allocation-vma=0x700000

//--- main.s
.type reserved_space,@object
.section .my.reserved.section,"awx",@nobits
.globl reserved_space
.p2align 4, 0x0
reserved_space:
.zero 0x80000000
.size reserved_space, 0x80000000

.text
.globl main
.globl _start
.type main, %function
_start:
main:
.cfi_startproc
nop
nop
nop
retq
.cfi_endproc
.size main, .-main

//--- main.ls
SECTIONS
{
.my.reserved.section 1<<40 : {
*(.my.reserved.section);
}
} INSERT BEFORE .comment;
Loading