about summary refs log tree commit diff
path: root/tests/run-make/libstd-no-protected/rmake.rs
blob: 4091406d46e29880f8c244db2a0ce1ad6f8899fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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;
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);
}