about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-25 07:01:38 +0100
committerGitHub <noreply@github.com>2024-11-25 07:01:38 +0100
commit4c40119dc4840a1a8015e1f73219ea7ae92b96fe (patch)
treecf099ab571fe4517898be0acce1a947044d5c6c9
parent3f86eddf837191f61ab9ca203b5742278f98d758 (diff)
parentc1285b4fe661798fcc618bdd55a83b0172142f18 (diff)
downloadrust-4c40119dc4840a1a8015e1f73219ea7ae92b96fe.tar.gz
rust-4c40119dc4840a1a8015e1f73219ea7ae92b96fe.zip
Rollup merge of #132432 - davidlattimore:std-interposable, r=Mark-Simulacrum
Add a test to verify that libstd doesn't use protected symbols
-rw-r--r--tests/run-make/libstd-no-protected/rmake.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/run-make/libstd-no-protected/rmake.rs b/tests/run-make/libstd-no-protected/rmake.rs
new file mode 100644
index 00000000000..3bba59a8f4d
--- /dev/null
+++ b/tests/run-make/libstd-no-protected/rmake.rs
@@ -0,0 +1,63 @@
+// If libstd was compiled to use protected symbols, then linking would fail if GNU ld < 2.40 were
+// used. This might not be noticed, since usually we use LLD for linking, so we could end up
+// distributing a version of libstd that would cause link errors for such users.
+
+//@ only-x86_64-unknown-linux-gnu
+
+use run_make_support::object::Endianness;
+use run_make_support::object::read::archive::ArchiveFile;
+use run_make_support::object::read::elf::{FileHeader as _, SectionHeader as _};
+use run_make_support::rfs::{read, read_dir};
+use run_make_support::{has_prefix, has_suffix, object, path, rustc, shallow_find_files, target};
+
+type FileHeader = run_make_support::object::elf::FileHeader64<Endianness>;
+type SymbolTable<'data> = run_make_support::object::read::elf::SymbolTable<'data, FileHeader>;
+
+fn main() {
+    // Find libstd-...rlib
+    let sysroot = rustc().print("sysroot").run().stdout_utf8();
+    let sysroot = sysroot.trim();
+    let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib");
+    let mut libs = shallow_find_files(&target_sysroot, |path| {
+        has_prefix(path, "libstd-") && has_suffix(path, ".rlib")
+    });
+    assert_eq!(libs.len(), 1);
+    let libstd_path = libs.pop().unwrap();
+    let archive_data = read(libstd_path);
+
+    // Parse all the object files within the libstd archive, checking defined symbols.
+    let mut num_protected = 0;
+    let mut num_symbols = 0;
+
+    let archive = ArchiveFile::parse(&*archive_data).unwrap();
+    for member in archive.members() {
+        let member = member.unwrap();
+        if member.name() == b"lib.rmeta" {
+            continue;
+        }
+        let data = member.data(&*archive_data).unwrap();
+
+        let header = FileHeader::parse(data).unwrap();
+        let endian = header.endian().unwrap();
+        let sections = header.sections(endian, data).unwrap();
+
+        for (section_index, section) in sections.enumerate() {
+            if section.sh_type(endian) == object::elf::SHT_SYMTAB {
+                let symbols =
+                    SymbolTable::parse(endian, data, &sections, section_index, section).unwrap();
+                for symbol in symbols.symbols() {
+                    if symbol.st_visibility() == object::elf::STV_PROTECTED {
+                        num_protected += 1;
+                    }
+                    num_symbols += 1;
+                }
+            }
+        }
+    }
+
+    // If there were no symbols at all, then something is wrong with the test.
+    assert_ne!(num_symbols, 0);
+
+    // The purpose of this test - check that no symbols have protected visibility.
+    assert_eq!(num_protected, 0);
+}