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