Skip to content

Commit fbf9869

Browse files
committed
rustc: Handle some libstd symbole exports better
Right now symbol exports, particularly in a cdylib, are handled by assuming that `pub extern` combined with `#[no_mangle]` means "export this". This isn't actually what we want for some symbols that the standard library uses to implement itself, for example symbols related to allocation. Additionally other special symbols like `rust_eh_personallity` have no need to be exported from cdylib crate types (only needed in dylib crate types). This commit updates how rustc handles these special symbols by adding to the hardcoded logic of symbols like `rust_eh_personallity` but also adding a new attribute, `#[rustc_std_internal_symbol]`, which forces the export level to be considered the same as all other Rust functions instead of looking like a C function. The eventual goal here is to prevent functions like `__rdl_alloc` from showing up as part of a Rust cdylib as it's just an internal implementation detail. This then further allows such symbols to get gc'd by the linker when creating a cdylib.
1 parent 12e6b53 commit fbf9869

File tree

7 files changed

+74
-11
lines changed

7 files changed

+74
-11
lines changed

src/liballoc_jemalloc/lib.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ mod contents {
107107
// ABI
108108

109109
#[no_mangle]
110-
#[linkage = "external"]
110+
#[rustc_std_internal_symbol]
111111
pub unsafe extern fn __rde_alloc(size: usize,
112112
align: usize,
113113
err: *mut u8) -> *mut u8 {
@@ -122,13 +122,13 @@ mod contents {
122122
}
123123

124124
#[no_mangle]
125-
#[linkage = "external"]
125+
#[rustc_std_internal_symbol]
126126
pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
127127
System.oom((*(err as *const AllocErr)).clone())
128128
}
129129

130130
#[no_mangle]
131-
#[linkage = "external"]
131+
#[rustc_std_internal_symbol]
132132
pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
133133
size: usize,
134134
align: usize) {
@@ -137,7 +137,7 @@ mod contents {
137137
}
138138

139139
#[no_mangle]
140-
#[linkage = "external"]
140+
#[rustc_std_internal_symbol]
141141
pub unsafe extern fn __rde_usable_size(layout: *const u8,
142142
min: *mut usize,
143143
max: *mut usize) {
@@ -153,7 +153,7 @@ mod contents {
153153
}
154154

155155
#[no_mangle]
156-
#[linkage = "external"]
156+
#[rustc_std_internal_symbol]
157157
pub unsafe extern fn __rde_realloc(ptr: *mut u8,
158158
_old_size: usize,
159159
old_align: usize,
@@ -177,7 +177,7 @@ mod contents {
177177
}
178178

179179
#[no_mangle]
180-
#[linkage = "external"]
180+
#[rustc_std_internal_symbol]
181181
pub unsafe extern fn __rde_alloc_zeroed(size: usize,
182182
align: usize,
183183
err: *mut u8) -> *mut u8 {
@@ -196,7 +196,7 @@ mod contents {
196196
}
197197

198198
#[no_mangle]
199-
#[linkage = "external"]
199+
#[rustc_std_internal_symbol]
200200
pub unsafe extern fn __rde_alloc_excess(size: usize,
201201
align: usize,
202202
excess: *mut usize,
@@ -210,7 +210,7 @@ mod contents {
210210
}
211211

212212
#[no_mangle]
213-
#[linkage = "external"]
213+
#[rustc_std_internal_symbol]
214214
pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
215215
old_size: usize,
216216
old_align: usize,
@@ -227,7 +227,7 @@ mod contents {
227227
}
228228

229229
#[no_mangle]
230-
#[linkage = "external"]
230+
#[rustc_std_internal_symbol]
231231
pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
232232
old_size: usize,
233233
old_align: usize,
@@ -237,7 +237,7 @@ mod contents {
237237
}
238238

239239
#[no_mangle]
240-
#[linkage = "external"]
240+
#[rustc_std_internal_symbol]
241241
pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
242242
_old_size: usize,
243243
old_align: usize,

src/librustc_allocator/expand.rs

+4
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,13 @@ impl<'a> AllocFnFactory<'a> {
177177

178178
let no_mangle = Symbol::intern("no_mangle");
179179
let no_mangle = self.cx.meta_word(self.span, no_mangle);
180+
181+
let special = Symbol::intern("rustc_std_internal_symbol");
182+
let special = self.cx.meta_word(self.span, special);
180183
vec![
181184
self.cx.attribute(self.span, linkage),
182185
self.cx.attribute(self.span, no_mangle),
186+
self.cx.attribute(self.span, special),
183187
]
184188
}
185189

src/librustc_trans/back/symbol_export.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc::ty::TyCtxt;
2121
use rustc::ty::maps::Providers;
2222
use rustc::util::nodemap::FxHashMap;
2323
use rustc_allocator::ALLOCATOR_METHODS;
24+
use syntax::attr;
2425

2526
pub type ExportedSymbols = FxHashMap<
2627
CrateNum,
@@ -180,7 +181,15 @@ pub fn provide_extern(providers: &mut Providers) {
180181
}
181182

182183
fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
183-
if tcx.contains_extern_indicator(sym_def_id) {
184+
// We export anything that's not mangled at the "C" layer as it probably has
185+
// to do with ABI concerns. We do not, however, apply such treatment to
186+
// special symbols in the standard library for various plumbing between
187+
// core/std/allocators/etc. For example symbols used to hook up allocation
188+
// are not considered for export
189+
let is_extern = tcx.contains_extern_indicator(sym_def_id);
190+
let std_internal = attr::contains_name(&tcx.get_attrs(sym_def_id),
191+
"rustc_std_internal_symbol");
192+
if is_extern && !std_internal {
184193
SymbolExportLevel::C
185194
} else {
186195
SymbolExportLevel::Rust

src/libstd/heap.rs

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub use alloc_system::System;
1717

1818
#[cfg(not(test))]
1919
#[doc(hidden)]
20+
#[allow(unused_attributes)]
2021
pub mod __default_lib_allocator {
2122
use super::{System, Layout, Alloc, AllocErr};
2223
use ptr;
@@ -28,6 +29,7 @@ pub mod __default_lib_allocator {
2829
// ABI
2930

3031
#[no_mangle]
32+
#[rustc_std_internal_symbol]
3133
pub unsafe extern fn __rdl_alloc(size: usize,
3234
align: usize,
3335
err: *mut u8) -> *mut u8 {
@@ -42,18 +44,21 @@ pub mod __default_lib_allocator {
4244
}
4345

4446
#[no_mangle]
47+
#[rustc_std_internal_symbol]
4548
pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
4649
System.oom((*(err as *const AllocErr)).clone())
4750
}
4851

4952
#[no_mangle]
53+
#[rustc_std_internal_symbol]
5054
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
5155
size: usize,
5256
align: usize) {
5357
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
5458
}
5559

5660
#[no_mangle]
61+
#[rustc_std_internal_symbol]
5762
pub unsafe extern fn __rdl_usable_size(layout: *const u8,
5863
min: *mut usize,
5964
max: *mut usize) {
@@ -63,6 +68,7 @@ pub mod __default_lib_allocator {
6368
}
6469

6570
#[no_mangle]
71+
#[rustc_std_internal_symbol]
6672
pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
6773
old_size: usize,
6874
old_align: usize,
@@ -81,6 +87,7 @@ pub mod __default_lib_allocator {
8187
}
8288

8389
#[no_mangle]
90+
#[rustc_std_internal_symbol]
8491
pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
8592
align: usize,
8693
err: *mut u8) -> *mut u8 {
@@ -95,6 +102,7 @@ pub mod __default_lib_allocator {
95102
}
96103

97104
#[no_mangle]
105+
#[rustc_std_internal_symbol]
98106
pub unsafe extern fn __rdl_alloc_excess(size: usize,
99107
align: usize,
100108
excess: *mut usize,
@@ -113,6 +121,7 @@ pub mod __default_lib_allocator {
113121
}
114122

115123
#[no_mangle]
124+
#[rustc_std_internal_symbol]
116125
pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
117126
old_size: usize,
118127
old_align: usize,
@@ -135,6 +144,7 @@ pub mod __default_lib_allocator {
135144
}
136145

137146
#[no_mangle]
147+
#[rustc_std_internal_symbol]
138148
pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
139149
old_size: usize,
140150
old_align: usize,
@@ -149,6 +159,7 @@ pub mod __default_lib_allocator {
149159
}
150160

151161
#[no_mangle]
162+
#[rustc_std_internal_symbol]
152163
pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
153164
old_size: usize,
154165
old_align: usize,

src/libsyntax/feature_gate.rs

+6
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
917917
"allow_fail attribute is currently unstable",
918918
cfg_fn!(allow_fail))),
919919

920+
("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
921+
"rustc_attrs",
922+
"this is an internal attribute that will \
923+
never be stable",
924+
cfg_fn!(rustc_attrs))),
925+
920926
// Crate level attributes
921927
("crate_name", CrateLevel, Ungated),
922928
("crate_type", CrateLevel, Ungated),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Test that allocator-related symbols don't show up as exported from a cdylib as
2+
# they're internal to Rust and not part of the public ABI.
3+
4+
-include ../tools.mk
5+
6+
ifdef IS_MSVC
7+
all:
8+
true
9+
else
10+
all:
11+
$(RUSTC) foo.rs
12+
nm -g "$(call DYLIB,foo)"
13+
nm -g "$(call DYLIB,foo)" | grep -vq __rdl_
14+
nm -g "$(call DYLIB,foo)" | grep -vq __rde_
15+
nm -g "$(call DYLIB,foo)" | grep -vq __rg_
16+
nm -g "$(call DYLIB,foo)" | grep -vq __rust_
17+
endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "cdylib"]
12+
13+
#[no_mangle]
14+
pub extern fn foo() -> u32 {
15+
3
16+
}

0 commit comments

Comments
 (0)