| #!/usr/bin/env perl | 
 |  | 
 | # | 
 | #//===----------------------------------------------------------------------===// | 
 | #// | 
 | #// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | #// See https://llvm.org/LICENSE.txt for license information. | 
 | #// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | #// | 
 | #//===----------------------------------------------------------------------===// | 
 | # | 
 |  | 
 | use strict; | 
 | use warnings; | 
 |  | 
 | use FindBin; | 
 | use lib "$FindBin::Bin/lib"; | 
 |  | 
 | use tools; | 
 |  | 
 | our $VERSION = "0.002"; | 
 | my $target_arch; | 
 |  | 
 | sub execstack($) { | 
 |     my ( $file ) = @_; | 
 |     my @output; | 
 |     my @stack; | 
 |     my $tool; | 
 |     if($target_arch eq "mic") { | 
 |         $tool = "x86_64-k1om-linux-readelf"; | 
 |     } else { | 
 |         $tool = "readelf"; | 
 |     } | 
 |     execute( [ $tool, "-l", "-W", $file ], -stdout => \@output ); | 
 |     @stack = grep( $_ =~ m{\A\s*(?:GNU_)?STACK\s+}, @output ); | 
 |     if ( not @stack ) { | 
 |         # Interpret missed "STACK" line as error. | 
 |         runtime_error( "$file: No stack segment found; looks like stack would be executable." ); | 
 |     }; # if | 
 |     if ( @stack > 1 ) { | 
 |         runtime_error( "$file: More than one stack segment found.", "readelf output:", @output, "(eof)" ); | 
 |     }; # if | 
 |     # Typical stack lines are: | 
 |     # Linux* OS IA-32 architecture: | 
 |     #    GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 | 
 |     # Linux* OS Intel(R) 64: | 
 |     #    GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x8 | 
 |     if ( $stack[ 0 ] !~ m{\A\s*(?:GNU_)?STACK(?:\s+0x[0-9a-f]+){5}\s+([R ][W ][E ])\s+0x[0-9a-f]+\s*\z} ) { | 
 |         runtime_error( "$file: Cannot parse stack segment line:", ">>> $stack[ 0 ]" ); | 
 |     }; # if | 
 |     my $attrs = $1; | 
 |     if ( $attrs =~ m{E} ) { | 
 |         runtime_error( "$file: Stack is executable" ); | 
 |     }; # if | 
 | }; # sub execstack | 
 |  | 
 | get_options( | 
 |     "arch=s" => \$target_arch, | 
 | ); | 
 |  | 
 | foreach my $file ( @ARGV ) { | 
 |     execstack( $file ); | 
 | }; # foreach $file | 
 |  | 
 | exit( 0 ); | 
 |  | 
 | __END__ | 
 |  | 
 | =pod | 
 |  | 
 | =head1 NAME | 
 |  | 
 | B<check-execstack.pl> -- Check whether stack is executable, issue an error if so. | 
 |  | 
 | =head1 SYNOPSIS | 
 |  | 
 | B<check-execstack.pl> I<option>... I<file>... | 
 |  | 
 | =head1 DESCRIPTION | 
 |  | 
 | The script checks whether stack of specified executable file, and issues error if stack is | 
 | executable. If stack is not executable, the script exits silently with zero exit code. | 
 |  | 
 | The script runs C<readelf> utility to get information about specified executable file. So, the | 
 | script fails if C<readelf> is not available. Effectively it means the script works only on Linux* OS | 
 | (and, probably, Intel(R) Many Integrated Core Architecture). | 
 |  | 
 | =head1 OPTIONS | 
 |  | 
 | =over | 
 |  | 
 | =item Standard Options | 
 |  | 
 | =over | 
 |  | 
 | =item B<--doc> | 
 |  | 
 | =item B<--manual> | 
 |  | 
 | Print full help message and exit. | 
 |  | 
 | =item B<--help> | 
 |  | 
 | Print short help message and exit. | 
 |  | 
 | =item B<--usage> | 
 |  | 
 | Print very short usage message and exit. | 
 |  | 
 | =item B<--verbose> | 
 |  | 
 | Do print informational messages. | 
 |  | 
 | =item B<--version> | 
 |  | 
 | Print program version and exit. | 
 |  | 
 | =item B<--quiet> | 
 |  | 
 | Work quiet, do not print informational messages. | 
 |  | 
 | =back | 
 |  | 
 | =back | 
 |  | 
 | =head1 ARGUMENTS | 
 |  | 
 | =over | 
 |  | 
 | =item I<file> | 
 |  | 
 | A name of executable or shared object to check. Multiple files may be specified. | 
 |  | 
 | =back | 
 |  | 
 | =head1 EXAMPLES | 
 |  | 
 | Check libomp.so library: | 
 |  | 
 |     $ check-execstack.pl libomp.so | 
 |  | 
 | =cut | 
 |  | 
 | # end of file # | 
 |  |