Print this page
9139 check_rtime should be able to forbid libraries
9140 check_rtime should learn libnsl is safe now
9141 check_rtime exceptions could be cleaner
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/scripts/check_rtime.pl
+++ new/usr/src/tools/scripts/check_rtime.pl
1 1 #!/usr/perl5/bin/perl -w
2 2 #
3 3 # CDDL HEADER START
4 4 #
5 5 # The contents of this file are subject to the terms of the
6 6 # Common Development and Distribution License (the "License").
7 7 # You may not use this file except in compliance with the License.
8 8 #
9 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 # or http://www.opensolaris.org/os/licensing.
11 11 # See the License for the specific language governing permissions
12 12 # and limitations under the License.
13 13 #
14 14 # When distributing Covered Code, include this CDDL HEADER in each
15 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 # If applicable, add the following below this CDDL HEADER, with the
17 17 # fields enclosed by brackets "[]" replaced with your own identifying
18 18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 19 #
20 20 # CDDL HEADER END
21 21 #
22 22
23 23 #
24 24 # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25 25 #
26 26
27 27 #
28 28 # Check ELF information.
29 29 #
30 30 # This script descends a directory hierarchy inspecting ELF dynamic executables
31 31 # and shared objects. The general theme is to verify that common Makefile rules
32 32 # have been used to build these objects. Typical failures occur when Makefile
33 33 # rules are re-invented rather than being inherited from "cmd/lib" Makefiles.
34 34 #
35 35 # As always, a number of components don't follow the rules, and these are
36 36 # excluded to reduce this scripts output.
37 37 #
38 38 # By default any file that has conditions that should be reported is first
39 39 # listed and then each condition follows. The -o (one-line) option produces a
40 40 # more terse output which is better for sorting/diffing with "nightly".
41 41 #
42 42 # NOTE: missing dependencies, symbols or versions are reported by running the
43 43 # file through ldd(1). As objects within a proto area are built to exist in a
44 44 # base system, standard use of ldd(1) will bind any objects to dependencies
45 45 # that exist in the base system. It is frequently the case that newer objects
46 46 # exist in the proto area that are required to satisfy other objects
47 47 # dependencies, and without using these newer objects an ldd(1) will produce
48 48 # misleading error messages. To compensate for this, the -D/-d options, or the
49 49 # existence of the CODEMSG_WS/ROOT environment variables, cause the creation of
50 50 # alternative dependency mappings via crle(1) configuration files that establish
51 51 # any proto shared objects as alternatives to their base system location. Thus
52 52 # ldd(1) can be executed against these configuration files so that objects in a
53 53 # proto area bind to their dependencies in the same proto area.
54 54
55 55
56 56 # Define all global variables (required for strict)
57 57 use vars qw($Prog $Env $Ena64 $Tmpdir);
58 58 use vars qw($LddNoU $Conf32 $Conf64);
59 59 use vars qw(%opt);
60 60 use vars qw($ErrFH $ErrTtl $InfoFH $InfoTtl $OutCnt1 $OutCnt2);
61 61
62 62 # An exception file is used to specify regular expressions to match
63 63 # objects. These directives specify special attributes of the object.
64 64 # The regular expressions are read from the file and compiled into the
65 65 # regular expression variables.
66 66 #
67 67 # The name of each regular expression variable is of the form
68 68 #
69 69 # $EXRE_xxx
70 70 #
71 71 # where xxx is the name of the exception in lower case. For example,
72 72 # the regular expression variable for EXEC_STACK is $EXRE_exec_stack.
73 73 #
74 74 # onbld_elfmod::LoadExceptionsToEXRE() depends on this naming convention
75 75 # to initialize the regular expression variables, and to detect invalid
76 76 # exception names.
77 77 #
78 78 # If a given exception is not used in the exception file, its regular
79 79 # expression variable will be undefined. Users of these variables must
80 80 # test the variable with defined() prior to use:
81 81 #
82 82 # defined($EXRE_exec_stack) && ($foo =~ $EXRE_exec_stack)
83 83 #
84 84 # or if the test is to make sure the item is not specified:
85 85 #
86 86 # !defined($EXRE_exec_stack) || ($foo !~ $EXRE_exec_stack)
87 87 #
88 88 # ----
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
89 89 #
90 90 # The exceptions are:
91 91 #
92 92 # EXEC_DATA
93 93 # Objects that are not required to have non-executable writable
94 94 # data segments.
95 95 #
96 96 # EXEC_STACK
97 97 # Objects that are not required to have a non-executable stack
98 98 #
99 +# FORBIDDEN_DEP
100 +# Objects allowed to link to 'forbidden' objects
101 +#
102 +# FORBIDDEN
103 +# Objects to which nobody not excepted with FORBIDDEN_DEP may link
104 +#
99 105 # NOCRLEALT
100 106 # Objects that should be skipped by AltObjectConfig() when building
101 107 # the crle script that maps objects to the proto area.
102 108 #
103 109 # NODIRECT
104 110 # Objects that are not required to use direct bindings
105 111 #
106 112 # NOSYMSORT
107 113 # Objects we should not check for duplicate addresses in
108 114 # the symbol sort sections.
109 115 #
110 116 # OLDDEP
111 117 # Objects that are no longer needed because their functionalty
112 118 # has migrated elsewhere. These are usually pure filters that
113 119 # point at libc.
114 120 #
115 121 # SKIP
116 122 # Files and directories that should be excluded from analysis.
117 123 #
118 124 # STAB
119 125 # Objects that are allowed to contain stab debugging sections
120 126 #
121 127 # TEXTREL
122 128 # Object for which relocations are allowed to the text segment
123 129 #
124 130 # UNDEF_REF
125 131 # Objects that are allowed undefined references
126 132 #
127 133 # UNREF_OBJ
128 134 # "unreferenced object=" ldd(1) diagnostics.
129 135 #
130 136 # UNUSED_DEPS
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
131 137 # Objects that are allowed to have unused dependencies
132 138 #
133 139 # UNUSED_OBJ
134 140 # Objects that are allowed to be unused dependencies
135 141 #
136 142 # UNUSED_RPATH
137 143 # Objects with unused runpaths
138 144 #
139 145
140 146 use vars qw($EXRE_exec_data $EXRE_exec_stack $EXRE_nocrlealt);
141 -use vars qw($EXRE_nodirect $EXRE_nosymsort);
147 +use vars qw($EXRE_nodirect $EXRE_nosymsort $EXRE_forbidden_dep $EXRE_forbidden);
142 148 use vars qw($EXRE_olddep $EXRE_skip $EXRE_stab $EXRE_textrel $EXRE_undef_ref);
143 149 use vars qw($EXRE_unref_obj $EXRE_unused_deps $EXRE_unused_obj);
144 150 use vars qw($EXRE_unused_rpath);
145 151
146 152 use strict;
147 153 use Getopt::Std;
148 154 use File::Basename;
149 155
150 156
151 157 # Reliably compare two OS revisions. Arguments are <ver1> <op> <ver2>.
152 158 # <op> is the string form of a normal numeric comparison operator.
153 159 sub cmp_os_ver {
154 160 my @ver1 = split(/\./, $_[0]);
155 161 my $op = $_[1];
156 162 my @ver2 = split(/\./, $_[2]);
157 163
158 164 push @ver2, ("0") x $#ver1 - $#ver2;
159 165 push @ver1, ("0") x $#ver2 - $#ver1;
160 166
161 167 my $diff = 0;
162 168 while (@ver1 || @ver2) {
163 169 if (($diff = shift(@ver1) - shift(@ver2)) != 0) {
164 170 last;
165 171 }
166 172 }
167 173 return (eval "$diff $op 0" ? 1 : 0);
168 174 }
169 175
170 176 ## ProcFile(FullPath, RelPath, File, Class, Type, Verdef)
171 177 #
172 178 # Determine whether this a ELF dynamic object and if so investigate its runtime
173 179 # attributes.
174 180 #
175 181 sub ProcFile {
176 182 my($FullPath, $RelPath, $Class, $Type, $Verdef) = @_;
177 183 my(@Elf, @Ldd, $Dyn, $Sym, $Stack);
178 184 my($Sun, $Relsz, $Pltsz, $Tex, $Stab, $Strip, $Lddopt, $SymSort);
179 185 my($Val, $Header, $IsX86, $RWX, $UnDep);
180 186 my($HasDirectBinding);
181 187
182 188 # Only look at executables and sharable objects
183 189 return if ($Type ne 'EXEC') && ($Type ne 'DYN');
184 190
185 191 # Ignore symbolic links
186 192 return if -l $FullPath;
187 193
188 194 # Is this an object or directory hierarchy we don't care about?
189 195 return if (defined($EXRE_skip) && ($RelPath =~ $EXRE_skip));
190 196
191 197 # Bail if we can't stat the file. Otherwise, note if it is SUID/SGID.
192 198 return if !stat($FullPath);
193 199 my $Secure = (-u _ || -g _) ? 1 : 0;
194 200
195 201 # Reset output message counts for new input file
196 202 $$ErrTtl = $$InfoTtl = 0;
197 203
198 204 @Ldd = 0;
199 205
200 206 # Determine whether we have access to inspect the file.
201 207 if (!(-r $FullPath)) {
202 208 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
203 209 "unable to inspect file: permission denied");
204 210 return;
205 211 }
206 212
207 213 # Determine whether we have a executable (static or dynamic) or a
208 214 # shared object.
209 215 @Elf = split(/\n/, `elfdump -epdcy $FullPath 2>&1`);
210 216
211 217 $Dyn = $Stack = $IsX86 = $RWX = 0;
212 218 $Header = 'None';
213 219 foreach my $Line (@Elf) {
214 220 # If we have an invalid file type (which we can tell from the
215 221 # first line), or we're processing an archive, bail.
216 222 if ($Header eq 'None') {
217 223 if (($Line =~ /invalid file/) ||
218 224 ($Line =~ /\Q$FullPath\E(.*):/)) {
219 225 return;
220 226 }
221 227 }
222 228
223 229 if ($Line =~ /^ELF Header/) {
224 230 $Header = 'Ehdr';
225 231 next;
226 232 }
227 233
228 234 if ($Line =~ /^Program Header/) {
229 235 $Header = 'Phdr';
230 236 $RWX = 0;
231 237 next;
232 238 }
233 239
234 240 if ($Line =~ /^Dynamic Section/) {
235 241 # A dynamic section indicates we're a dynamic object
236 242 # (this makes sure we don't check static executables).
237 243 $Dyn = 1;
238 244 next;
239 245 }
240 246
241 247 if (($Header eq 'Ehdr') && ($Line =~ /e_machine:/)) {
242 248 # If it's a X86 object, we need to enforce RW- data.
243 249 $IsX86 = 1 if $Line =~ /(EM_AMD64|EM_386)/;
244 250 next;
245 251 }
246 252
247 253 if (($Header eq 'Phdr') &&
248 254 ($Line =~ /\[ PF_X\s+PF_W\s+PF_R \]/)) {
249 255 # RWX segment seen.
250 256 $RWX = 1;
251 257 next;
252 258 }
253 259
254 260 if (($Header eq 'Phdr') &&
255 261 ($Line =~ /\[ PT_LOAD \]/ && $RWX && $IsX86)) {
256 262 # Seen an RWX PT_LOAD segment.
257 263 if (!defined($EXRE_exec_data) ||
258 264 ($RelPath !~ $EXRE_exec_data)) {
259 265 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
260 266 "application requires non-executable " .
261 267 "data\t<no -Mmapfile_noexdata?>");
262 268 }
263 269 next;
264 270 }
265 271
266 272 if (($Header eq 'Phdr') && ($Line =~ /\[ PT_SUNWSTACK \]/)) {
267 273 # This object defines a non-executable stack.
268 274 $Stack = 1;
269 275 next;
270 276 }
271 277 }
272 278
273 279 # Determine whether this ELF executable or shared object has a
274 280 # conforming mcs(1) comment section. If the correct $(POST_PROCESS)
275 281 # macros are used, only a 3 or 4 line .comment section should exist
276 282 # containing one or two "@(#)SunOS" identifying comments (one comment
277 283 # for a non-debug build, and two for a debug build). The results of
278 284 # the following split should be three or four lines, the last empty
279 285 # line being discarded by the split.
280 286 if ($opt{m}) {
281 287 my(@Mcs, $Con, $Dev);
282 288
283 289 @Mcs = split(/\n/, `mcs -p $FullPath 2>&1`);
284 290
285 291 $Con = $Dev = $Val = 0;
286 292 foreach my $Line (@Mcs) {
287 293 $Val++;
288 294
289 295 if (($Val == 3) && ($Line !~ /^@\(#\)SunOS/)) {
290 296 $Con = 1;
291 297 last;
292 298 }
293 299 if (($Val == 4) && ($Line =~ /^@\(#\)SunOS/)) {
294 300 $Dev = 1;
295 301 next;
296 302 }
297 303 if (($Dev == 0) && ($Val == 4)) {
298 304 $Con = 1;
299 305 last;
300 306 }
301 307 if (($Dev == 1) && ($Val == 5)) {
302 308 $Con = 1;
303 309 last;
304 310 }
305 311 }
306 312 if ($opt{m} && ($Con == 1)) {
307 313 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
308 314 "non-conforming mcs(1) comment\t<no \$(POST_PROCESS)?>");
309 315 }
310 316 }
311 317
312 318 # Applications should contain a non-executable stack definition.
313 319 if (($Type eq 'EXEC') && ($Stack == 0) &&
314 320 (!defined($EXRE_exec_stack) || ($RelPath !~ $EXRE_exec_stack))) {
315 321 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
316 322 "non-executable stack required\t<no -Mmapfile_noexstk?>");
317 323 }
318 324
319 325 # Having caught any static executables in the mcs(1) check and non-
320 326 # executable stack definition check, continue with dynamic objects
321 327 # from now on.
322 328 if ($Dyn eq 0) {
323 329 return;
324 330 }
325 331
326 332 # Use ldd unless its a 64-bit object and we lack the hardware.
327 333 if (($Class == 32) || $Ena64) {
328 334 my $LDDFullPath = $FullPath;
329 335
330 336 if ($Secure) {
331 337 # The execution of a secure application over an nfs file
332 338 # system mounted nosuid will result in warning messages
333 339 # being sent to /var/adm/messages. As this type of
334 340 # environment can occur with root builds, move the file
335 341 # being investigated to a safe place first. In addition
336 342 # remove its secure permission so that it can be
337 343 # influenced by any alternative dependency mappings.
338 344
339 345 my $File = $RelPath;
340 346 $File =~ s!^.*/!!; # basename
341 347
342 348 my($TmpPath) = "$Tmpdir/$File";
343 349
344 350 system('cp', $LDDFullPath, $TmpPath);
345 351 chmod 0777, $TmpPath;
346 352 $LDDFullPath = $TmpPath;
347 353 }
348 354
349 355 # Use ldd(1) to determine the objects relocatability and use.
350 356 # By default look for all unreferenced dependencies. However,
351 357 # some objects have legitimate dependencies that they do not
352 358 # reference.
353 359 if ($LddNoU) {
354 360 $Lddopt = "-ru";
355 361 } else {
356 362 $Lddopt = "-rU";
357 363 }
358 364 @Ldd = split(/\n/, `ldd $Lddopt $Env $LDDFullPath 2>&1`);
359 365 if ($Secure) {
360 366 unlink $LDDFullPath;
361 367 }
362 368 }
363 369
364 370 $Val = 0;
365 371 $Sym = 5;
366 372 $UnDep = 1;
367 373
368 374 foreach my $Line (@Ldd) {
369 375
370 376 if ($Val == 0) {
371 377 $Val = 1;
372 378 # Make sure ldd(1) worked. One possible failure is that
373 379 # this is an old ldd(1) prior to -e addition (4390308).
374 380 if ($Line =~ /usage:/) {
375 381 $Line =~ s/$/\t<old ldd(1)?>/;
376 382 onbld_elfmod::OutMsg($ErrFH, $ErrTtl,
377 383 $RelPath, $Line);
378 384 last;
379 385 } elsif ($Line =~ /execution failed/) {
380 386 onbld_elfmod::OutMsg($ErrFH, $ErrTtl,
381 387 $RelPath, $Line);
382 388 last;
383 389 }
384 390
385 391 # It's possible this binary can't be executed, ie. we've
386 392 # found a sparc binary while running on an intel system,
387 393 # or a sparcv9 binary on a sparcv7/8 system.
388 394 if ($Line =~ /wrong class/) {
389 395 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
390 396 "has wrong class or data encoding");
391 397 next;
392 398 }
393 399
394 400 # Historically, ldd(1) likes executable objects to have
395 401 # their execute bit set.
396 402 if ($Line =~ /not executable/) {
397 403 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
398 404 "is not executable");
399 405 next;
400 406 }
401 407 }
402 408
403 409 # Look for "file" or "versions" that aren't found. Note that
404 410 # these lines will occur before we find any symbol referencing
405 411 # errors.
406 412 if (($Sym == 5) && ($Line =~ /not found\)/)) {
407 413 if ($Line =~ /file not found\)/) {
408 414 $Line =~ s/$/\t<no -zdefs?>/;
409 415 }
410 416 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
411 417 next;
412 418 }
413 419 # Look for relocations whose symbols can't be found. Note, we
414 420 # only print out the first 5 relocations for any file as this
415 421 # output can be excessive.
416 422 if ($Sym && ($Line =~ /symbol not found/)) {
417 423 # Determine if this file is allowed undefined
418 424 # references.
419 425 if (($Sym == 5) && defined($EXRE_undef_ref) &&
420 426 ($RelPath =~ $EXRE_undef_ref)) {
421 427 $Sym = 0;
422 428 next;
423 429 }
424 430 if ($Sym-- == 1) {
425 431 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
426 432 "continued ...") if !$opt{o};
427 433 next;
428 434 }
429 435 # Just print the symbol name.
430 436 $Line =~ s/$/\t<no -zdefs?>/;
431 437 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
432 438 next;
433 439 }
434 440 # Look for any unused search paths.
435 441 if ($Line =~ /unused search path=/) {
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
436 442 next if defined($EXRE_unused_rpath) &&
437 443 ($Line =~ $EXRE_unused_rpath);
438 444
439 445 if ($Secure) {
440 446 $Line =~ s!$Tmpdir/!!;
441 447 }
442 448 $Line =~ s/^[ \t]*(.*)/\t$1\t<remove search path?>/;
443 449 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
444 450 next;
445 451 }
452 +
446 453 # Look for unreferenced dependencies. Note, if any unreferenced
447 454 # objects are ignored, then set $UnDep so as to suppress any
448 455 # associated unused-object messages.
449 456 if ($Line =~ /unreferenced object=/) {
450 457 if (defined($EXRE_unref_obj) &&
451 458 ($Line =~ $EXRE_unref_obj)) {
452 459 $UnDep = 0;
453 460 next;
454 461 }
455 462 if ($Secure) {
456 463 $Line =~ s!$Tmpdir/!!;
457 464 }
458 465 $Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/;
459 466 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
460 467 next;
461 468 }
462 469 # Look for any unused dependencies.
463 470 if ($UnDep && ($Line =~ /unused/)) {
464 471 # Skip if object is allowed to have unused dependencies
465 472 next if defined($EXRE_unused_deps) &&
466 473 ($RelPath =~ $EXRE_unused_deps);
467 474
468 475 # Skip if dependency is always allowed to be unused
469 476 next if defined($EXRE_unused_obj) &&
470 477 ($Line =~ $EXRE_unused_obj);
471 478
472 479 $Line =~ s!$Tmpdir/!! if $Secure;
473 480 $Line =~ s/^[ \t]*(.*)/$1\t<remove lib or -zignore?>/;
474 481 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath, $Line);
475 482 next;
476 483 }
477 484 }
478 485
479 486 # Reuse the elfdump(1) data to investigate additional dynamic linking
480 487 # information.
481 488
482 489 $Sun = $Relsz = $Pltsz = $Dyn = $Stab = $SymSort = 0;
483 490 $Tex = $Strip = 1;
484 491 $HasDirectBinding = 0;
485 492
486 493 $Header = 'None';
487 494 ELF: foreach my $Line (@Elf) {
488 495 # We're only interested in the section headers and the dynamic
489 496 # section.
490 497 if ($Line =~ /^Section Header/) {
491 498 $Header = 'Shdr';
492 499
493 500 if (($Sun == 0) && ($Line =~ /\.SUNW_reloc/)) {
494 501 # This object has a combined relocation section.
495 502 $Sun = 1;
496 503
497 504 } elsif (($Stab == 0) && ($Line =~ /\.stab/)) {
498 505 # This object contain .stabs sections
499 506 $Stab = 1;
500 507 } elsif (($SymSort == 0) &&
501 508 ($Line =~ /\.SUNW_dyn(sym)|(tls)sort/)) {
502 509 # This object contains a symbol sort section
503 510 $SymSort = 1;
504 511 }
505 512
506 513 if (($Strip == 1) && ($Line =~ /\.symtab/)) {
507 514 # This object contains a complete symbol table.
508 515 $Strip = 0;
509 516 }
510 517 next;
511 518
512 519 } elsif ($Line =~ /^Dynamic Section/) {
513 520 $Header = 'Dyn';
514 521 next;
515 522 } elsif ($Line =~ /^Syminfo Section/) {
516 523 $Header = 'Syminfo';
517 524 next;
518 525 } elsif (($Header ne 'Dyn') && ($Header ne 'Syminfo')) {
519 526 next;
520 527 }
521 528
522 529 # Look into the Syminfo section.
523 530 # Does this object have at least one Directly Bound symbol?
524 531 if (($Header eq 'Syminfo')) {
525 532 my(@Symword);
526 533
527 534 if ($HasDirectBinding == 1) {
528 535 next;
529 536 }
530 537
531 538 @Symword = split(' ', $Line);
532 539
533 540 if (!defined($Symword[1])) {
534 541 next;
535 542 }
536 543 if ($Symword[1] =~ /B/) {
537 544 $HasDirectBinding = 1;
538 545 }
539 546 next;
540 547 }
541 548
542 549 # Does this object contain text relocations.
543 550 if ($Tex && ($Line =~ /TEXTREL/)) {
544 551 # Determine if this file is allowed text relocations.
545 552 if (defined($EXRE_textrel) &&
546 553 ($RelPath =~ $EXRE_textrel)) {
547 554 $Tex = 0;
548 555 next ELF;
549 556 }
550 557 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
551 558 "TEXTREL .dynamic tag\t\t\t<no -Kpic?>");
552 559 $Tex = 0;
553 560 next;
554 561 }
555 562
556 563 # Does this file have any relocation sections (there are a few
557 564 # psr libraries with no relocations at all, thus a .SUNW_reloc
558 565 # section won't exist either).
559 566 if (($Relsz == 0) && ($Line =~ / RELA?SZ/)) {
560 567 $Relsz = hex((split(' ', $Line))[2]);
561 568 next;
562 569 }
563 570
564 571 # Does this file have any plt relocations. If the plt size is
565 572 # equivalent to the total relocation size then we don't have
566 573 # any relocations suitable for combining into a .SUNW_reloc
567 574 # section.
568 575 if (($Pltsz == 0) && ($Line =~ / PLTRELSZ/)) {
569 576 $Pltsz = hex((split(' ', $Line))[2]);
↓ open down ↓ |
114 lines elided |
↑ open up ↑ |
570 577 next;
571 578 }
572 579
573 580 # Does this object have any dependencies.
574 581 if ($Line =~ /NEEDED/) {
575 582 my($Need) = (split(' ', $Line))[3];
576 583
577 584 if (defined($EXRE_olddep) && ($Need =~ $EXRE_olddep)) {
578 585 # Catch any old (unnecessary) dependencies.
579 586 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
580 - "NEEDED=$Need\t<dependency no longer necessary>");
587 + "NEEDED=$Need\t<dependency no " .
588 + "longer necessary>");
589 + } elsif (defined($EXRE_forbidden) &&
590 + ($Need =~ $EXRE_forbidden)) {
591 + next if defined($EXRE_forbidden_dep) &&
592 + ($FullPath =~ $EXRE_forbidden_dep);
593 +
594 + onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
595 + "NEEDED=$Need\t<forbidden dependency, " .
596 + "missing -nodefaultlibs?>");
597 + next;
581 598 } elsif ($opt{i}) {
582 599 # Under the -i (information) option print out
583 600 # any useful dynamic entries.
584 601 onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
585 602 "NEEDED=$Need");
586 - }
603 + }
587 604 next;
588 605 }
589 606
590 607 # Is this object built with -B direct flag on?
591 608 if ($Line =~ / DIRECT /) {
592 609 $HasDirectBinding = 1;
593 610 }
594 611
595 612 # Does this object specify a runpath.
596 613 if ($opt{i} && ($Line =~ /RPATH/)) {
597 614 my($Rpath) = (split(' ', $Line))[3];
598 615 onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
599 616 $RelPath, "RPATH=$Rpath");
600 617 next;
601 618 }
602 619 }
603 620
604 621 # A shared object, that contains non-plt relocations, should have a
605 622 # combined relocation section indicating it was built with -z combreloc.
606 623 if (($Type eq 'DYN') && $Relsz && ($Relsz != $Pltsz) && ($Sun == 0)) {
607 624 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
608 625 ".SUNW_reloc section missing\t\t<no -zcombreloc?>");
609 626 }
610 627
611 628 # No objects released to a customer should have any .stabs sections
612 629 # remaining, they should be stripped.
613 630 if ($opt{s} && $Stab) {
614 631 goto DONESTAB if defined($EXRE_stab) && ($RelPath =~ $EXRE_stab);
615 632
616 633 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
617 634 "debugging sections should be deleted\t<no strip -x?>");
618 635 }
619 636
620 637 # Identify an object that is not built with either -B direct or
621 638 # -z direct.
622 639 goto DONESTAB
623 640 if (defined($EXRE_nodirect) && ($RelPath =~ $EXRE_nodirect));
624 641
625 642 if ($Relsz && ($HasDirectBinding == 0)) {
626 643 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
627 644 "object has no direct bindings\t<no -B direct or -z direct?>");
628 645 }
629 646
630 647 DONESTAB:
631 648
632 649 # All objects should have a full symbol table to provide complete
633 650 # debugging stack traces.
634 651 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
635 652 "symbol table should not be stripped\t<remove -s?>") if $Strip;
636 653
637 654 # If there are symbol sort sections in this object, report on
638 655 # any that have duplicate addresses.
639 656 ProcSymSort($FullPath, $RelPath) if $SymSort;
640 657
641 658 # If -v was specified, and the object has a version definition
642 659 # section, generate output showing each public symbol and the
643 660 # version it belongs to.
644 661 ProcVerdef($FullPath, $RelPath)
645 662 if ($Verdef eq 'VERDEF') && $opt{v};
646 663 }
647 664
648 665
649 666 ## ProcSymSortOutMsg(RelPath, secname, addr, names...)
650 667 #
651 668 # Call onbld_elfmod::OutMsg for a duplicate address error in a symbol sort
652 669 # section
653 670 #
654 671 sub ProcSymSortOutMsg {
655 672 my($RelPath, $secname, $addr, @names) = @_;
656 673
657 674 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
658 675 "$secname: duplicate $addr: ". join(', ', @names));
659 676 }
660 677
661 678
662 679 ## ProcSymSort(FullPath, RelPath)
663 680 #
664 681 # Examine the symbol sort sections for the given object and report
665 682 # on any duplicate addresses found. Ideally, mapfile directives
666 683 # should be used when building objects that have multiple symbols
667 684 # with the same address so that only one of them appears in the sort
668 685 # section. This saves space, reduces user confusion, and ensures that
669 686 # libproc and debuggers always display public names instead of symbols
670 687 # that are merely implementation details.
671 688 #
672 689 sub ProcSymSort {
673 690
674 691 my($FullPath, $RelPath) = @_;
675 692
676 693 # If this object is exempt from checking, return quietly
677 694 return if defined($EXRE_nosymsort) && ($FullPath =~ $EXRE_nosymsort);
678 695
679 696
680 697 open(SORT, "elfdump -S $FullPath|") ||
681 698 die "$Prog: Unable to execute elfdump (symbol sort sections)\n";
682 699
683 700 my $line;
684 701 my $last_addr;
685 702 my @dups = ();
686 703 my $secname;
687 704 while ($line = <SORT>) {
688 705 chomp $line;
689 706
690 707 next if ($line eq '');
691 708
692 709 # If this is a header line, pick up the section name
693 710 if ($line =~ /^Symbol Sort Section:\s+([^\s]+)\s+/) {
694 711 $secname = $1;
695 712
696 713 # Every new section is followed by a column header line
697 714 $line = <SORT>; # Toss header line
698 715
699 716 # Flush anything left from previous section
700 717 ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups)
701 718 if (scalar(@dups) > 1);
702 719
703 720 # Reset variables for new sort section
704 721 $last_addr = '';
705 722 @dups = ();
706 723
707 724 next;
708 725 }
709 726
710 727 # Process symbol line
711 728 my @fields = split /\s+/, $line;
712 729 my $new_addr = $fields[2];
713 730 my $new_type = $fields[8];
714 731 my $new_name = $fields[9];
715 732
716 733 if ($new_type eq 'UNDEF') {
717 734 onbld_elfmod::OutMsg($ErrFH, $ErrTtl, $RelPath,
718 735 "$secname: unexpected UNDEF symbol " .
719 736 "(link-editor error): $new_name");
720 737 next;
721 738 }
722 739
723 740 if ($new_addr eq $last_addr) {
724 741 push @dups, $new_name;
725 742 } else {
726 743 ProcSymSortOutMsg($RelPath, $secname,
727 744 $last_addr, @dups) if (scalar(@dups) > 1);
728 745 @dups = ( $new_name );
729 746 $last_addr = $new_addr;
730 747 }
731 748 }
732 749
733 750 ProcSymSortOutMsg($RelPath, $secname, $last_addr, @dups)
734 751 if (scalar(@dups) > 1);
735 752
736 753 close SORT;
737 754 }
738 755
739 756
740 757 ## ProcVerdef(FullPath, RelPath)
741 758 #
742 759 # Examine the version definition section for the given object and report
743 760 # each public symbol along with the version it belongs to.
744 761 #
745 762 sub ProcVerdef {
746 763
747 764 my($FullPath, $RelPath) = @_;
748 765 my $line;
749 766 my $cur_ver = '';
750 767 my $tab = $opt{o} ? '' : "\t";
751 768
752 769 # pvs -dov provides information about the versioning hierarchy
753 770 # in the file. Lines are of the format:
754 771 # path - version[XXX];
755 772 # where [XXX] indicates optional information, such as flags
756 773 # or inherited versions.
757 774 #
758 775 # Private versions are allowed to change freely, so ignore them.
759 776 open(PVS, "pvs -dov $FullPath|") ||
760 777 die "$Prog: Unable to execute pvs (version definition section)\n";
761 778
762 779 while ($line = <PVS>) {
763 780 chomp $line;
764 781
765 782 if ($line =~ /^[^\s]+\s+-\s+([^;]+)/) {
766 783 my $ver = $1;
767 784
768 785 next if $ver =~ /private/i;
769 786 onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
770 787 "${tab}VERDEF=$ver");
771 788 }
772 789 }
773 790 close PVS;
774 791
775 792 # pvs -dos lists the symbols assigned to each version definition.
776 793 # Lines are of the format:
777 794 # path - version: symbol;
778 795 # path - version: symbol (size);
779 796 # where the (size) is added to data items, but not for functions.
780 797 # We strip off the size, if present.
781 798
782 799 open(PVS, "pvs -dos $FullPath|") ||
783 800 die "$Prog: Unable to execute pvs (version definition section)\n";
784 801 while ($line = <PVS>) {
785 802 chomp $line;
786 803 if ($line =~ /^[^\s]+\s+-\s+([^:]+):\s*([^\s;]+)/) {
787 804 my $ver = $1;
788 805 my $sym = $2;
789 806
790 807 next if $ver =~ /private/i;
791 808
792 809 if ($opt{o}) {
793 810 onbld_elfmod::OutMsg($InfoFH, $InfoTtl, $RelPath,
794 811 "VERSION=$ver, SYMBOL=$sym");
795 812 } else {
796 813 if ($cur_ver ne $ver) {
797 814 onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
798 815 $RelPath, "VERSION=$ver");
799 816 $cur_ver = $ver;
800 817 }
801 818 onbld_elfmod::OutMsg($InfoFH, $InfoTtl,
802 819 $RelPath, "SYMBOL=$sym");
803 820 }
804 821 }
805 822 }
806 823
807 824 close PVS;
808 825 }
809 826
810 827
811 828 ## OpenFindElf(file, FileHandleRef, LineNumRef)
812 829 #
813 830 # Open file in 'find_elf -r' format, and return the value of
814 831 # the opening PREFIX line.
815 832 #
816 833 # entry:
817 834 # file - file, or find_elf child process, to open
818 835 # FileHandleRef - Reference to file handle to open
819 836 # LineNumRef - Reference to integer to increment as lines are input
820 837 #
821 838 # exit:
822 839 # This routine issues a fatal error and does not return on error.
823 840 # Otherwise, the value of PREFIX is returned.
824 841 #
825 842 sub OpenFindElf {
826 843 my ($file, $fh, $LineNum) = @_;
827 844 my $line;
828 845 my $prefix;
829 846
830 847 open($fh, $file) || die "$Prog: Unable to open: $file";
831 848 $$LineNum = 0;
832 849
833 850 # This script requires relative paths as created by 'find_elf -r'.
834 851 # When this is done, the first non-comment line will always
835 852 # be PREFIX. Obtain that line, or issue a fatal error.
836 853 while ($line = onbld_elfmod::GetLine($fh, $LineNum)) {
837 854 if ($line =~ /^PREFIX\s+(.*)$/i) {
838 855 $prefix = $1;
839 856 last;
840 857 }
841 858
842 859 die "$Prog: No PREFIX line seen on line $$LineNum: $file";
843 860 }
844 861
845 862 $prefix;
846 863 }
847 864
848 865
849 866 ## ProcFindElf(file)
850 867 #
851 868 # Open the specified file, which must be produced by "find_elf -r",
852 869 # and process the files it describes.
853 870 #
854 871 sub ProcFindElf {
855 872 my $file = $_[0];
856 873 my $line;
857 874 my $LineNum;
858 875
859 876 my $prefix = OpenFindElf($file, \*FIND_ELF, \$LineNum);
860 877
861 878 while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) {
862 879 next if !($line =~ /^OBJECT\s/i);
863 880
864 881 my ($item, $class, $type, $verdef, $obj) =
865 882 split(/\s+/, $line, 5);
866 883
867 884 ProcFile("$prefix/$obj", $obj, $class, $type, $verdef);
868 885 }
869 886
870 887 close FIND_ELF;
871 888 }
872 889
873 890
874 891 ## AltObjectConfig(file)
875 892 #
876 893 # Recurse through a directory hierarchy looking for appropriate dependencies
877 894 # to map from their standard system locations to the proto area via a crle
878 895 # config file.
879 896 #
880 897 # entry:
881 898 # file - File of ELF objects, in 'find_elf -r' format, to examine.
882 899 #
883 900 # exit:
884 901 # Scripts are generated for the 32 and 64-bit cases to run crle
885 902 # and create runtime configuration files that will establish
886 903 # alternative dependency mappings for the objects identified.
887 904 #
888 905 # $Env - Set to environment variable definitions that will cause
889 906 # the config files generated by this routine to be used
890 907 # by ldd.
891 908 # $Conf32, $Conf64 - Undefined, or set to the config files generated
892 909 # by this routine. If defined, the caller is responsible for
893 910 # unlinking the files before exiting.
894 911 #
895 912 sub AltObjectConfig {
896 913 my $file = $_[0];
897 914 my ($Crle32, $Crle64);
898 915 my $line;
899 916 my $LineNum;
900 917 my $obj_path;
901 918 my $obj_active = 0;
902 919 my $obj_class;
903 920
904 921 my $prefix = OpenFindElf($file, \*FIND_ELF);
905 922
906 923 LINE:
907 924 while ($line = onbld_elfmod::GetLine(\*FIND_ELF, \$LineNum)) {
908 925 ITEM: {
909 926
910 927 if ($line =~ /^OBJECT\s/i) {
911 928 my ($item, $class, $type, $verdef, $obj) =
912 929 split(/\s+/, $line, 5);
913 930
914 931 if ($type eq 'DYN') {
915 932 $obj_active = 1;
916 933 $obj_path = $obj;
917 934 $obj_class = $class;
918 935 } else {
919 936 # Only want sharable objects
920 937 $obj_active = 0;
921 938 }
922 939 last ITEM;
923 940 }
924 941
925 942 # We need to follow links to sharable objects so
926 943 # that any dependencies are expressed in all their
927 944 # available forms. We depend on ALIAS lines directly
928 945 # following the object they alias, so if we have
929 946 # a current object, this alias belongs to it.
930 947 if ($obj_active && ($line =~ /^ALIAS\s/i)) {
931 948 my ($item, $real_obj, $obj) =
932 949 split(/\s+/, $line, 3);
933 950 $obj_path = $obj;
934 951 last ITEM;
935 952 }
936 953
937 954 # Skip unrecognized item
938 955 next LINE;
939 956 }
940 957
941 958 next if !$obj_active;
942 959
943 960 my $full = "$prefix/$obj_path";
944 961
945 962 next if defined($EXRE_nocrlealt) &&
946 963 ($obj_path =~ $EXRE_nocrlealt);
947 964
948 965 my $Dir = $full;
949 966 $Dir =~ s/^(.*)\/.*$/$1/;
950 967
951 968 # Create a crle(1) script for the dependency we've found.
952 969 # We build separate scripts for the 32 and 64-bit cases.
953 970 # We create and initialize each script when we encounter
954 971 # the first object that needs it.
955 972 if ($obj_class == 32) {
956 973 if (!$Crle32) {
957 974 $Crle32 = "$Tmpdir/$Prog.crle32.$$";
958 975 open(CRLE32, "> $Crle32") ||
959 976 die "$Prog: open failed: $Crle32: $!";
960 977 print CRLE32 "#!/bin/sh\ncrle \\\n";
961 978 }
962 979 print CRLE32 "\t-o $Dir -a /$obj_path \\\n";
963 980 } elsif ($Ena64) {
964 981 if (!$Crle64) {
965 982 $Crle64 = "$Tmpdir/$Prog.crle64.$$";
966 983 open(CRLE64, "> $Crle64") ||
967 984 die "$Prog: open failed: $Crle64: $!";
968 985 print CRLE64 "#!/bin/sh\ncrle -64\\\n";
969 986 }
970 987 print CRLE64 "\t-o $Dir -a /$obj_path \\\n";
971 988 }
972 989 }
973 990
974 991 close FIND_ELF;
975 992
976 993
977 994 # Now that the config scripts are complete, use them to generate
978 995 # runtime linker config files.
979 996 if ($Crle64) {
980 997 $Conf64 = "$Tmpdir/$Prog.conf64.$$";
981 998 print CRLE64 "\t-c $Conf64\n";
982 999
983 1000 chmod 0755, $Crle64;
984 1001 close CRLE64;
985 1002
986 1003 undef $Conf64 if system($Crle64);
987 1004
988 1005 # Done with the script
989 1006 unlink $Crle64;
990 1007 }
991 1008 if ($Crle32) {
992 1009 $Conf32 = "$Tmpdir/$Prog.conf32.$$";
993 1010 print CRLE32 "\t-c $Conf32\n";
994 1011
995 1012 chmod 0755, $Crle32;
996 1013 close CRLE32;
997 1014
998 1015 undef $Conf32 if system($Crle32);
999 1016
1000 1017 # Done with the script
1001 1018 unlink $Crle32;
1002 1019 }
1003 1020
1004 1021 # Set $Env so that we will use the config files generated above
1005 1022 # when we run ldd.
1006 1023 if ($Crle64 && $Conf64 && $Crle32 && $Conf32) {
1007 1024 $Env = "-e LD_FLAGS=config_64=$Conf64,config_32=$Conf32";
1008 1025 } elsif ($Crle64 && $Conf64) {
1009 1026 $Env = "-e LD_FLAGS=config_64=$Conf64";
1010 1027 } elsif ($Crle32 && $Conf32) {
1011 1028 $Env = "-e LD_FLAGS=config_32=$Conf32";
1012 1029 }
1013 1030 }
1014 1031
1015 1032 # -----------------------------------------------------------------------------
1016 1033
1017 1034 # This script relies on ldd returning output reflecting only the binary
1018 1035 # contents. But if LD_PRELOAD* environment variables are present, libraries
1019 1036 # named by them will also appear in the output, disrupting our analysis.
1020 1037 # So, before we get too far, scrub the environment.
1021 1038
1022 1039 delete($ENV{LD_PRELOAD});
1023 1040 delete($ENV{LD_PRELOAD_32});
1024 1041 delete($ENV{LD_PRELOAD_64});
1025 1042
1026 1043 # Establish a program name for any error diagnostics.
1027 1044 chomp($Prog = `basename $0`);
1028 1045
1029 1046 # The onbld_elfmod package is maintained in the same directory as this
1030 1047 # script, and is installed in ../lib/perl. Use the local one if present,
1031 1048 # and the installed one otherwise.
1032 1049 my $moddir = dirname($0);
1033 1050 $moddir = "$moddir/../lib/perl" if ! -f "$moddir/onbld_elfmod.pm";
1034 1051 require "$moddir/onbld_elfmod.pm";
1035 1052
1036 1053 # Determine what machinery is available.
1037 1054 my $Mach = `uname -p`;
1038 1055 my$Isalist = `isalist`;
1039 1056 if ($Mach =~ /sparc/) {
1040 1057 if ($Isalist =~ /sparcv9/) {
1041 1058 $Ena64 = "ok";
1042 1059 }
1043 1060 } elsif ($Mach =~ /i386/) {
1044 1061 if ($Isalist =~ /amd64/) {
1045 1062 $Ena64 = "ok";
1046 1063 }
1047 1064 }
1048 1065
1049 1066 # $Env is used with all calls to ldd. It is set by AltObjectConfig to
1050 1067 # cause an alternate object mapping runtime config file to be used.
1051 1068 $Env = '';
1052 1069
1053 1070 # Check that we have arguments.
1054 1071 if ((getopts('D:d:E:e:f:I:imosvw:', \%opt) == 0) ||
1055 1072 (!$opt{f} && ($#ARGV == -1))) {
1056 1073 print "usage: $Prog [-imosv] [-D depfile | -d depdir] [-E errfile]\n";
1057 1074 print "\t\t[-e exfile] [-f listfile] [-I infofile] [-w outdir]\n";
1058 1075 print "\t\t[file | dir]...\n";
1059 1076 print "\n";
1060 1077 print "\t[-D depfile]\testablish dependencies from 'find_elf -r' file list\n";
1061 1078 print "\t[-d depdir]\testablish dependencies from under directory\n";
1062 1079 print "\t[-E errfile]\tdirect error output to file\n";
1063 1080 print "\t[-e exfile]\texceptions file\n";
1064 1081 print "\t[-f listfile]\tuse file list produced by find_elf -r\n";
1065 1082 print "\t[-I infofile]\tdirect informational output (-i, -v) to file\n";
1066 1083 print "\t[-i]\t\tproduce dynamic table entry information\n";
1067 1084 print "\t[-m]\t\tprocess mcs(1) comments\n";
1068 1085 print "\t[-o]\t\tproduce one-liner output (prefixed with pathname)\n";
1069 1086 print "\t[-s]\t\tprocess .stab and .symtab entries\n";
1070 1087 print "\t[-v]\t\tprocess version definition entries\n";
1071 1088 print "\t[-w outdir]\tinterpret all files relative to given directory\n";
1072 1089 exit 1;
1073 1090 }
1074 1091
1075 1092 die "$Prog: -D and -d options are mutually exclusive\n" if ($opt{D} && $opt{d});
1076 1093
1077 1094 $Tmpdir = "/tmp" if (!($Tmpdir = $ENV{TMPDIR}) || (! -d $Tmpdir));
1078 1095
1079 1096 # If -w, change working directory to given location
1080 1097 !$opt{w} || chdir($opt{w}) || die "$Prog: can't cd to $opt{w}";
1081 1098
1082 1099 # Locate and process the exceptions file
1083 1100 onbld_elfmod::LoadExceptionsToEXRE('check_rtime');
1084 1101
1085 1102 # Is there a proto area available, either via the -d option, or because
1086 1103 # we are part of an activated workspace?
1087 1104 my $Proto;
1088 1105 if ($opt{d}) {
1089 1106 # User specified dependency directory - make sure it exists.
1090 1107 -d $opt{d} || die "$Prog: $opt{d} is not a directory\n";
1091 1108 $Proto = $opt{d};
1092 1109 } elsif ($ENV{CODEMGR_WS}) {
1093 1110 my $Root;
1094 1111
1095 1112 # Without a user specified dependency directory see if we're
1096 1113 # part of a codemanager workspace and if a proto area exists.
1097 1114 $Proto = $Root if ($Root = $ENV{ROOT}) && (-d $Root);
1098 1115 }
1099 1116
1100 1117 # If we are basing this analysis off the sharable objects found in
1101 1118 # a proto area, then gather dependencies and construct an alternative
1102 1119 # dependency mapping via a crle(1) configuration file.
1103 1120 #
1104 1121 # To support alternative dependency mapping we'll need ldd(1)'s
1105 1122 # -e option. This is relatively new (s81_30), so make sure
1106 1123 # ldd(1) is capable before gathering any dependency information.
1107 1124 if ($opt{D} || $Proto) {
1108 1125 if (system('ldd -e /usr/lib/lddstub 2> /dev/null')) {
1109 1126 print "ldd: does not support -e, unable to ";
1110 1127 print "create alternative dependency mappingings.\n";
1111 1128 print "ldd: option added under 4390308 (s81_30).\n\n";
1112 1129 } else {
1113 1130 # If -D was specified, it supplies a list of files in
1114 1131 # 'find_elf -r' format, and can use it directly. Otherwise,
1115 1132 # we will run find_elf as a child process to find the
1116 1133 # sharable objects found under $Proto.
1117 1134 AltObjectConfig($opt{D} ? $opt{D} : "find_elf -frs $Proto|");
1118 1135 }
1119 1136 }
1120 1137
1121 1138 # To support unreferenced dependency detection we'll need ldd(1)'s -U
1122 1139 # option. This is relatively new (4638070), and if not available we
1123 1140 # can still fall back to -u. Even with this option, don't use -U with
1124 1141 # releases prior to 5.10 as the cleanup for -U use only got integrated
1125 1142 # into 5.10 under 4642023. Note, that nightly doesn't typically set a
1126 1143 # RELEASE from the standard <env> files. Users who wish to disable use
1127 1144 # of ldd(1)'s -U should set (or uncomment) RELEASE in their <env> file
1128 1145 # if using nightly, or otherwise establish it in their environment.
1129 1146 if (system('ldd -U /usr/lib/lddstub 2> /dev/null')) {
1130 1147 $LddNoU = 1;
1131 1148 } else {
1132 1149 my($Release);
1133 1150
1134 1151 if (($Release = $ENV{RELEASE}) && (cmp_os_ver($Release, "<", "5.10"))) {
1135 1152 $LddNoU = 1;
1136 1153 } else {
1137 1154 $LddNoU = 0;
1138 1155 }
1139 1156 }
1140 1157
1141 1158 # Set up variables used to handle output files:
1142 1159 #
1143 1160 # Error messages go to stdout unless -E is specified. $ErrFH is a
1144 1161 # file handle reference that points at the file handle where error messages
1145 1162 # are sent, and $ErrTtl is a reference that points at an integer used
1146 1163 # to count how many lines have been sent there.
1147 1164 #
1148 1165 # Informational messages go to stdout unless -I is specified. $InfoFH is a
1149 1166 # file handle reference that points at the file handle where info messages
1150 1167 # are sent, and $InfoTtl is a reference that points at an integer used
1151 1168 # to count how many lines have been sent there.
1152 1169 #
1153 1170 if ($opt{E}) {
1154 1171 open(ERROR, ">$opt{E}") || die "$Prog: open failed: $opt{E}";
1155 1172 $ErrFH = \*ERROR;
1156 1173 } else {
1157 1174 $ErrFH = \*STDOUT;
1158 1175 }
1159 1176
1160 1177 if ($opt{I}) {
1161 1178 open(INFO, ">$opt{I}") || die "$Prog: open failed: $opt{I}";
1162 1179 $InfoFH = \*INFO;
1163 1180 } else {
1164 1181 $InfoFH = \*STDOUT;
1165 1182 }
1166 1183 my ($err_dev, $err_ino) = stat($ErrFH);
1167 1184 my ($info_dev, $info_ino) = stat($InfoFH);
1168 1185 $ErrTtl = \$OutCnt1;
1169 1186 $InfoTtl = (($err_dev == $info_dev) && ($err_ino == $info_ino)) ?
1170 1187 \$OutCnt1 : \$OutCnt2;
1171 1188
1172 1189
1173 1190 # If we were given a list of objects in 'find_elf -r' format, then
1174 1191 # process it.
1175 1192 ProcFindElf($opt{f}) if $opt{f};
1176 1193
1177 1194 # Process each argument
1178 1195 foreach my $Arg (@ARGV) {
1179 1196 # Run find_elf to find the files given by $Arg and process them
1180 1197 ProcFindElf("find_elf -fr $Arg|");
1181 1198 }
1182 1199
1183 1200 # Cleanup output files
1184 1201 unlink $Conf64 if $Conf64;
1185 1202 unlink $Conf32 if $Conf32;
1186 1203 close ERROR if $opt{E};
1187 1204 close INFO if $opt{I};
1188 1205
1189 1206 exit 0;
↓ open down ↓ |
593 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX