#! /usr/bin/perl -w
# $Id: cklibc5.pl,v 1.2 1998/10/07 15:27:16 ray Exp $
# created by Torsten Duwe
# modified to fit in 'rpm -b' framework by Raymund Will

($C = $0) =~ s%.*/%%;

@Sections = (
  ".bss",
  ".comment",
  ".ctors",
  ".data",
  ".dtors",
  ".dynamic",
  ".dynstr",
  ".dynsym",
  ".eh_frame",
  ".fini",
  ".gcc_except_table",
  ".got",
  ".hash",
  ".init",
  ".interp",
  ".note",
  ".plt",
  ".rel.bss",
  ".rel.ctors",
  ".rel.data",
  ".rel.dtors",
  ".rel.eh_frame",
  ".rel.gcc_except_table",
  ".rel.got",
  ".rel.plt",
  ".rel.rodata",
  ".rel.stab",
  ".rel.text ",
  ".rodata",
  ".stab",
  ".stabstr",
  ".text",
);

%DontOmit = (
  ".dynstr", 1,
  ".interp", 1,
);

$OptErr = "";
%Fail = ();
$Err = 0;

if ( $#ARGV < $[ ) {
  $OptErr .= sprintf( "$C: missing parameter(s)\n");
} elsif ( $#ARGV > $[ ) {
  $OptErr .= sprintf( "$C: superfluous parameter(s)\n");
} else {
  $Dir = shift;
}
  
if ( $OptErr || ! defined($Dir) || ! -d "$Dir" ) {
  print( STDERR $OptErr) if ( $OptErr );
  die( "Usage: $C dir\n");
}

$Omit = "";
$OmitAllKnown = "";
foreach $i ( sort( @Sections) ) {
  $Known{$i} = 1;
  $OmitAllKnown .= "-R $i ";
  next if ( defined( $DontOmit{$i}) );
  $Omit .= "-R $i ";
}

open( FIND, "find $Dir -type f -print | sort|") || die;

while ( <FIND> ) {
  chop;

  # has to be readable 
  -r $_ || next;

  # has to be an ELF binary
  open(IN, "< $_");
  sysread(IN, $magic, 4);
  close(IN);
  $magic =~ m,\177ELF, || next;

  # unknown sections in the ELF file fill produce a non-empty var here:
  if ( `objcopy -O binary $_ /dev/fd/1 $OmitAllKnown 2>&1` ne "" ) {
    my @New = ();
    my $f = $_;
    open( IN, "objdump -h $f |") || die;
    while ( <IN> ) {
      my $n = /^\s+\d+ (\.\S+)/ || next;
      #next unless ( /^\s+\d+ (\.\S+)/ );
      next if ( defined( $Known{$1}) );
      push( @New, $1);
      $Known{$1} = 1;
      $Omit .= " -R $1";
      $OmitAllKnown .= " -R $1";
    }
    close( IN);
    if ( @New ) {
      print( STDERR "$C: $f: new unknown section(s): @New\n");
    }
    $_ = $f;
  }

  $INTERP = `objcopy -O binary $_ /dev/fd/1 $Omit -R .dynstr`;
  $DYNSTR = `objcopy -O binary $_ /dev/fd/1 $Omit -R .interp`;

  if ( $INTERP =~ m,/lib/ld-linux.so.1, ) {
    $Fail{$_} = "ld.so";
    $Err++;
  }

  if ( $DYNSTR =~ m,\000lib[cm].so.5\000, ) {
    if ( defined( $Fail{$_}) ) {
      $Fail{$_} .= " and libs";
    } else {
      $Fail{$_} = "old libs";
      $Err++;
    } 
  }
}
close( FIND);

if ( $Err ) {
  print( STDERR "WARNING: illegal references to old stuff in:\n");
  foreach $i ( sort( keys( %Fail)) ) {
    print( STDERR "  $i: $Fail{$i}\n");
  }
}
exit( $Err);
