Skip to content

Commit 3bcb724

Browse files
authored
[BOLT] Add --custom-allocation-vma flag (#136385)
Add an advanced-user flag so we are able to rewrite binaries when we fail to identify a suitable location to put new code. User then can supply a custom location via --custom-allocation-vma. This happens more obviously if the binary has segments mapped to very high addresses.
1 parent c239acb commit 3bcb724

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@ UseGnuStack("use-gnu-stack",
237237
cl::ZeroOrMore,
238238
cl::cat(BoltCategory));
239239

240+
static cl::opt<uint64_t> CustomAllocationVMA(
241+
"custom-allocation-vma",
242+
cl::desc("use a custom address at which new code will be put, "
243+
"bypassing BOLT's logic to detect where to put code"),
244+
cl::Hidden, cl::cat(BoltCategory));
245+
240246
static cl::opt<bool>
241247
SequentialDisassembly("sequential-disassembly",
242248
cl::desc("performs disassembly sequentially"),
@@ -592,6 +598,25 @@ Error RewriteInstance::discoverStorage() {
592598

593599
FirstNonAllocatableOffset = NextAvailableOffset;
594600

601+
if (opts::CustomAllocationVMA) {
602+
// If user specified a custom address where we should start writing new
603+
// data, honor that.
604+
NextAvailableAddress = opts::CustomAllocationVMA;
605+
// Sanity check the user-supplied address and emit warnings if something
606+
// seems off.
607+
for (const ELF64LE::Phdr &Phdr : PHs) {
608+
switch (Phdr.p_type) {
609+
case ELF::PT_LOAD:
610+
if (NextAvailableAddress >= Phdr.p_vaddr &&
611+
NextAvailableAddress < Phdr.p_vaddr + Phdr.p_memsz) {
612+
BC->errs() << "BOLT-WARNING: user-supplied allocation vma 0x"
613+
<< Twine::utohexstr(NextAvailableAddress)
614+
<< " conflicts with ELF segment at 0x"
615+
<< Twine::utohexstr(Phdr.p_vaddr) << "\n";
616+
}
617+
}
618+
}
619+
}
595620
NextAvailableAddress = alignTo(NextAvailableAddress, BC->PageAlign);
596621
NextAvailableOffset = alignTo(NextAvailableOffset, BC->PageAlign);
597622

bolt/test/X86/high-segments.s

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Check that we are able to rewrite binaries when we fail to identify a
2+
// suitable location to put new code and user supplies a custom one via
3+
// --custom-allocation-vma. This happens more obviously if the binary has
4+
// segments mapped to very high addresses.
5+
6+
// In this example, my.reserved.section is mapped to a segment to be loaded
7+
// at address 0x10000000000, while regular text should be at 0x200000. We
8+
// pick a vma in the middle at 0x700000 to carve space for BOLT to put data,
9+
// since BOLT's usual route of allocating after the last segment will put
10+
// code far away and that will blow up relocations from main.
11+
12+
// RUN: split-file %s %t
13+
// RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o
14+
// RUN: %clang %cflags -no-pie %t.o -o %t.exe -Wl,-T %t/main.ls
15+
// RUN: llvm-bolt %t.exe -o %t.bolt --custom-allocation-vma=0x700000
16+
17+
//--- main.s
18+
.type reserved_space,@object
19+
.section .my.reserved.section,"awx",@nobits
20+
.globl reserved_space
21+
.p2align 4, 0x0
22+
reserved_space:
23+
.zero 0x80000000
24+
.size reserved_space, 0x80000000
25+
26+
.text
27+
.globl main
28+
.globl _start
29+
.type main, %function
30+
_start:
31+
main:
32+
.cfi_startproc
33+
nop
34+
nop
35+
nop
36+
retq
37+
.cfi_endproc
38+
.size main, .-main
39+
40+
//--- main.ls
41+
SECTIONS
42+
{
43+
.my.reserved.section 1<<40 : {
44+
*(.my.reserved.section);
45+
}
46+
} INSERT BEFORE .comment;

0 commit comments

Comments
 (0)