Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | |
| 3 | # |
| 4 | #//===----------------------------------------------------------------------===// |
| 5 | #// |
Chandler Carruth | 57b08b0 | 2019-01-19 10:56:40 +0000 | [diff] [blame] | 6 | #// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 7 | #// See https://llvm.org/LICENSE.txt for license information. |
| 8 | #// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 9 | #// |
| 10 | #//===----------------------------------------------------------------------===// |
| 11 | # |
| 12 | |
| 13 | use strict; |
| 14 | use warnings; |
| 15 | |
| 16 | use FindBin; |
| 17 | use lib "$FindBin::Bin/lib"; |
| 18 | |
| 19 | use tools; |
| 20 | |
| 21 | our $VERSION = "0.002"; |
Jonathan Peyton | 4c91ad1 | 2016-01-26 19:44:31 +0000 | [diff] [blame] | 22 | my $target_arch; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 23 | |
| 24 | sub execstack($) { |
| 25 | my ( $file ) = @_; |
| 26 | my @output; |
| 27 | my @stack; |
Andrey Churbanov | d315cea | 2015-01-16 12:54:51 +0000 | [diff] [blame] | 28 | my $tool; |
| 29 | if($target_arch eq "mic") { |
| 30 | $tool = "x86_64-k1om-linux-readelf"; |
| 31 | } else { |
| 32 | $tool = "readelf"; |
| 33 | } |
| 34 | execute( [ $tool, "-l", "-W", $file ], -stdout => \@output ); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 35 | @stack = grep( $_ =~ m{\A\s*(?:GNU_)?STACK\s+}, @output ); |
| 36 | if ( not @stack ) { |
| 37 | # Interpret missed "STACK" line as error. |
| 38 | runtime_error( "$file: No stack segment found; looks like stack would be executable." ); |
| 39 | }; # if |
| 40 | if ( @stack > 1 ) { |
| 41 | runtime_error( "$file: More than one stack segment found.", "readelf output:", @output, "(eof)" ); |
| 42 | }; # if |
| 43 | # Typical stack lines are: |
| 44 | # Linux* OS IA-32 architecture: |
| 45 | # GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 |
| 46 | # Linux* OS Intel(R) 64: |
| 47 | # GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x8 |
| 48 | 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} ) { |
| 49 | runtime_error( "$file: Cannot parse stack segment line:", ">>> $stack[ 0 ]" ); |
| 50 | }; # if |
| 51 | my $attrs = $1; |
| 52 | if ( $attrs =~ m{E} ) { |
| 53 | runtime_error( "$file: Stack is executable" ); |
| 54 | }; # if |
| 55 | }; # sub execstack |
| 56 | |
| 57 | get_options( |
Jonathan Peyton | 4c91ad1 | 2016-01-26 19:44:31 +0000 | [diff] [blame] | 58 | "arch=s" => \$target_arch, |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 59 | ); |
| 60 | |
| 61 | foreach my $file ( @ARGV ) { |
| 62 | execstack( $file ); |
| 63 | }; # foreach $file |
| 64 | |
| 65 | exit( 0 ); |
| 66 | |
| 67 | __END__ |
| 68 | |
| 69 | =pod |
| 70 | |
| 71 | =head1 NAME |
| 72 | |
| 73 | B<check-execstack.pl> -- Check whether stack is executable, issue an error if so. |
| 74 | |
| 75 | =head1 SYNOPSIS |
| 76 | |
| 77 | B<check-execstack.pl> I<optiion>... I<file>... |
| 78 | |
| 79 | =head1 DESCRIPTION |
| 80 | |
| 81 | The script checks whether stack of specified executable file, and issues error if stack is |
| 82 | executable. If stack is not executable, the script exits silently with zero exit code. |
| 83 | |
| 84 | The script runs C<readelf> utility to get information about specified executable file. So, the |
| 85 | script fails if C<readelf> is not available. Effectively it means the script works only on Linux* OS |
| 86 | (and, probably, Intel(R) Many Integrated Core Architecture). |
| 87 | |
| 88 | =head1 OPTIONS |
| 89 | |
| 90 | =over |
| 91 | |
| 92 | =item Standard Options |
| 93 | |
| 94 | =over |
| 95 | |
| 96 | =item B<--doc> |
| 97 | |
| 98 | =item B<--manual> |
| 99 | |
| 100 | Print full help message and exit. |
| 101 | |
| 102 | =item B<--help> |
| 103 | |
| 104 | Print short help message and exit. |
| 105 | |
| 106 | =item B<--usage> |
| 107 | |
| 108 | Print very short usage message and exit. |
| 109 | |
| 110 | =item B<--verbose> |
| 111 | |
| 112 | Do print informational messages. |
| 113 | |
| 114 | =item B<--version> |
| 115 | |
| 116 | Print program version and exit. |
| 117 | |
| 118 | =item B<--quiet> |
| 119 | |
| 120 | Work quiet, do not print informational messages. |
| 121 | |
| 122 | =back |
| 123 | |
| 124 | =back |
| 125 | |
| 126 | =head1 ARGUMENTS |
| 127 | |
| 128 | =over |
| 129 | |
| 130 | =item I<file> |
| 131 | |
| 132 | A name of executable or shared object to check. Multiple files may be specified. |
| 133 | |
| 134 | =back |
| 135 | |
| 136 | =head1 EXAMPLES |
| 137 | |
Jonathan Peyton | f0efbb5 | 2015-06-01 02:41:44 +0000 | [diff] [blame] | 138 | Check libomp.so library: |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 139 | |
Jonathan Peyton | f0efbb5 | 2015-06-01 02:41:44 +0000 | [diff] [blame] | 140 | $ check-execstack.pl libomp.so |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 141 | |
| 142 | =cut |
| 143 | |
| 144 | # end of file # |
| 145 | |