blob: 1fa787e7a5ff2a8de11703d809f435c224a0a415 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001#!/usr/bin/perl
2
3#
4#//===----------------------------------------------------------------------===//
5#//
6#// The LLVM Compiler Infrastructure
7#//
8#// This file is dual licensed under the MIT and the University of Illinois Open
9#// Source Licenses. See LICENSE.txt for details.
10#//
11#//===----------------------------------------------------------------------===//
12#
13
14use strict;
15use warnings;
16
17use FindBin;
18use lib "$FindBin::Bin/lib";
19
20use Platform ":vars";
21use tools;
22
23our $VERSION = "0.004";
24
25my $hex = qr{[0-9a-f]}i; # hex digit.
26
27# lrb_32e-specific details.
28
29my $mic_arch; # either knf or knc
30my $mic_os; # either bsd or lin
31sub bad_lrb_fmt($) {
32 # Before we allowed both elf64-x86-64-freebsd and elf-l1om-freebsd.
33 # Now the first one is obsolete, only elf64-l1om-freebsd is allowed.
34 my ( $fmt ) = @_;
35 if ( 0 ) {
36 } elsif ( "$mic_os" eq "bsd" ) {
37 if ( "$mic_arch" eq "knf" ) {
38 return $fmt !~ m{\Aelf64-l1om(?:-freebsd)?\z};
39 } else {
40 return $fmt !~ m{\Aelf64-x86-64(?:-freebsd)?\z};
41 };
42 } elsif ( "$mic_os" eq "lin" ) {
43 if ( 0 ) {
44 } elsif ( "$mic_arch" eq "knf" ) {
45 return $fmt !~ m{\Aelf64-l1om?\z};
46 } elsif ( "$mic_arch" eq "knc" ) {
47 return $fmt !~ m{\Aelf64-k1om?\z};
48 } else {
49 return 1;
50 };
51 } else {
52 return 1;
53 };
54}; # sub bad_lrb_fmt
55
56# Undesired instructions for lrb: all x87 and some other.
57# AC: Since compiler 2010-06-30 x87 instructions are supported, removed the check of x87.
58my $lrb_bad_re;
59sub bad_lrb_instr($$) {
60 my ( $instr, $args ) = @_;
61# if ( "$mic_os" eq "lin" and "$mic_arch" eq "knf" ) {
62 if ( "$mic_os" eq "lin" or "$mic_arch" eq "knc" ) {
63 # workaround of bad code generation on KNF Linux* OS:
64 return ( defined( $instr ) and $instr =~ $lrb_bad_re );
65 } else {
66 return ( defined( $instr ) and $instr =~ $lrb_bad_re or defined( $args ) and $args =~ m{xmm}i );
67 }
68}; # sub bad_lrb_instr
69
70# lin_32-specific details.
71
72sub bad_ia32_fmt($) {
73 my ( $fmt ) = @_;
74 return $fmt !~ m{\Aelf32-i386\z};
75}; # sub bad_ia32_fmt
76
77my @sse2 =
78 qw{
79 movapd movupd movhpd movlpd movmskpd movsd
80 addpd addsd subpd subsd mulpd mulsd divpd divsd sqrtpd sqrtsd maxpd maxsd minpd minsd
81 andpd andnpd orpd xorpd
82 cmppd cmpsd comisd ucomisd
83 shufpd unpckhpd unpcklpd
84 cvtpd2pi cvttpd2pi cvtpi2pd cvtpd2dq cvttpd2dq cvtdq2pd cvtps2pd cvtpd2ps cvtss2sd cvtsd2ss
85 cvtsd2si cvttsd2si cvtsi2sd cvtdq2ps cvtps2dq cvttps2dq movdqa movdqu movq2dq movdq2q
86 pmuludq paddq psubq pshuflw pshufhw pshufd pslldq psrldq punpckhqdq punpcklqdq clflush
87 lfence mfence maskmovdqu movntpd movntdq movnti
88 };
89my @sse3 =
90 qw{
91 fisttp lddqu addsubps addsubpd haddps hsubps haddpd hsubpd movshdup movsldup movddup monitor
92 mwait
93 };
94my @ssse3 =
95 qw{
96 phaddw phaddsw phaddd phsubw phsubsw phsubd pabsb pabsw pabsd pmaddubsw pmulhrsw pshufb
97 psignb psignw psignd palignr
98 };
99my @sse4 =
100 (
101 # SSE4.1
102 qw{
103 pmulld pmuldq dppd dpps movntdqa blendpd blendps blendvpd blendvps pblendvb pblendw pminuw
104 pminud pminsb pminsd pmaxuw pmaxud pmaxsb pmaxsd roundps roundpd roundss roundsd extractps
105 insertps pinsrb pinsrd pinsrq pextrb pextrw pextrd pextrq pmovsxbw pmovzxbw pmovsxbd
106 pmovzxbd pmovsxwd pmovzxwd pmovsxbq pmovzxbq pmovsxwq pmovzxwq pmovsxdq pmovzxdq mpsadbw
107 phminposuw ptest pcmpeqq packusdw
108 },
109 # SSE4.2
110 qw{
111 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq crc32 popcnt
112 }
113 );
114
115# Undesired instructions for IA-32 architecture: Pentium 4 (SSE2) and newer.
116# TODO: It would be much more reliable to list *allowed* instructions rather than list undesired
117# instructions. In such a case the list will be stable and not require update when SSE5 is released.
118my @ia32_bad_list = ( @sse2, @sse3, @ssse3, @sse4 );
119
120my $ia32_bad_re = qr{@{[ "^(?:" . join( "|", @ia32_bad_list ) . ")" ]}}i;
121
122sub bad_ia32_instr($$) {
123 my ( $instr, $args ) = @_;
124 return ( defined( $instr ) and $instr =~ $ia32_bad_re );
125}; # sub bad_ia32_instr
126
127sub check_file($;$$) {
128
129 my ( $file, $show_instructions, $max_instructions ) = @_;
130 my @bulk;
131
132 if ( not defined( $max_instructions ) ) {
133 $max_instructions = 100;
134 }; # if
135
136 if ( "$mic_os" eq "bsd" ) {
137 execute( [ "x86_64-freebsd-objdump", "-d", $file ], -stdout => \@bulk );
138 } else {
139 execute( [ "objdump", "-d", $file ], -stdout => \@bulk );
140 }
141
142 my $n = 0;
143 my $errors = 0;
144 my $current_func = ""; # Name of current fuction.
145 my $reported_func = ""; # name of last reported function.
146 foreach my $line ( @bulk ) {
147 ++ $n;
148 if ( 0 ) {
149 } elsif ( $line =~ m{^\s*$} ) {
150 # Empty line.
151 # Ignore.
152 } elsif ( $line =~ m{^In archive (.*?):\s*$} ) {
153 # In archive libiomp5.a:
154 } elsif ( $line =~ m{^(?:.*?):\s*file format (.*?)\s*$} ) {
155 # libiomp5.so: file format elf64-x86-64-freebsd
156 # kmp_ftn_cdecl.o: file format elf64-x86-64
157 my $fmt = $1;
158 if ( bad_fmt( $fmt ) ) {
159 runtime_error( "Invalid file format: $fmt." );
160 }; # if
161 } elsif ( $line =~ m{^Disassembly of section (.*?):\s*$} ) {
162 # Disassembly of section .plt:
163 } elsif ( $line =~ m{^$hex+ <([^>]+)>:\s*$} ) {
164 # 0000000000017e98 <__kmp_str_format@plt-0x10>:
165 $current_func = $1;
166 } elsif ( $line =~ m{^\s*\.{3}\s*$} ) {
167 } elsif ( $line =~ m{^\s*($hex+):\s+($hex$hex(?: $hex$hex)*)\s+(?:lock\s+|rex[.a-z]*\s+)?([^ ]+)(?:\s+([^#]+?))?\s*(?:#|$)} ) {
168 # 17e98: ff 35 fa 7d 26 00 pushq 0x267dfa(%rip) # 27fc98 <_GLOBAL_OFFSET_TABLE>
169 my ( $addr, $dump, $instr, $args ) = ( $1, $2, $3, $4 );
170 # Check this is not a bad instruction and xmm registers are not used.
171 if ( bad_instr( $instr, $args ) ) {
172 if ( $errors == 0 ) {
173 warning( "Invalid instructions found in `$file':" );
174 }; # if
175 if ( $current_func ne $reported_func ) {
176 warning( " $current_func" );
177 $reported_func = $current_func;
178 }; # if
179 ++ $errors;
180 if ( $show_instructions ) {
181 warning( " $line" );
182 }; # if
183 if ( $errors >= $max_instructions ) {
184 info( "$errors invalid instructions found; scanning stopped." );
185 last;
186 }; # if
187 }; # if
188 } else {
189 runtime_error( "Error parsing objdump output line $n:\n>>>> $line\n" );
190 }; # if
191 }; # foreach $line
192
193 return $errors;
194
195}; # sub check_file
196
197# --------------------------------------------------------------------------------------------------
198
199# Parse command line.
200my $max_instructions;
201my $show_instructions;
202get_options(
203 "max-instructions=i" => \$max_instructions,
204 "show-instructions!" => \$show_instructions,
205 "mic-arch=s" => \$mic_arch,
206 "mic-os=s" => \$mic_os,
207 Platform::target_options(),
208);
209if ( "$mic_os" eq "lin" and "$mic_arch" eq "knf" ) {
210 $lrb_bad_re = qr{^(?:pause|[slm]fence|scatter|gather|cmpxchg16b|clevict[12])}i;
211} else {
212 $lrb_bad_re = qr{^(?:pause|[slm]fence|scatter|gather|cmov|cmpxchg16b|clevict[12])}i;
213};
214if ( 0 ) {
215} elsif ( $target_platform eq "lrb_32e" ) {
216 *bad_instr = \*bad_lrb_instr;
217 *bad_fmt = \*bad_lrb_fmt;
218} elsif ( $target_platform eq "lin_32" ) {
219 *bad_instr = \*bad_ia32_instr;
220 *bad_fmt = \*bad_ia32_fmt;
221} else {
222 runtime_error( "Only works on lin_32 and lrb_32e platforms." );
223}; # if
224
225# Do the work.
226my $rc = 0;
227if ( not @ARGV ) {
228 info( "No arguments specified -- nothing to do." );
229} else {
230 foreach my $arg ( @ARGV ) {
231 my $errs = check_file( $arg, $show_instructions, $max_instructions );
232 if ( $errs > 0 ) {
233 $rc = 3;
234 }; # if
235 }; # foreach $arg
236}; # if
237
238exit( $rc );
239
240__END__
241
242=pod
243
244=head1 NAME
245
246B<check-instruction-set.pl> -- Make sure binary file does not contain undesired instructions.
247
248=head1 SYNOPSIS
249
250B<check-instructions.pl> I<option>... I<file>...
251
252=head1 OPTIONS
253
254=over
255
256=item B<--architecture=>I<arch>
257
258Specify target architecture.
259
260=item B<--max-instructions=>I<number>
261
262Stop scanning if I<number> invalid instructions found. 100 by default.
263
264=item B<--os=>I<os>
265
266Specify target OS.
267
268=item B<-->[B<no->]B<show-instructions>
269
270Show invalid instructions found in the file. Bu default, instructions are not shown.
271
272=item Standard Options
273
274=over
275
276=item B<--doc>
277
278=item B<--manual>
279
280Print full help message and exit.
281
282=item B<--help>
283
284Print short help message and exit.
285
286=item B<--usage>
287
288Print very short usage message and exit.
289
290=item B<--verbose>
291
292Do print informational messages.
293
294=item B<--version>
295
296Print program version and exit.
297
298=item B<--quiet>
299
300Work quiet, do not print informational messages.
301
302=back
303
304=back
305
306=head1 ARGUMENTS
307
308=over
309
310=item I<file>
311
312File (object file or library, either static or dynamic) to check.
313
314=back
315
316=head1 DESCRIPTION
317
318The script runs F<objdump> utility to get disassembler listing and checks the file does not contain
319unwanted instructions.
320
321Currently the script works only for:
322
323=over
324
325=item C<lrb_32e>
326
327Intel(R) Many Integrated Core Architecture target OS. Undesired unstructions are: all x87 instructions and some others.
328
329=item C<lin_32>
330
331Undesired instructions are instructions not valid for Pentium 3 processor (SSE2 and newer).
332
333=back
334
335=cut
336