Add a test to verify that libstd doesn't use protected symbols · rust-lang/rust@c1285b4 (original) (raw)

``

1

`+

// If libstd was compiled to use protected symbols, then linking would fail if GNU ld < 2.40 were

`

``

2

`+

// used. This might not be noticed, since usually we use LLD for linking, so we could end up

`

``

3

`+

// distributing a version of libstd that would cause link errors for such users.

`

``

4

+

``

5

`+

//@ only-x86_64-unknown-linux-gnu

`

``

6

+

``

7

`+

use run_make_support::object::Endianness;

`

``

8

`+

use run_make_support::object::read::archive::ArchiveFile;

`

``

9

`+

use run_make_support::object::read:🧝:{FileHeader as _, SectionHeader as _};

`

``

10

`+

use run_make_support::rfs::{read, read_dir};

`

``

11

`+

use run_make_support::{has_prefix, has_suffix, object, path, rustc, shallow_find_files, target};

`

``

12

+

``

13

`+

type FileHeader = run_make_support::object:🧝:FileHeader64;

`

``

14

`+

type SymbolTable<'data> = run_make_support::object::read:🧝:SymbolTable<'data, FileHeader>;

`

``

15

+

``

16

`+

fn main() {

`

``

17

`+

// Find libstd-...rlib

`

``

18

`+

let sysroot = rustc().print("sysroot").run().stdout_utf8();

`

``

19

`+

let sysroot = sysroot.trim();

`

``

20

`+

let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib");

`

``

21

`+

let mut libs = shallow_find_files(&target_sysroot, |path| {

`

``

22

`+

has_prefix(path, "libstd-") && has_suffix(path, ".rlib")

`

``

23

`+

});

`

``

24

`+

assert_eq!(libs.len(), 1);

`

``

25

`+

let libstd_path = libs.pop().unwrap();

`

``

26

`+

let archive_data = read(libstd_path);

`

``

27

+

``

28

`+

// Parse all the object files within the libstd archive, checking defined symbols.

`

``

29

`+

let mut num_protected = 0;

`

``

30

`+

let mut num_symbols = 0;

`

``

31

+

``

32

`+

let archive = ArchiveFile::parse(&*archive_data).unwrap();

`

``

33

`+

for member in archive.members() {

`

``

34

`+

let member = member.unwrap();

`

``

35

`+

if member.name() == b"lib.rmeta" {

`

``

36

`+

continue;

`

``

37

`+

}

`

``

38

`+

let data = member.data(&*archive_data).unwrap();

`

``

39

+

``

40

`+

let header = FileHeader::parse(data).unwrap();

`

``

41

`+

let endian = header.endian().unwrap();

`

``

42

`+

let sections = header.sections(endian, data).unwrap();

`

``

43

+

``

44

`+

for (section_index, section) in sections.enumerate() {

`

``

45

`+

if section.sh_type(endian) == object:🧝:SHT_SYMTAB {

`

``

46

`+

let symbols =

`

``

47

`+

SymbolTable::parse(endian, data, &sections, section_index, section).unwrap();

`

``

48

`+

for symbol in symbols.symbols() {

`

``

49

`+

if symbol.st_visibility() == object:🧝:STV_PROTECTED {

`

``

50

`+

num_protected += 1;

`

``

51

`+

}

`

``

52

`+

num_symbols += 1;

`

``

53

`+

}

`

``

54

`+

}

`

``

55

`+

}

`

``

56

`+

}

`

``

57

+

``

58

`+

// If there were no symbols at all, then something is wrong with the test.

`

``

59

`+

assert_ne!(num_symbols, 0);

`

``

60

+

``

61

`+

// The purpose of this test - check that no symbols have protected visibility.

`

``

62

`+

assert_eq!(num_protected, 0);

`

``

63

`+

}

`