@@ -54,6 +54,12 @@ FunctionPadSpec("pad-funcs",
54
54
cl::Hidden,
55
55
cl::cat(BoltCategory));
56
56
57
+ static cl::list<std::string> FunctionPadBeforeSpec (
58
+ " pad-funcs-before" , cl::CommaSeparated,
59
+ cl::desc (" list of functions to pad with amount of bytes" ),
60
+ cl::value_desc(" func1:pad1,func2:pad2,func3:pad3,..." ), cl::Hidden,
61
+ cl::cat(BoltCategory));
62
+
57
63
static cl::opt<bool > MarkFuncs (
58
64
" mark-funcs" ,
59
65
cl::desc (" mark function boundaries with break instruction to make "
@@ -94,6 +100,30 @@ size_t padFunction(const BinaryFunction &Function) {
94
100
return 0 ;
95
101
}
96
102
103
+ size_t padFunctionBefore (const BinaryFunction &Function) {
104
+ static std::map<std::string, size_t > FunctionPadding;
105
+
106
+ if (FunctionPadding.empty () && !FunctionPadBeforeSpec.empty ()) {
107
+ for (std::string &Spec : FunctionPadBeforeSpec) {
108
+ size_t N = Spec.find (' :' );
109
+ if (N == std::string::npos)
110
+ continue ;
111
+ std::string Name = Spec.substr (0 , N);
112
+ size_t Padding = std::stoull (Spec.substr (N + 1 ));
113
+ FunctionPadding[Name] = Padding;
114
+ }
115
+ }
116
+
117
+ for (auto &FPI : FunctionPadding) {
118
+ std::string Name = FPI.first ;
119
+ size_t Padding = FPI.second ;
120
+ if (Function.hasNameRegex (Name))
121
+ return Padding;
122
+ }
123
+
124
+ return 0 ;
125
+ }
126
+
97
127
} // namespace opts
98
128
99
129
namespace {
@@ -319,6 +349,36 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
319
349
Streamer.emitCodeAlignment (Function.getAlign (), &*BC.STI );
320
350
}
321
351
352
+ if (size_t Padding = opts::padFunctionBefore (Function)) {
353
+ // Handle padFuncsBefore after the above alignment logic but before
354
+ // symbol addresses are decided; with the intent that the nops are
355
+ // not executed and the original alignment logic is preserved.
356
+ if (!BC.HasRelocations ) {
357
+ errs () << " BOLT-ERROR: -pad-before-funcs is not supported in "
358
+ << " non-relocation mode\n " ;
359
+ exit (1 );
360
+ }
361
+
362
+ // Preserve Function.getMinAlign().
363
+ if (!isAligned (Function.getMinAlign (), Padding)) {
364
+ errs () << " BOLT-ERROR: User-requested " << Padding
365
+ << " padding bytes before function " << Function
366
+ << " is not a multiple of the minimum function alignment ("
367
+ << Function.getMinAlign ().value () << " ).\n " ;
368
+ exit (1 );
369
+ }
370
+
371
+ LLVM_DEBUG (dbgs () << " BOLT-DEBUG: padding function " << Function << " with "
372
+ << Padding << " bytes\n " );
373
+
374
+ // Since the padding is not executed, it can be null bytes.
375
+ Streamer.emitFill (Padding, 0 );
376
+
377
+ Function.setMaxSize (Function.getMaxSize () + Padding);
378
+ Function.setSize (Function.getSize () + Padding);
379
+ Function.setImageSize (Function.getImageSize () + Padding);
380
+ }
381
+
322
382
MCContext &Context = Streamer.getContext ();
323
383
const MCAsmInfo *MAI = Context.getAsmInfo ();
324
384
0 commit comments