Bug 9172 - ARM softfp mode broken, floating point values are mangled when using --trace
Summary: ARM softfp mode broken, floating point values are mangled when using --trace
Alias: None
Product: Runtime
Classification: Mono
Component: JIT ()
Version: unspecified
Hardware: Other Linux
: --- normal
Target Milestone: ---
Assignee: Alex Rønne Petersen
Depends on:
Reported: 2012-12-31 18:02 UTC by Andrew Paprocki
Modified: 2014-04-30 21:49 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Andrew Paprocki 2012-12-31 18:02:37 UTC
Description of Problem:

Some Synology NAS products (e.g. DS409) have a Marvell ARM CPU:
[    0.000000] CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977

This CPU does not have an FPU and requires softfp emulation. I believe this software emulation is broken, leading to runtime errors in Mono when floating point values are accessed on this CPU. 

Steps to reproduce the problem:

The StringDictionary class uses a default floating point value for its 'loadFactor'. Simply attempting to construct a StringDictionary on this CPU leads to a runtime ArgumentOutOfRange exception, even though one is not being specified and the CLR is using the default value.

Test case:

$ cat test.cs
public class Test { public static void Main() {
  new System.Collections.Specialized.StringDictionary();
} }
$ mcs test.cs
$ mono --trace test.exe
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentOutOfRangeException: load factor
Parameter name: loadFactor
  at System.Collections.Hashtable..ctor (Int32 capacity, Single loadFactor, IHashCodeProvider hcp, IComparer comparer) [0x00000] in <filename unknown>:0 
  at System.Collections.Hashtable..ctor (Int32 capacity, Single loadFactor) [0x00000] in <filename unknown>:0 
  at System.Collections.Hashtable..ctor () [0x00000] in <filename unknown>:0 
  at System.Collections.Specialized.StringDictionary..ctor () [0x00000] in <filename unknown>:0 
  at Test.Main () [0x00000] in <filename unknown>:0 

How often does this happen? 

Floating point operations fail 100% of the time.

Additional Information:

$ cat /proc/cpuinfo
cat /proc/cpuinfo
Processor	: Feroceon 88FR131 rev 1 (v5l)
BogoMIPS	: 1192.75
Features	: swp half thumb fastmult edsp 
CPU implementer	: 0x56
CPU architecture: 5TE
CPU variant	: 0x2
CPU part	: 0x131
CPU revision	: 1

Hardware	: Feroceon-KW
Revision	: 0000
Serial		: 0000000000000000
Comment 1 Andrew Paprocki 2012-12-31 18:36:49 UTC
I believe this is the relevant Hashtable constructor --trace output showing that the 1.0f constant is 0.0:

[0x4001f0a0: 0.03804 4] LEAVE: System.Collections.Hashtable:.cctor ()                                                                                                       
[0x4001f0a0: 0.03810 3] LEAVE: (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr)[OBJECT:(nil)]                                              
[0x4001f0a0: 0.03820 3] ENTER: System.Collections.Hashtable:.ctor ()() ip: (nil)                                                                                            
[0x4001f0a0: 0.03889 4] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4_arg (double)() ip: (nil)                                                    
[0x4001f0a0: 0.03898 4] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4_arg (double)result=1065353216                                               
[0x4001f0a0: 0.03990 4] ENTER: System.Collections.Hashtable:.ctor (int,single)() ip: (nil)                                                                                  
[0x4001f0a0: 0.04061 5] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)() ip: (nil)                                                        
[0x4001f0a0: 0.04066 5] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)FP=0.000000                                                         
[0x4001f0a0: 0.04074 5] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4_arg (double)() ip: (nil)                                                    
[0x4001f0a0: 0.04079 5] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4_arg (double)result=0                                                        
[0x4001f0a0: 0.04924 5] ENTER: System.Collections.Hashtable:.ctor (int,single,System.Collections.IHashCodeProvider,System.Collections.IComparer)() ip: (nil)                
[0x4001f0a0: 0.04930 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)() ip: (nil)                                                        
[0x4001f0a0: 0.04935 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)FP=0.000000                                                         
[0x4001f0a0: 0.05015 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper___emul_fcmp_lt (double,double)() ip: (nil)                                                
[0x4001f0a0: 0.05023 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper___emul_fcmp_lt (double,double)result=1                                                    
[0x4001f0a0: 0.05090 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper_helper_ldstr_mscorlib (intptr)() ip: (nil)                                                
[0x4001f0a0: 0.05101 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_helper_ldstr_mscorlib (intptr)[System.String:0x406392a0]                                  
[0x4001f0a0: 0.05108 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)() ip: (nil)                                                        
[0x4001f0a0: 0.05113 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fload_r4 (intptr)FP=0.000000                                                         
[0x4001f0a0: 0.05179 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_object_new_ptrfree_box (intptr)() ip: (nil)                                          
[0x4001f0a0: 0.05185 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_object_new_ptrfree_box (intptr)[System.Single:0x40639790]                            
[0x4001f0a0: 0.05249 6] ENTER: (wrapper managed-to-native) object:__icall_wrapper_mono_fstore_r4 (double,intptr)() ip: (nil)                                                
[0x4001f0a0: 0.05255 6] LEAVE: (wrapper managed-to-native) object:__icall_wrapper_mono_fstore_r4 (double,intptr)                                                            
[0x4001f0a0: 0.05956 6] ENTER: (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr)() ip: (nil)
Comment 2 Andrew Paprocki 2013-01-01 14:39:38 UTC
This only appears to happen when --trace is used. When --trace is not specified, the 1.0f is passed properly, but with --trace, zero is being passed to the fcmp_lt.
Comment 3 Alex Rønne Petersen 2013-08-23 17:27:37 UTC
Quite possibly related: We use `__builtin_return_address(1)` in our trace code, but the value `1` is not supported on ARM. As such, GCC is allowed to pretty much eat your laundry according to the documentation: http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
Comment 4 Alex Rønne Petersen 2013-08-23 17:32:40 UTC
Andrew, getting a hold of ARM hardware without an FPU is pretty hard these days. Would you be able to set me up with SSH access to a machine like this, or ship one to me (Denmark)? Whatever works for you.

Comment 5 Andrew Paprocki 2013-08-24 09:43:17 UTC
I would not be able to give SSH access to this particular device, although I could perform any necessary tests on it. The Synology DSx09 NAS series all use this particular ARM. I am not sure if any of these devices are available used in Denmark. The smallest is the DS209 unit, which only has 2 drives.
Comment 6 Alex Rønne Petersen 2013-11-22 05:57:42 UTC
I would need a machine that I can actually develop and test on incrementally, as this is a very subtle issue. Otherwise the turnaround time would be very painful and wasteful.
Comment 7 Alex Rønne Petersen 2014-04-30 21:49:04 UTC
Some fixes have been made to the ARM --trace code in master. They may or may not fix this. --trace is mostly a debugging facility and isn't actually guaranteed to work in all cases (yet). Given that and the fact that I don't have access to a system to debug this on, I'll close this bug.