Fix prelink issue breaking .bss
The reason prelink seemed to break relocations in .bss is because the .note.rustc section happened to be placed in front of .bss. Using objcopy to strip the note renumbered the sections and the symbols in the .dynsym section were pointing to the wrong section index, but only for .bss. Prelink would skip updating these dyn entries because it thought they were pointing to a section that didn't get relocated, like .comment. In some cases the GOT was actually prelinked correctly, but the dynamic linker at run time would modify it to point at the non-prelinked address. Removing the SHF_ALLOC flag from the section causes it to be placed at the end of the executable where it can be safely removed. This is still a hack to the compiler because I couldn't find any way to get the section attributes to be correct using the high-level LLVM interface.
This commit is contained in:
committed by
Steven Walter
parent
ba3486997a
commit
0ade0cc790
+158
@@ -0,0 +1,158 @@
|
||||
From 1bd3ab55ce24b2a54e021ba471a5f934b3b9ad6b Mon Sep 17 00:00:00 2001
|
||||
From: Steven Walter <swalter@lexmark.com>
|
||||
Date: Tue, 7 Jul 2015 16:49:44 -0400
|
||||
Subject: [PATCH 10/12] rustc_trans: make .note.rustc look more like debug info
|
||||
|
||||
Mark the global variable as const and private so the resulting section
|
||||
is not flagged as writable and to avoid putting an unnecessary symbol in
|
||||
the dynamic table of shared objects.
|
||||
|
||||
Unfortunately there doesn't seem to be a way to avoid the section being
|
||||
marked SHF_ALLOC when declared as a variable in LLVM. Hack around that
|
||||
by using objcopy to clear the flags on the section before the final
|
||||
link.
|
||||
|
||||
This places the section at the end of the executable so it can be
|
||||
stripped later without rearranging important code/data sections.
|
||||
---
|
||||
mk/platform.mk | 1 +
|
||||
src/librustc/session/config.rs | 2 ++
|
||||
src/librustc_back/target/mod.rs | 4 ++++
|
||||
src/librustc_trans/back/link.rs | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
src/librustc_trans/trans/base.rs | 3 +++
|
||||
5 files changed, 48 insertions(+)
|
||||
|
||||
diff --git a/mk/platform.mk b/mk/platform.mk
|
||||
index 0c90632..4681783 100644
|
||||
--- a/mk/platform.mk
|
||||
+++ b/mk/platform.mk
|
||||
@@ -181,6 +181,7 @@ define CFG_MAKE_TOOLCHAIN
|
||||
AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
|
||||
LINK_$(1)=$(CROSS_PREFIX_$(1))$(LINK_$(1))
|
||||
RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(LINK_$(1))) \
|
||||
+ -C objcopy=$$(call FIND_COMPILER,$$(OBJCOPY_$(1))) \
|
||||
-C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))
|
||||
|
||||
RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
|
||||
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
|
||||
index ecb38d4..b74b3c4 100644
|
||||
--- a/src/librustc/session/config.rs
|
||||
+++ b/src/librustc/session/config.rs
|
||||
@@ -460,6 +460,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
|
||||
CG_OPTIONS, cg_type_desc, cgsetters,
|
||||
ar: Option<String> = (None, parse_opt_string,
|
||||
"tool to assemble archives with"),
|
||||
+ objcopy: Option<String> = (None, parse_opt_string,
|
||||
+ "system objcopy for manipulating objects"),
|
||||
linker: Option<String> = (None, parse_opt_string,
|
||||
"system linker to link outputs with"),
|
||||
link_args: Option<Vec<String>> = (None, parse_opt_list,
|
||||
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
|
||||
index 3ffa484..d52e67c 100644
|
||||
--- a/src/librustc_back/target/mod.rs
|
||||
+++ b/src/librustc_back/target/mod.rs
|
||||
@@ -110,6 +110,8 @@ pub struct TargetOptions {
|
||||
/// sysroot folder.
|
||||
pub pre_link_objects: Vec<String>,
|
||||
pub post_link_objects: Vec<String>,
|
||||
+ /// Path to objcopy. Defaults to "objcopy".
|
||||
+ pub objcopy: String,
|
||||
/// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
|
||||
/// to "default".
|
||||
pub cpu: String,
|
||||
@@ -198,6 +200,7 @@ impl Default for TargetOptions {
|
||||
ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(),
|
||||
pre_link_args: Vec::new(),
|
||||
post_link_args: Vec::new(),
|
||||
+ objcopy: "objcopy".to_string(),
|
||||
cpu: "generic".to_string(),
|
||||
features: "".to_string(),
|
||||
dynamic_linking: false,
|
||||
@@ -314,6 +317,7 @@ impl Target {
|
||||
key!(cpu);
|
||||
key!(ar);
|
||||
key!(linker);
|
||||
+ key!(objcopy);
|
||||
key!(relocation_model);
|
||||
key!(code_model);
|
||||
key!(dll_prefix);
|
||||
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
|
||||
index 2a87cd7..53fa913 100644
|
||||
--- a/src/librustc_trans/back/link.rs
|
||||
+++ b/src/librustc_trans/back/link.rs
|
||||
@@ -393,6 +393,13 @@ fn command_path(sess: &Session) -> OsString {
|
||||
env::join_paths(new_path).unwrap()
|
||||
}
|
||||
|
||||
+pub fn get_objcopy_prog(sess: &Session) -> String {
|
||||
+ match sess.opts.cg.objcopy {
|
||||
+ Some(ref objcopy) => return objcopy.to_string(),
|
||||
+ None => sess.target.target.options.objcopy.clone(),
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
pub fn remove(sess: &Session, path: &Path) {
|
||||
match fs::remove_file(path) {
|
||||
Ok(..) => {}
|
||||
@@ -919,6 +926,34 @@ fn link_natively(sess: &Session, dylib: bool,
|
||||
}
|
||||
}
|
||||
|
||||
+fn fix_meta_section_attributes(sess: &Session, meta_name: &PathBuf) {
|
||||
+ // First, fix up the note section attributes. We want the SHF_ALLOC and
|
||||
+ // SHF_WRITE flags to be unset so the section will get placed near the
|
||||
+ // end along with the debug info. This allows the section to be
|
||||
+ // stripped later without renumbering important sections that
|
||||
+ // contain code and data.
|
||||
+ let objcopy = get_objcopy_prog(sess);
|
||||
+ let mut o_cmd = Command::new(&objcopy);
|
||||
+ o_cmd.arg("--rename-section")
|
||||
+ .arg(".note.rustc=.note.rustc,contents,noload,readonly")
|
||||
+ .arg(&meta_name);
|
||||
+ // Invoke objcopy
|
||||
+ info!("{:?}", o_cmd);
|
||||
+ match o_cmd.status() {
|
||||
+ Ok(exitstatus) => {
|
||||
+ if !exitstatus.success() {
|
||||
+ sess.err(&format!("objcopy failed with exit code {:?}", exitstatus.code()));
|
||||
+ sess.note(&format!("{:?}", &o_cmd));
|
||||
+ }
|
||||
+ },
|
||||
+ Err(exitstatus) => {
|
||||
+ sess.err(&format!("objcopy failed: {}", exitstatus));
|
||||
+ sess.note(&format!("{:?}", &o_cmd));
|
||||
+ }
|
||||
+ }
|
||||
+ sess.abort_if_errors();
|
||||
+}
|
||||
+
|
||||
fn link_args(cmd: &mut Linker,
|
||||
sess: &Session,
|
||||
dylib: bool,
|
||||
@@ -951,6 +986,9 @@ fn link_args(cmd: &mut Linker,
|
||||
// executable. This metadata is in a separate object file from the main
|
||||
// object file, so we link that in here.
|
||||
if dylib {
|
||||
+ let meta_name = outputs.with_extension("metadata.o");
|
||||
+
|
||||
+ fix_meta_section_attributes(sess, &meta_name);
|
||||
cmd.add_object(&outputs.with_extension("metadata.o"));
|
||||
}
|
||||
|
||||
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
|
||||
index 14fea61..df019f7 100644
|
||||
--- a/src/librustc_trans/trans/base.rs
|
||||
+++ b/src/librustc_trans/trans/base.rs
|
||||
@@ -2560,6 +2560,9 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate,
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
+ llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
+ llvm::LLVMSetUnnamedAddr(llglobal, llvm::True);
|
||||
+ llvm::SetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
let name = loader::meta_section_name(&cx.sess().target.target);
|
||||
let name = CString::new(name).unwrap();
|
||||
llvm::LLVMSetSection(llglobal, name.as_ptr())
|
||||
--
|
||||
1.9.1
|
||||
|
||||
@@ -152,6 +152,7 @@ def rust_gen_target(d, thing, wd):
|
||||
prefix = d.getVar('{}_PREFIX'.format(thing), True)
|
||||
ccache = d.getVar('CCACHE', True)
|
||||
linker = "{}{}gcc".format(ccache, prefix)
|
||||
objcopy = "{}objcopy".format(prefix)
|
||||
features = d.getVarFlag('FEATURES', arch, True) or ""
|
||||
|
||||
pre_link_args = pre_link_args_for(d, thing, arch)
|
||||
@@ -166,6 +167,7 @@ def rust_gen_target(d, thing, wd):
|
||||
"arch": "{}",
|
||||
"os": "linux",
|
||||
"linker": "{}",
|
||||
"objcopy": "{}",
|
||||
"features": "{}",
|
||||
"dynamic-linking": true,
|
||||
"executables": true,
|
||||
@@ -183,6 +185,7 @@ def rust_gen_target(d, thing, wd):
|
||||
target_pointer_width,
|
||||
arch_to_rust_target_arch(arch),
|
||||
linker,
|
||||
objcopy,
|
||||
features,
|
||||
as_json(pre_link_args),
|
||||
as_json(post_link_args),
|
||||
@@ -258,6 +261,9 @@ def rust_gen_mk_cfg(d, thing):
|
||||
], stdout=o, stdin=i)
|
||||
if r:
|
||||
raise Exception
|
||||
o.write("OBJCOPY_{} := {}objcopy\n".format(sys, prefix))
|
||||
o.close()
|
||||
i.close()
|
||||
|
||||
python do_rust_arch_fixup () {
|
||||
for thing in ['BUILD', 'HOST', 'TARGET']:
|
||||
|
||||
@@ -14,6 +14,7 @@ SRC_URI_append = "\
|
||||
file://${PP}/0007-mk-install-use-disable-rewrite-paths.patch \
|
||||
file://${PP}/0008-install-disable-ldconfig.patch \
|
||||
file://${PP}/0009-Remove-crate-metadata-from-symbol-hashing.patch \
|
||||
file://${PP}/0010-rustc_trans-make-.note.rustc-look-more-like-debug-in.patch \
|
||||
\
|
||||
file://rust-installer/0001-add-option-to-disable-rewriting-of-install-paths.patch;patchdir=src/rust-installer \
|
||||
"
|
||||
|
||||
Reference in New Issue
Block a user