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