aboutsummaryrefslogtreecommitdiff
blob: e8fbf473b8ab279820e5377738d8453ada17a602 (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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
BEGIN {
	split(" " SYMBOLS_LIST, SYMBOLS);
}

/^  OS\/ABI:/ {
	ABI = $NF
}

{
	# Unstripped libc's have '.symtab' section as well, and
	# we should stop processing when we hit that
	if ($0 ~ "^Symbol (.*)table '.symtab'")
		nextfile;

	for (x in SYMBOLS) {
		sym_regex = "^" SYMBOLS[x] "(@|$)";
		# On x86, x86_64 and others, $8 is the symbol name, but on
		# alpha, its $10, so rather use $NF, as it should be the
		# last field
		if ($NF ~ sym_regex) {
			split($NF, symbol_array, /@|@@/);

			# Don't add local symbols of versioned libc's
			if (VERSIONED_LIBC && !symbol_array[2])
				continue;

			# Handle non-versioned libc's like uClibc ...
			if (!symbol_array[2])
				symbol_array[2] = "";

			# We have a versioned libc
			if (symbol_array[2] && !VERSIONED_LIBC)
				VERSIONED_LIBC = 1;

			ADD = 1;
			# Check that we do not add duplicates
			for (y in PROCESSED_SYMBOLS) {
				if (y == $NF) {
					ADD = 0;
					break;
				}
			}

			if (ADD) {
				SYMBOL_LIST[symbol_array[2]] = SYMBOL_LIST[symbol_array[2]] " " symbol_array[1];
				PROCESSED_SYMBOLS[$NF] = $NF;
			}
		}

		sym_regex = "^__" SYMBOLS[x] "(@@|$)";
		if (($5 == "WEAK") && ($NF ~ sym_regex)) {
			split($NF, symbol_array, /@@/);

			# Don't add local symbols of versioned libc's
			if (VERSIONED_LIBC && !symbol_array[2])
				continue;

			# Blacklist __getcwd on FreeBSD
			# Unleashed - May 2006
			if ((symbol_array[1] == "__getcwd") && (ABI == "FreeBSD"))
				continue;

			# Handle non-versioned libc's like uClibc ...
			if (!symbol_array[2])
				symbol_array[2] = "";

			# We have a versioned libc
			if (symbol_array[2] && !VERSIONED_LIBC)
				VERSIONED_LIBC = 1;

			ADD = 1;
			# Check that we do not add duplicates
			for (y in PROCESSED_SYMBOLS) {
				if (y == $NF) {
					ADD = 0;
					break;
				}
			}

			if (ADD) {
				SYMBOL_LIST[symbol_array[2]] = SYMBOL_LIST[symbol_array[2]] " " symbol_array[1];
				PROCESSED_SYMBOLS[$NF] = $NF;
			}
		}
	}
}

END {
	COUNT = 0;
	delete VERSION_LIST
	for (sym_version in SYMBOL_LIST)
		if (sym_version)
			VERSION_LIST[COUNT++] = sym_version;

	# We need the symbol versions sorted alphabetically ...
	if (COUNT)
		asort(VERSION_LIST);
	else
		# Handle non-versioned libc's like uClibc ...
		COUNT = 1;

	for (i = 1; i <= COUNT; ++i) {
		if (VERSION_LIST[i]) {
			sym_version = VERSION_LIST[i];
			printf("%s {\n", sym_version);
		} else {
			# Handle non-versioned libc's like uClibc ...
			sym_version = "";
			printf("{\n");
		}

		printf("  global:\n");

		split(SYMBOL_LIST[sym_version], sym_names);

		for (x in sym_names) {
			printf("    %s;\n", sym_names[x]);
		}

		if (!old_sym_version) {
			printf("  local:\n");
			printf("    *;\n");
			printf("};\n");
		} else {
			printf("} %s;\n", old_sym_version);
		}

		old_sym_version = sym_version;
	}
}