Bug 21762

Summary: Use of STABS directives on MIPS causes label to be incorrectly marked as MIPS16
Product: binutils Reporter: James Cowgill <jcowgill+sourceware>
Component: gasAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: macro
Priority: P2    
Version: 2.28   
Target Milestone: 2.30   
Host: Target:
Build: Last reconfirmed:

Description James Cowgill 2017-07-12 15:53:54 UTC
On MIPS, attempting to use a STABS directive (.stabs, .stabn or .stabd) before a .set directive has occured in the input file, causes any preceding labels to be marked as MIPS16.

> $ cat test.s
> main:
> 	.stabd 0, 0, 0
> $ mips-linux-gnu-as test.s -o test.o
> $ readelf --syms test.o | grep main
>      4: 00000000     0 NOTYPE  LOCAL  DEFAULT [MIPS16]     1 main

Passing -no-mips16 causes as to emit a micromips symbol instead:
> $ mips-linux-gnu-as -no-mips16 test.s -o test.o
> $ readelf --syms test.o | grep main
>      4: 00000000     0 NOTYPE  LOCAL  DEFAULT [MICROMIPS]     1 main

Using some noop .set directive before the .stabd works around the bug:
> $ cat test.s
> main:
> 	.set mips0
> 	.stabd 0, 0, 0
> $ mips-linux-gnu-as test.s -o test.o
> $ readelf --syms test.o | grep main
>      4: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 main
Comment 1 James Cowgill 2017-07-12 16:05:45 UTC
> Breakpoint 1, mips_compressed_mark_label (label=0x555555a599e0) at ../../binutils-gdb/gas/config/tc-mips.c:4389
> 4389	  gas_assert (HAVE_CODE_COMPRESSION);
> (gdb) bt
> #0  mips_compressed_mark_label (label=0x555555a599e0) at ../../binutils-gdb/gas/config/tc-mips.c:4389
> #1  0x0000555555606353 in mips_compressed_mark_labels () at ../../binutils-gdb/gas/config/tc-mips.c:4414
> #2  0x0000555555601663 in mips_mark_labels () at ../../binutils-gdb/gas/config/tc-mips.c:1944
> #3  0x00005555556291e9 in s_mips_stab (type=100) at ../../binutils-gdb/gas/config/tc-mips.c:17152
> #4  0x00005555555eb667 in read_a_source_file (name=0x7fffffffe2e9 "test.s") at ../../binutils-> gdb/gas/read.c:1146
> #5  0x00005555555cc4ab in perform_an_assembly_pass (argc=0, argv=0x5555559f6f08) at ../../binutils-> gdb/gas/as.c:1172
> #6  0x00005555555cc75c in main (argc=2, argv=0x5555559f6f00) at ../../binutils-gdb/gas/as.c:1297
> (gdb) p mips_opts.mips16
> $1 = -1

So the "if (mips_opts.mips16)" condition is true and the label gets marked as MIPS16.

My guess is that one of the functions in the above call chain needs a call to "file_mips_check_options" adding to it.
Comment 2 Sourceware Commits 2017-09-21 23:55:46 UTC
The master branch has been updated by Maciej W. Rozycki <macro@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=42c0794e961fd7922ad1358bd7221a8c85278ccc

commit 42c0794e961fd7922ad1358bd7221a8c85278ccc
Author: James Cowgill <James.Cowgill@imgtec.com>
Date:   Fri Sep 22 00:54:19 2017 +0100

    PR gas/21762: MIPS: Fix .stabs directive marking labels as MIPS16
    
    If a .stabs directive was used before another .set directive in a MIPS
    source file, s_mips_stab would call mips_mark_labels without having
    initialized the mips_opts structure yet.  Fix this by calling
    file_mips_check_options which will initialize mips_opts if necessary.
    
    gas/
    	PR gas/21762
    	* config/tc-mips.c (s_mips_stab): Insert call to
    	file_mips_check_options.
    	* testsuite/gas/mips/micromips@stabs-symbol-type.d: New test.
    	* testsuite/gas/mips/mips.exp: Run the new tests.
    	* testsuite/gas/mips/mips16@stabs-symbol-type.d: New test.
    	* testsuite/gas/mips/stabs-symbol-type.d: New test.
    	* testsuite/gas/mips/stabs-symbol-type.s: New test source.
Comment 3 Maciej W. Rozycki 2017-09-22 00:08:52 UTC
Fixed.