1
Fork 0

Support for -Z patchable-function-entry

`-Z patchable-function-entry` works like `-fpatchable-function-entry`
on clang/gcc. The arguments are total nop count and function offset.

See MCP rust-lang/compiler-team#704
This commit is contained in:
Matthew Maurer 2023-12-12 13:32:43 -08:00 committed by Florian Schmiderer
parent d929a42a66
commit ac7595fdb1
7 changed files with 139 additions and 1 deletions

View file

@ -2963,7 +2963,7 @@ pub(crate) mod dep_tracking {
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
};
use crate::lint;
@ -3071,6 +3071,7 @@ pub(crate) mod dep_tracking {
OomStrategy,
LanguageIdentifier,
NextSolverConfig,
PatchableFunctionEntry,
Polonius,
InliningThreshold,
FunctionReturn,
@ -3248,6 +3249,32 @@ impl DumpMonoStatsFormat {
}
}
/// `-Z patchable-function-entry` representation - how many nops to put before and after function
/// entry.
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
pub struct PatchableFunctionEntry {
/// Nops before the entry
prefix: u8,
/// Nops after the entry
entry: u8,
}
impl PatchableFunctionEntry {
pub fn from_nop_count_and_offset(nop_count: u8, offset: u8) -> Option<PatchableFunctionEntry> {
if nop_count < offset {
None
} else {
Some(Self { prefix: offset, entry: nop_count - offset })
}
}
pub fn prefix(&self) -> u8 {
self.prefix
}
pub fn entry(&self) -> u8 {
self.entry
}
}
/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
/// or future prototype.
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]

View file

@ -379,6 +379,8 @@ mod desc {
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
pub const parse_patchable_function_entry: &str =
"nop_count,entry_offset or nop_count (defaulting entry_offset=0)";
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@ -723,6 +725,7 @@ mod parse {
true
}
pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool {
match v {
// OnBrokenPipe::Default can't be explicitly specified
@ -734,6 +737,30 @@ mod parse {
true
}
pub(crate) fn parse_patchable_function_entry(
slot: &mut PatchableFunctionEntry,
v: Option<&str>,
) -> bool {
let mut nop_count = 0;
let mut offset = 0;
if !parse_number(&mut nop_count, v) {
let parts = v.and_then(|v| v.split_once(',')).unzip();
if !parse_number(&mut nop_count, parts.0) {
return false;
}
if !parse_number(&mut offset, parts.1) {
return false;
}
}
if let Some(pfe) = PatchableFunctionEntry::from_nop_count_and_offset(nop_count, offset) {
*slot = pfe;
return true;
}
false
}
pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
match v {
Some("panic") => *slot = OomStrategy::Panic,
@ -1859,6 +1886,8 @@ options! {
"panic strategy for panics in drops"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link (default: no)"),
patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
"nop padding at function entry"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether to use the PLT when calling into shared libraries;
only has effect for PIC code on systems with ELF binaries