| @@ -1,124 +1,133 @@ | | | @@ -1,124 +1,133 @@ |
1 | # $NetBSD: check-shlibs-macho.awk,v 1.5 2018/05/25 10:57:28 jperkin Exp $ | | 1 | # $NetBSD: check-shlibs-macho.awk,v 1.6 2018/06/07 04:58:46 dbj Exp $ |
2 | | | 2 | |
3 | # | | 3 | # |
4 | # Read a list of potential Mach-O binaries from stdin. | | 4 | # Read a list of potential Mach-O binaries from stdin. |
5 | # For each, check the list of required DSOs and ensure that each of them can | | 5 | # For each, check the list of required DSOs and ensure that each of them can |
6 | # be found correctly, and check that any pkgsrc-installed DSOs belong to a | | 6 | # be found correctly, and check that any pkgsrc-installed DSOs belong to a |
7 | # full dependency. | | 7 | # full dependency. |
8 | # | | 8 | # |
9 | | | 9 | |
10 | function shquote(IN, out) { | | 10 | function shquote(IN, out) { |
11 | out = IN; | | 11 | out = IN; |
12 | gsub("\\\\", "\\\\", out); | | 12 | gsub("\\\\", "\\\\", out); |
13 | gsub("\\\n", "\\n", out); | | 13 | gsub("\\\n", "\\n", out); |
14 | gsub("\\\t", "\\t", out); | | 14 | gsub("\\\t", "\\t", out); |
15 | gsub(" ", "\\ ", out); | | 15 | gsub(" ", "\\ ", out); |
16 | gsub("'", "\\'", out); | | 16 | gsub("'", "\\'", out); |
17 | gsub("`", "\\`", out); | | 17 | gsub("`", "\\`", out); |
18 | gsub("\"", "\\\"", out); | | 18 | gsub("\"", "\\\"", out); |
19 | gsub(";", "\\;", out); | | 19 | gsub(";", "\\;", out); |
20 | gsub("&", "\\&", out); | | 20 | gsub("&", "\\&", out); |
21 | gsub("<", "\\<", out); | | 21 | gsub("<", "\\<", out); |
22 | gsub(">", "\\>", out); | | 22 | gsub(">", "\\>", out); |
23 | gsub("\\(", "\\(", out); | | 23 | gsub("\\(", "\\(", out); |
24 | gsub("\\)", "\\)", out); | | 24 | gsub("\\)", "\\)", out); |
25 | gsub("\\|", "\\|", out); | | 25 | gsub("\\|", "\\|", out); |
26 | gsub("\\*", "\\*", out); | | 26 | gsub("\\*", "\\*", out); |
27 | gsub("\\?", "\\?", out); | | 27 | gsub("\\?", "\\?", out); |
28 | gsub("\\{", "\\{", out); | | 28 | gsub("\\{", "\\{", out); |
29 | gsub("\\}", "\\}", out); | | 29 | gsub("\\}", "\\}", out); |
30 | gsub("\\[", "\\[", out); | | 30 | gsub("\\[", "\\[", out); |
31 | gsub("\\]", "\\]", out); | | 31 | gsub("\\]", "\\]", out); |
32 | gsub("\\$", "\\$", out); | | 32 | gsub("\\$", "\\$", out); |
33 | gsub("!", "\\!", out); | | 33 | gsub("!", "\\!", out); |
34 | gsub("#", "\\#", out); | | 34 | gsub("#", "\\#", out); |
35 | gsub("\\^", "\\^", out); | | 35 | gsub("\\^", "\\^", out); |
36 | gsub("~", "\\~", out); | | 36 | gsub("~", "\\~", out); |
37 | return out; | | 37 | return out; |
38 | } | | 38 | } |
39 | | | 39 | |
40 | function check_pkg(DSO, pkg, found) { | | 40 | function check_pkg(DSO, pkg, found) { |
41 | if (destdir == "") | | 41 | if (destdir == "") |
42 | return 0 | | 42 | return 0 |
43 | if (DSO in pkgcache) { | | 43 | if (DSO in pkgcache) { |
44 | pkg = pkgcache[DSO] | | 44 | pkg = pkgcache[DSO] |
45 | } else { | | 45 | } else { |
46 | cmd = pkg_info_cmd " -Fe " shquote(DSO) " 2>/dev/null" | | 46 | cmd = pkg_info_cmd " -Fe " shquote(DSO) " 2>/dev/null" |
47 | if ((cmd | getline pkg) < 0) { | | 47 | if ((cmd | getline pkg) < 0) { |
48 | close(cmd) | | 48 | close(cmd) |
49 | return 0 | | 49 | return 0 |
50 | } | | 50 | } |
51 | close(cmd) | | 51 | close(cmd) |
52 | pkgcache[DSO] = pkg | | 52 | pkgcache[DSO] = pkg |
53 | } | | 53 | } |
54 | if (pkg == "") | | 54 | if (pkg == "") |
55 | return 0 | | 55 | return 0 |
56 | found=0 | | 56 | found=0 |
57 | while ((getline < depends_file) > 0) { | | 57 | while ((getline < depends_file) > 0) { |
58 | if ($3 == pkg) { | | 58 | if ($3 == pkg) { |
59 | found=1 | | 59 | found=1 |
60 | if ($1 != "full") | | 60 | if ($1 != "full") |
61 | continue | | 61 | continue |
62 | close(depends_file) | | 62 | close(depends_file) |
63 | return 0 | | 63 | return 0 |
64 | } | | 64 | } |
65 | } | | 65 | } |
66 | if (found) | | 66 | if (found) |
67 | print DSO ": " pkg " is not a runtime dependency" | | 67 | print DSO ": " pkg " is not a runtime dependency" |
68 | close(depends_file) | | 68 | close(depends_file) |
69 | } | | 69 | } |
70 | | | 70 | |
71 | function checkshlib(DSO, needed, found) { | | 71 | function checkshlib(DSO, needed, found) { |
72 | cmd = "otool -XL " shquote(DSO) " 2>/dev/null" | | 72 | cmd = "otool -XL " shquote(DSO) " 2>/dev/null" |
| | | 73 | libno = 0 |
73 | while ((cmd | getline) > 0) { | | 74 | while ((cmd | getline) > 0) { |
74 | if ($0 !~ /^\t/) | | 75 | if ($0 !~ /^\t/) |
75 | continue | | 76 | continue |
| | | 77 | # |
| | | 78 | # The first lib is the "install_name". Allow it to |
| | | 79 | # be just the library basename name to support modules. |
| | | 80 | # |
| | | 81 | if (libno++ == 0 && |
| | | 82 | $1 == parts[split(DSO, parts, "/")]) { |
| | | 83 | continue |
| | | 84 | } |
76 | needed[$1] = "" | | 85 | needed[$1] = "" |
77 | } | | 86 | } |
78 | close(cmd) | | 87 | close(cmd) |
79 | ndirs = split(cross_destdir ":" destdir, check_dirs, ":") | | 88 | ndirs = split(cross_destdir ":" destdir, check_dirs, ":") |
80 | for (lib in needed) { | | 89 | for (lib in needed) { |
81 | # | | 90 | # |
82 | # Ensure we don't have any WRKDIR references. | | 91 | # Ensure we don't have any WRKDIR references. |
83 | # | | 92 | # |
84 | if (lib == wrkdir || | | 93 | if (lib == wrkdir || |
85 | substr(lib, 1, length(wrkdir) + 1) == wrkdir "/") | | 94 | substr(lib, 1, length(wrkdir) + 1) == wrkdir "/") |
86 | print DSO ": path relative to WRKDIR: " lib | | 95 | print DSO ": path relative to WRKDIR: " lib |
87 | | | 96 | |
88 | # | | 97 | # |
89 | # Ensure there are no relative paths. | | 98 | # Ensure there are no relative paths. |
90 | # | | 99 | # |
91 | if (substr(lib, 1, 1) != "/") | | 100 | if (substr(lib, 1, 1) != "/") |
92 | print DSO ": relative library path: " lib | | 101 | print DSO ": relative library path: " lib |
93 | | | 102 | |
94 | # | | 103 | # |
95 | # Check destination dirs for library existence. If found in a | | 104 | # Check destination dirs for library existence. If found in a |
96 | # system path (cross_destdir is somewhat confusing but if set | | 105 | # system path (cross_destdir is somewhat confusing but if set |
97 | # it points to the populated cross destdir, otherwise we are | | 106 | # it points to the populated cross destdir, otherwise we are |
98 | # checking '/') then check_pkg() ensures it is a runtime dep. | | 107 | # checking '/') then check_pkg() ensures it is a runtime dep. |
99 | # | | 108 | # |
100 | for (i = 1; i <= ndirs; i++) { | | 109 | for (i = 1; i <= ndirs; i++) { |
101 | libfile = check_dirs[i] lib | | 110 | libfile = check_dirs[i] lib |
102 | if (!(libfile in libcache)) | | 111 | if (!(libfile in libcache)) |
103 | libcache[libfile] = system("test -f " \ | | 112 | libcache[libfile] = system("test -f " \ |
104 | shquote(libfile)) | | 113 | shquote(libfile)) |
105 | if (libcache[libfile] == 0) { | | 114 | if (libcache[libfile] == 0) { |
106 | check_pkg(lib) | | 115 | check_pkg(lib) |
107 | found = 1 | | 116 | found = 1 |
108 | break | | 117 | break |
109 | } | | 118 | } |
110 | } | | 119 | } |
111 | if (found == 0) | | 120 | if (found == 0) |
112 | print DSO ": missing library: " lib | | 121 | print DSO ": missing library: " lib |
113 | } | | 122 | } |
114 | } | | 123 | } |
115 | | | 124 | |
116 | BEGIN { | | 125 | BEGIN { |
117 | cross_destdir = ENVIRON["CROSS_DESTDIR"] | | 126 | cross_destdir = ENVIRON["CROSS_DESTDIR"] |
118 | destdir = ENVIRON["DESTDIR"] | | 127 | destdir = ENVIRON["DESTDIR"] |
119 | wrkdir = ENVIRON["WRKDIR"] | | 128 | wrkdir = ENVIRON["WRKDIR"] |
120 | pkg_info_cmd = ENVIRON["PKG_INFO_CMD"] | | 129 | pkg_info_cmd = ENVIRON["PKG_INFO_CMD"] |
121 | depends_file = ENVIRON["DEPENDS_FILE"] | | 130 | depends_file = ENVIRON["DEPENDS_FILE"] |
122 | } | | 131 | } |
123 | | | 132 | |
124 | { checkshlib($0); } | | 133 | { checkshlib($0); } |