Skip to content

Commit 066c9e1

Browse files
committed
Move shared code to rustc_sanitizers crate and reorg tests
1 parent 17ae239 commit 066c9e1

30 files changed

Lines changed: 236 additions & 146 deletions

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4731,6 +4731,7 @@ name = "rustc_sanitizers"
47314731
version = "0.0.0"
47324732
dependencies = [
47334733
"bitflags",
4734+
"libc",
47344735
"rustc_abi",
47354736
"rustc_data_structures",
47364737
"rustc_hir",

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_middle::middle::codegen_fn_attrs::{
77
TargetFeature,
88
};
99
use rustc_middle::ty::{self, Instance, TyCtxt};
10+
use rustc_sanitizers::ignorelist::SanitizerIgnoreList;
1011
use rustc_session::config::{
1112
BranchProtection, FunctionReturn, InstrumentMcount, InstrumentMcountOpts, OptLevel, PAuthKey,
1213
PacRet,
@@ -476,7 +477,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
476477
llfn: &'ll Value,
477478
codegen_fn_attrs: &CodegenFnAttrs,
478479
instance: Option<ty::Instance<'tcx>>,
479-
sanitizer_ignorelist: Option<&crate::llvm::SanitizerIgnoreList>,
480+
sanitizer_ignorelist: Option<&SanitizerIgnoreList>,
480481
) {
481482
let sess = tcx.sess;
482483
let mut to_add = SmallVec::<[_; 16]>::new();
@@ -541,59 +542,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
541542
let mut enabled = tcx.sess.sanitizers() - codegen_fn_attrs.sanitizers.disabled;
542543
if let Some(ignorelist) = sanitizer_ignorelist {
543544
if let Some(instance) = instance {
544-
let sym_name = tcx.symbol_name(instance).name;
545-
let span = tcx.def_span(instance.def_id());
546-
let source_map = tcx.sess.source_map();
547-
let filename =
548-
source_map.span_to_filename(span).prefer_local_unconditionally().to_string();
549-
550-
let mainfile = tcx
551-
.sess
552-
.local_crate_source_file()
553-
.and_then(|path| path.local_path().map(|p| p.display().to_string()))
554-
.unwrap_or_default();
555-
556-
let demangled = rustc_middle::ty::print::with_no_trimmed_paths!(
557-
tcx.def_path_str(instance.def_id())
558-
);
559-
let is_ignored = |section: &std::ffi::CStr| -> bool {
560-
ignorelist.contains_prefix(section, c"fun", sym_name)
561-
|| ignorelist.contains_prefix(section, c"fun", &demangled)
562-
|| ignorelist.contains_prefix(section, c"src", &filename)
563-
|| (!mainfile.is_empty()
564-
&& ignorelist.contains_prefix(section, c"mainfile", &mainfile))
565-
};
566-
567-
let ignore_address = is_ignored(c"address");
568-
let ignore_kernel_address = ignore_address || is_ignored(c"kernel-address");
569-
let ignore_hwaddress = is_ignored(c"hwaddress");
570-
let ignore_kernel_hwaddress = ignore_hwaddress || is_ignored(c"kernel-hwaddress");
571-
572-
if enabled.contains(SanitizerSet::ADDRESS) && ignore_address {
573-
enabled.remove(SanitizerSet::ADDRESS);
574-
}
575-
if enabled.contains(SanitizerSet::KERNELADDRESS) && ignore_kernel_address {
576-
enabled.remove(SanitizerSet::KERNELADDRESS);
577-
}
578-
if enabled.contains(SanitizerSet::MEMORY) && is_ignored(c"memory") {
579-
enabled.remove(SanitizerSet::MEMORY);
580-
}
581-
if enabled.contains(SanitizerSet::THREAD) && is_ignored(c"thread") {
582-
enabled.remove(SanitizerSet::THREAD);
583-
}
584-
if enabled.contains(SanitizerSet::HWADDRESS) && ignore_hwaddress {
585-
enabled.remove(SanitizerSet::HWADDRESS);
586-
}
587-
if enabled.contains(SanitizerSet::KERNELHWADDRESS) && ignore_kernel_hwaddress {
588-
enabled.remove(SanitizerSet::KERNELHWADDRESS);
589-
}
590-
if enabled.contains(SanitizerSet::SAFESTACK) && is_ignored(c"safestack") {
591-
enabled.remove(SanitizerSet::SAFESTACK);
592-
}
593-
if is_ignored(c"cfi") {
545+
let result = ignorelist.filter_instance_sanitizers(tcx, instance, enabled);
546+
enabled = result.enabled;
547+
if result.ignore_cfi {
594548
to_add.push(llvm::CreateAttrString(cx.llcx, "no-sanitize-cfi"));
595549
}
596-
if is_ignored(c"kcfi") {
550+
if result.ignore_kcfi {
597551
to_add.push(llvm::CreateAttrString(cx.llcx, "no-sanitize-kcfi"));
598552
}
599553
}

compiler/rustc_codegen_llvm/src/base.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,12 @@ pub(crate) fn compile_codegen_unit(
129129
if let Some(entry) =
130130
maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx, cx.codegen_unit)
131131
{
132-
let mut attrs = attributes::sanitize_attrs(&cx, tcx, SanitizerFnAttrs::default(), tcx.sess.sanitizers());
132+
let mut attrs = attributes::sanitize_attrs(
133+
&cx,
134+
tcx,
135+
SanitizerFnAttrs::default(),
136+
tcx.sess.sanitizers(),
137+
);
133138
// When pointer authentication is enabled, ensure that the ptrauth-* attributes are
134139
// also attached to the entry wrapper.
135140
//

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use rustc_hir::def::DefKind;
1515
use rustc_hir::def_id::DefId;
1616
use rustc_middle::bug;
1717
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
18-
use rustc_middle::ty::{self, Ty, Instance, TyCtxt};
19-
use rustc_session::{PointerAuthAddressDiscriminator, PointerAuthSchema, cstore::DllImport};
18+
use rustc_middle::ty::{Instance, TyCtxt};
19+
use rustc_session::{PointerAuthAddressDiscriminator, PointerAuthSchema};
2020
use tracing::debug;
2121

2222
use crate::consts::{IsInitOrFini, IsStatic, const_alloc_to_llvm};
@@ -535,17 +535,3 @@ impl AsCCharPtr for [u8] {
535535
self.as_ptr().cast()
536536
}
537537
}
538-
539-
pub(crate) fn type_name_for_ignore_list<'tcx>(
540-
tcx: TyCtxt<'tcx>,
541-
fn_abi: &rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>,
542-
) -> String {
543-
let inputs: Vec<_> = fn_abi.args.iter().map(|arg| arg.layout.ty).collect();
544-
let output = fn_abi.ret.layout.ty;
545-
let mut fn_sig_kind = ty::FnSigKind::default();
546-
fn_sig_kind = fn_sig_kind.set_safety(rustc_hir::Safety::Safe);
547-
fn_sig_kind = fn_sig_kind.set_c_variadic(fn_abi.c_variadic);
548-
let fn_sig = tcx.mk_fn_sig(inputs, output, fn_sig_kind);
549-
let fn_ptr = Ty::new_fn_ptr(tcx, ty::Binder::dummy(fn_sig));
550-
ty::print::with_no_trimmed_paths!(fn_ptr.to_string())
551-
}

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_middle::ty::layout::{
2020
};
2121
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
2222
use rustc_middle::{bug, span_bug};
23+
use rustc_sanitizers::ignorelist::{SanitizerIgnoreList, type_name_for_ignore_list};
2324
use rustc_session::config::{
2425
BranchProtection, CFGuard, CFProtection, DebugInfo, FunctionReturn, PAuthKey, PacRet,
2526
};
@@ -133,7 +134,7 @@ pub(crate) struct FullCx<'ll, 'tcx> {
133134
/// Extra per-CGU codegen state needed when coverage instrumentation is enabled.
134135
pub coverage_cx: Option<coverageinfo::CguCoverageContext<'ll, 'tcx>>,
135136
pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>,
136-
pub sanitizer_ignorelist: Option<crate::llvm::SanitizerIgnoreList>,
137+
pub sanitizer_ignorelist: Option<SanitizerIgnoreList>,
137138

138139
eh_personality: Cell<Option<&'ll Value>>,
139140
pub rust_try_fn: Cell<Option<(&'ll Type, &'ll Value)>>,
@@ -689,9 +690,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
689690
for path in &tcx.sess.opts.unstable_opts.sanitizer_ignorelist {
690691
let _ = tcx.sess.source_map().load_file(std::path::Path::new(path));
691692
}
692-
match crate::llvm::SanitizerIgnoreList::new(
693-
&tcx.sess.opts.unstable_opts.sanitizer_ignorelist,
694-
) {
693+
match SanitizerIgnoreList::new(&tcx.sess.opts.unstable_opts.sanitizer_ignorelist) {
695694
Ok(list) => Some(list),
696695
Err(err) => {
697696
tcx.dcx().fatal(format!("failed to parse sanitizer ignorelist: {}", err));
@@ -867,7 +866,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
867866
fn_abi: &rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>,
868867
) -> bool {
869868
self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| {
870-
let type_name = crate::common::type_name_for_ignore_list(self.tcx, fn_abi);
869+
let type_name = type_name_for_ignore_list(self.tcx, fn_abi);
871870
ignorelist.contains_prefix(sanitizer, c"type", &type_name)
872871
})
873872
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,19 +2463,6 @@ unsafe extern "C" {
24632463
pub(crate) fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
24642464
pub(crate) fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
24652465

2466-
pub(crate) fn LLVMRustSpecialCaseListCreate(
2467-
Paths: *const *const c_char,
2468-
NumPaths: size_t,
2469-
ErrorMsg: &RustString,
2470-
) -> *mut Opaque;
2471-
pub(crate) fn LLVMRustSpecialCaseListDestroy(List: *mut Opaque);
2472-
pub(crate) fn LLVMRustSpecialCaseListContainsPrefix(
2473-
List: *const Opaque,
2474-
Section: *const c_char,
2475-
Prefix: *const c_char,
2476-
Query: *const c_char,
2477-
) -> bool;
2478-
24792466
pub(crate) fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
24802467

24812468
pub(crate) fn LLVMRustUnpackOptimizationDiagnostic<'a>(

compiler/rustc_codegen_llvm/src/llvm/mod.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -375,52 +375,6 @@ pub(crate) fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec<u8> {
375375
RustString::build_byte_buffer(f)
376376
}
377377

378-
pub(crate) struct SanitizerIgnoreList {
379-
inner: *mut ffi::Opaque,
380-
}
381-
382-
impl SanitizerIgnoreList {
383-
pub(crate) fn new(paths: &[String]) -> Result<Self, String> {
384-
use std::ffi::CString;
385-
let c_paths: Vec<CString> =
386-
paths.iter().map(|p| CString::new(p.as_str()).unwrap()).collect();
387-
let c_ptrs: Vec<*const libc::c_char> = c_paths.iter().map(|c| c.as_ptr()).collect();
388-
389-
let mut inner = std::ptr::null_mut();
390-
let err = build_string(|err| unsafe {
391-
inner = ffi::LLVMRustSpecialCaseListCreate(c_ptrs.as_ptr(), c_ptrs.len(), err);
392-
});
393-
394-
let err = err.unwrap_or_else(|e| format!("utf8 error: {}", e));
395-
if inner.is_null() { Err(err) } else { Ok(Self { inner }) }
396-
}
397-
398-
pub(crate) fn contains_prefix(
399-
&self,
400-
section: &std::ffi::CStr,
401-
prefix: &std::ffi::CStr,
402-
query: &str,
403-
) -> bool {
404-
let query = std::ffi::CString::new(query).unwrap();
405-
unsafe {
406-
ffi::LLVMRustSpecialCaseListContainsPrefix(
407-
self.inner,
408-
section.as_ptr(),
409-
prefix.as_ptr(),
410-
query.as_ptr(),
411-
)
412-
}
413-
}
414-
}
415-
416-
impl Drop for SanitizerIgnoreList {
417-
fn drop(&mut self) {
418-
unsafe {
419-
ffi::LLVMRustSpecialCaseListDestroy(self.inner);
420-
}
421-
}
422-
}
423-
424378
pub(crate) fn twine_to_string(tr: &Twine) -> String {
425379
unsafe {
426380
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")

compiler/rustc_sanitizers/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2024"
66
[dependencies]
77
# tidy-alphabetical-start
88
bitflags = "2.5.0"
9+
libc = "0.2"
910
rustc_abi = { path = "../rustc_abi" }
1011
rustc_data_structures = { path = "../rustc_data_structures" }
1112
rustc_hir = { path = "../rustc_hir" }
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use std::cell::RefCell;
2+
use std::ffi::c_char;
3+
use std::ptr;
4+
use std::string::FromUtf8Error;
5+
6+
use libc::size_t;
7+
8+
unsafe extern "C" {
9+
pub(crate) type Opaque;
10+
/// Opaque type that allows C++ code to write bytes to a Rust-side buffer,
11+
/// in conjunction with `RawRustStringOstream`. Use this as `&RustString`
12+
/// (Rust) and `RustStringRef` (C++) in FFI signatures.
13+
pub(crate) type RustString;
14+
15+
pub(crate) fn LLVMRustSpecialCaseListCreate(
16+
Paths: *const *const c_char,
17+
NumPaths: size_t,
18+
ErrorMsg: &RustString,
19+
) -> *mut Opaque;
20+
21+
pub(crate) fn LLVMRustSpecialCaseListDestroy(List: *mut Opaque);
22+
pub(crate) fn LLVMRustSpecialCaseListContainsPrefix(
23+
List: *const Opaque,
24+
Section: *const c_char,
25+
Prefix: *const c_char,
26+
Query: *const c_char,
27+
) -> bool;
28+
}
29+
30+
/// Underlying implementation of [`RustString`].
31+
///
32+
/// Having two separate types makes it possible to use the opaque [`RustString`]
33+
/// in FFI signatures without `improper_ctypes` warnings. This is a workaround
34+
/// for the fact that there is no way to opt out of `improper_ctypes` when
35+
/// _declaring_ a type (as opposed to using that type).
36+
#[derive(Default)]
37+
struct RustStringInner {
38+
bytes: RefCell<Vec<u8>>,
39+
}
40+
41+
impl RustStringInner {
42+
fn as_opaque(&self) -> &RustString {
43+
let ptr: *const RustStringInner = ptr::from_ref(self);
44+
// We can't use `ptr::cast` here because extern types are `!Sized`.
45+
let ptr = ptr as *const RustString;
46+
unsafe { &*ptr }
47+
}
48+
49+
fn into_inner(self) -> Vec<u8> {
50+
self.bytes.into_inner()
51+
}
52+
}
53+
54+
impl RustString {
55+
pub(crate) fn build_byte_buffer(closure: impl FnOnce(&Self)) -> Vec<u8> {
56+
let buf = RustStringInner::default();
57+
closure(buf.as_opaque());
58+
buf.into_inner()
59+
}
60+
}
61+
62+
pub(crate) fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
63+
String::from_utf8(RustString::build_byte_buffer(f))
64+
}

0 commit comments

Comments
 (0)