Skip to content

Commit 486b5df

Browse files
committed
Auto merge of #1832 - hyd-dev:1776-follow-up, r=RalfJung
Report an error if a `#[no_mangle]`/`#[export_name = ...]` function has the same symbol name as a built-in shim Implements #1776 (comment). The error looks like this: ``` error: found `malloc` symbol definition that clashes with a built-in shim --> tests/compile-fail/function_calls/exported_symbol_shim_clashing.rs:12:9 | 12 | malloc(0); | ^^^^^^^^^ found `malloc` symbol definition that clashes with a built-in shim | help: the `malloc` symbol is defined here --> tests/compile-fail/function_calls/exported_symbol_shim_clashing.rs:2:1 | 2 | / extern "C" fn malloc(_: usize) -> *mut std::ffi::c_void { 3 | | //~^ HELP the `malloc` symbol is defined here 4 | | unreachable!() 5 | | } | |_^ = note: inside `main` at tests/compile-fail/function_calls/exported_symbol_shim_clashing.rs:12:9 ``` This does not implement "better error messages than we do currently for arg/ABI mismatches" in #1776 (comment) -- I failed to remove all `check_arg_count()` and `check_abi()` (they are still used in `src/shims/intrinsics.rs` and `call_dlsym()`) and they don't receive the name of the shim.
2 parents 042db78 + aaaa142 commit 486b5df

File tree

13 files changed

+350
-371
lines changed

13 files changed

+350
-371
lines changed

src/diagnostics.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ pub enum TerminationInfo {
2626
second: SpanData,
2727
second_crate: Symbol,
2828
},
29+
SymbolShimClashing {
30+
link_name: Symbol,
31+
span: SpanData,
32+
},
2933
}
3034

3135
impl fmt::Display for TerminationInfo {
@@ -39,6 +43,11 @@ impl fmt::Display for TerminationInfo {
3943
Deadlock => write!(f, "the evaluated program deadlocked"),
4044
MultipleSymbolDefinitions { link_name, .. } =>
4145
write!(f, "multiple definitions of symbol `{}`", link_name),
46+
SymbolShimClashing { link_name, .. } => write!(
47+
f,
48+
"found `{}` symbol definition that clashes with a built-in shim",
49+
link_name
50+
),
4251
}
4352
}
4453
}
@@ -79,7 +88,7 @@ pub fn report_error<'tcx, 'mir>(
7988
UnsupportedInIsolation(_) => Some("unsupported operation"),
8089
ExperimentalUb { .. } => Some("Undefined Behavior"),
8190
Deadlock => Some("deadlock"),
82-
MultipleSymbolDefinitions { .. } => None,
91+
MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
8392
};
8493
#[rustfmt::skip]
8594
let helps = match info {
@@ -98,6 +107,8 @@ pub fn report_error<'tcx, 'mir>(
98107
(Some(*first), format!("it's first defined here, in crate `{}`", first_crate)),
99108
(Some(*second), format!("then it's defined here again, in crate `{}`", second_crate)),
100109
],
110+
SymbolShimClashing { link_name, span } =>
111+
vec![(Some(*span), format!("the `{}` symbol is defined here", link_name))],
101112
_ => vec![],
102113
};
103114
(title, helps)

src/helpers.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use log::trace;
88
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
99
use rustc_middle::mir;
1010
use rustc_middle::ty::{self, layout::TyAndLayout, List, TyCtxt};
11+
use rustc_span::Symbol;
1112
use rustc_target::abi::{Align, FieldsShape, LayoutOf, Size, Variants};
1213
use rustc_target::spec::abi::Abi;
1314

@@ -677,6 +678,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
677678
throw_unsup_format!("{}", error_msg.as_ref());
678679
}
679680
}
681+
682+
fn check_abi_and_shim_symbol_clash(
683+
&mut self,
684+
abi: Abi,
685+
exp_abi: Abi,
686+
link_name: Symbol,
687+
) -> InterpResult<'tcx, ()> {
688+
self.check_abi(abi, exp_abi)?;
689+
if let Some(body) = self.eval_context_mut().lookup_exported_symbol(link_name)? {
690+
throw_machine_stop!(TerminationInfo::SymbolShimClashing {
691+
link_name,
692+
span: body.span.data(),
693+
})
694+
}
695+
Ok(())
696+
}
697+
698+
fn check_shim<'a, const N: usize>(
699+
&mut self,
700+
abi: Abi,
701+
exp_abi: Abi,
702+
link_name: Symbol,
703+
args: &'a [OpTy<'tcx, Tag>],
704+
) -> InterpResult<'tcx, &'a [OpTy<'tcx, Tag>; N]>
705+
where
706+
&'a [OpTy<'tcx, Tag>; N]: TryFrom<&'a [OpTy<'tcx, Tag>]>,
707+
{
708+
self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
709+
check_arg_count(args)
710+
}
680711
}
681712

682713
/// Check that the number of args is what we expect.

src/machine.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ pub struct Evaluator<'mir, 'tcx> {
297297
string_cache: FxHashMap<String, measureme::StringId>,
298298

299299
/// Cache of `Instance` exported under the given `Symbol` name.
300-
pub(crate) exported_symbols_cache: FxHashMap<Symbol, Instance<'tcx>>,
300+
/// `None` means no `Instance` exported under the given name is found.
301+
pub(crate) exported_symbols_cache: FxHashMap<Symbol, Option<Instance<'tcx>>>,
301302

302303
/// Whether to raise a panic in the context of the evaluated process when unsupported
303304
/// functionality is encountered. If `false`, an error is propagated in the Miri application context

src/shims/backtrace.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
use crate::rustc_target::abi::LayoutOf as _;
22
use crate::*;
3-
use helpers::check_arg_count;
43
use rustc_ast::ast::Mutability;
54
use rustc_middle::ty::{self, TypeAndMut};
6-
use rustc_span::BytePos;
7-
use rustc_target::abi::Size;
5+
use rustc_span::{BytePos, Symbol};
6+
use rustc_target::{abi::Size, spec::abi::Abi};
87
use std::convert::TryInto as _;
98

109
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
1110
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
1211
fn handle_miri_get_backtrace(
1312
&mut self,
13+
abi: Abi,
14+
link_name: Symbol,
1415
args: &[OpTy<'tcx, Tag>],
1516
dest: &PlaceTy<'tcx, Tag>,
1617
) -> InterpResult<'tcx> {
1718
let this = self.eval_context_mut();
1819
let tcx = this.tcx;
19-
let &[ref flags] = check_arg_count(args)?;
20+
let &[ref flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
2021

2122
let flags = this.read_scalar(flags)?.to_u64()?;
2223
if flags != 0 {
@@ -71,12 +72,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7172

7273
fn handle_miri_resolve_frame(
7374
&mut self,
75+
abi: Abi,
76+
link_name: Symbol,
7477
args: &[OpTy<'tcx, Tag>],
7578
dest: &PlaceTy<'tcx, Tag>,
7679
) -> InterpResult<'tcx> {
7780
let this = self.eval_context_mut();
7881
let tcx = this.tcx;
79-
let &[ref ptr, ref flags] = check_arg_count(args)?;
82+
let &[ref ptr, ref flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
8083

8184
let flags = this.read_scalar(flags)?.to_u64()?;
8285
if flags != 0 {

0 commit comments

Comments
 (0)