Skip to content

Commit b3be537

Browse files
committed
escape symbol names in global asm
1 parent c4dc073 commit b3be537

File tree

3 files changed

+89
-3
lines changed

3 files changed

+89
-3
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
399399
for piece in template {
400400
match *piece {
401401
InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s),
402-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
402+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
403403
match operands[operand_idx] {
404404
GlobalAsmOperandRef::Const { ref string } => {
405405
// Const operands get injected directly into the
@@ -414,7 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
414414
llvm::LLVMRustGetMangledName(llval, s);
415415
})
416416
.expect("symbol is not valid UTF-8");
417-
template_str.push_str(&symbol);
417+
template_str.push_str(&escape_symbol_name(self, symbol, span));
418418
}
419419
GlobalAsmOperandRef::SymStatic { def_id } => {
420420
let llval = self
@@ -428,7 +428,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
428428
llvm::LLVMRustGetMangledName(llval, s);
429429
})
430430
.expect("symbol is not valid UTF-8");
431-
template_str.push_str(&symbol);
431+
template_str.push_str(&escape_symbol_name(self, symbol, span));
432432
}
433433
}
434434
}
@@ -1390,3 +1390,42 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
13901390
_ => layout.llvm_type(cx),
13911391
}
13921392
}
1393+
1394+
fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String {
1395+
use rustc_target::spec::{Arch, BinaryFormat};
1396+
if !symbol.is_empty()
1397+
&& symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.'))
1398+
{
1399+
return symbol;
1400+
}
1401+
if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff {
1402+
cx.tcx.sess.dcx().span_fatal(
1403+
span,
1404+
format!(
1405+
"symbol escaping is not supported for the binary format {}",
1406+
cx.tcx.sess.target.binary_format
1407+
),
1408+
);
1409+
}
1410+
if matches!(cx.tcx.sess.target.arch, Arch::Nvptx64) {
1411+
cx.tcx.sess.dcx().span_fatal(
1412+
span,
1413+
format!(
1414+
"symbol escaping is not supported for the architecture {}",
1415+
cx.tcx.sess.target.arch
1416+
),
1417+
);
1418+
}
1419+
let mut escaped_symbol = String::new();
1420+
escaped_symbol.push('\"');
1421+
for c in symbol.chars() {
1422+
match c {
1423+
'\n' => escaped_symbol.push_str("\\\n"),
1424+
'"' => escaped_symbol.push_str("\\\""),
1425+
'\\' => escaped_symbol.push_str("\\\\"),
1426+
c => escaped_symbol.push(c),
1427+
}
1428+
}
1429+
escaped_symbol.push('\"');
1430+
escaped_symbol
1431+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ run-pass
2+
//@ only-x86_64-unknown-linux-gnu
3+
4+
// https://github.com/rust-lang/rust/issues/151950
5+
6+
unsafe extern "C" {
7+
#[link_name = "exit@GLIBC_2.2.5"]
8+
safe fn exit(status: i32) -> !;
9+
safe fn my_exit(status: i32) -> !;
10+
}
11+
12+
core::arch::global_asm!(".global my_exit", "my_exit:", "jmp {}", sym exit);
13+
14+
fn main() {
15+
my_exit(0);
16+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ build-fail
2+
//@ only-x86_64-unknown-linux-gnu
3+
//@ dont-check-compiler-stderr
4+
//@ dont-check-compiler-stdout
5+
6+
// https://github.com/rust-lang/rust/issues/151950
7+
8+
unsafe extern "C" {
9+
#[link_name = "memset]; mov eax, 1; #"]
10+
unsafe fn inject();
11+
}
12+
13+
#[unsafe(export_name = "memset]; mov eax, 1; #")]
14+
extern "C" fn inject_() {}
15+
16+
#[unsafe(naked)]
17+
extern "C" fn print_0() -> usize {
18+
core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject)
19+
}
20+
21+
#[unsafe(naked)]
22+
extern "C" fn print_1() -> usize {
23+
core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject_)
24+
}
25+
26+
fn main() {
27+
dbg!(print_0());
28+
dbg!(print_1());
29+
}
30+
31+
//~? ERROR linking

0 commit comments

Comments
 (0)