Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x86 API level 16 and 17 incorrect ldexp result #507

Closed
m1h4 opened this issue Sep 4, 2017 · 10 comments
Closed

x86 API level 16 and 17 incorrect ldexp result #507

m1h4 opened this issue Sep 4, 2017 · 10 comments
Assignees
Milestone

Comments

@m1h4
Copy link

m1h4 commented Sep 4, 2017

Description

We are having problems with the boost multiprecision library failing to initialize which were traced to a call to std::ldexp which is returning NaN instead of 536870912 for a long double input: std::ldexp(0.5L, 30). Making the same call with a double input std::ldexp(0.5, 30) works fine.

Can be easily reproduced in a new vanila project with c++ support by pasting the above line in the generated native-lib.cpp.

As far as we've been able to test, this only occures on x86 api level 16 and 17. Higher api levels are not affected as well as arm7 abi-s.

  • NDK Version: 15.2.4203891
  • Build sytem: cmake
  • Host OS: Mac
  • Compiler: Clang
  • ABI: x86
  • STL: c++_static
  • NDK API level: 9
  • Device API level: 16 and 17, higher are not affected
@m1h4
Copy link
Author

m1h4 commented Sep 4, 2017

Just tested and the problem is also present with the latest 16.0.4293906-beta1 NDK.

@enh
Copy link
Contributor

enh commented Sep 7, 2017

interesting that you're seeing this with r16 too, because one difference there is that libandroid_support.a contains ldexpl for x86 in r16 but didn't in r15 (see #502).

@enh enh changed the title clang on API level 16 and 17 incorrect ldexp result x86 API level 16 and 17 incorrect ldexp result Sep 7, 2017
@m1h4
Copy link
Author

m1h4 commented Sep 9, 2017

Just checked and the problem is also present on API 10 and API 15 so basically any x86 image below API 18 (tested with 16.0.4293906-beta1).

To clarify the original report:
The problem seems to be the implementation of ldexpl for these API levels.
When the overloaded std::ldexp resolves to ldexp (when using a regular double input) the result is correct for the specified input values.

@enh
Copy link
Contributor

enh commented Sep 10, 2017

i suspect that

commit a0ee07829a9ba7e99ef68e8c12551301cc797f0f
Author: Elliott Hughes <[email protected]>
Date:   Wed Jan 30 19:06:37 2013 -0800

    Upgrade libm.
    
    This brings us up to date with FreeBSD HEAD, fixes various bugs, unifies
    the set of functions we support on ARM, MIPS, and x86, fixes "long double",
    adds ISO C99 support, and adds basic unit tests.
    
    It turns out that our "long double" functions have always been broken
    for non-normal numbers. This patch fixes that by not using the upstream
    implementations and just forwarding to the regular "double" implementation
    instead (since "long double" on Android is just "double" anyway, which is
    what BSD doesn't support).
    
    All the tests pass on ARM, MIPS, and x86, plus glibc on x86-64.
    
    Bug: 3169850
    Bug: 8012787
    Bug: https://code.google.com/p/android/issues/detail?id=6697
    Change-Id: If0c343030959c24bfc50d4d21c9530052c581837

fixed ldexpl for x86 (by fixing the scalbn family). that's pretty much the last time that any of these functions changed, and it would tie in well with the API 18 release date.

the odd part here is that the r16beta1 libandroid_support.a should include an ldexpl. ah, except it's a weak reference. and i guess i don't know what that resolves to at run time. (though your example suggests "the incorrect copy in libm".)

that presumably means that none of

$ nm ./sources/cxx-stl/llvm-libc++/libs/x86/libandroid_support.a | grep -w W
00000000 W acosl
00000000 W acoshl
00000000 W asinl
00000000 W atan2l
00000000 W atanhl
00000000 W coshl
00000000 W expl
00000000 W hypotl
00000000 W lgammal
00000000 W logl
00000000 W log10l
00000000 W log2l
00000000 W remainderl
00000000 W sinhl
00000000 W sqrtl
00000000 W asinhl
00000000 W atanl
00000000 W cbrtl
00000000 W cosl
00000000 W erfcl
00000000 W erfl
00000000 W exp2l
00000000 W expm1l
00000000 W log1pl
00000000 W logbl
00000000 W nextafterl
00000000 W nexttoward
00000000 W nexttowardl
00000000 W remquol
00000000 W rintl
00000000 W sinl
00000000 W tanl
00000000 W tanhl
00000000 W ldexpl
00000000 W scalbnl

are actually helping. maybe we do want to fix https://issuetracker.google.com/64450768 and use _RENAME for all the <math.h> *l functions sooner rather than later...

presumably if you edit <math.h> to say

long double ldexpl(long double __x, int __exponent) __RENAME(ldexp);

then your code works?

i think we want to add a __RENAME32 (or somesuch) so we can add these annotations to all the long double functions in <math.h> (since double == long double for Android LP32), which will make all this nonsense go away and let us shrink libandroid_support.a still further...

@m1h4
Copy link
Author

m1h4 commented Sep 10, 2017

Yes, replacing ldexpl calls with ldexp works fine for the given problematic inputs in our use-case (boost::multiprecision). What you are saying sounds like the way to go in fixing these issues (aliasing the long double functions to double).

This is the output of objdump on a empty new c++ android project with a call to ldexpl added to the generated native code:

i686-linux-android-objdump -TC libnative-lib.so 

libnative-lib.so:     file format elf32-i386

DYNAMIC SYMBOL TABLE:
00000000      DF *UND*	00000000  LIBC        __cxa_finalize
00000000      DF *UND*	00000000  LIBC        __cxa_atexit
00000000      DF *UND*	00000000  LIBC        __stack_chk_fail
000004a0 g    DF .text	00000059  Base        Java_com_sample_myapplication_MainActivity_stringFromJNI
00000000      DF *UND*	00000000  LIBC        ldexpl
00002004 g    D  *ABS*	00000000  Base        _edata
00002004 g    D  *ABS*	00000000  Base        _end
00002004 g    D  *ABS*	00000000  Base        __bss_start

We can see that the call is not handled through libandroid_support.a but is linked dynamically to the (buggy) system libm.so...

@enh enh self-assigned this Sep 11, 2017
@enh
Copy link
Contributor

enh commented Sep 14, 2017

https://android-review.googlesource.com/#/c/platform/bionic/+/485247 is the proposed fix (in the platform).

@m1h4
Copy link
Author

m1h4 commented Sep 15, 2017

Thanks for the update!

How does this impact the NDK exactly? Does the NDK get packaged with the headers from platform/bionic or? Can we expect the next beta release of the r16 NDK to have these changes included?

@enh
Copy link
Contributor

enh commented Sep 15, 2017

TL;DR, yes, we hope to get this into r16beta2.

step 1 is for me to submit the change mentioned above. step 2 is that we run a script that copies all the latest headers into the NDK. step 3 is to cherrypick that batch of new headers to the r16 release branch.

step 0 though is for me to manually cherrypick my libc change into my NDK and check that it doesn't break anything (it seems quite likely to upset the current libandroid_support), and fix libandroid_support appropriately.

@m1h4
Copy link
Author

m1h4 commented Sep 15, 2017

Ok, thank you for the clarification!

hubot pushed a commit to aosp-mirror/platform_bionic that referenced this issue Sep 19, 2017
We can cut a lot of stuff out of the NDK's libandroid_support with this,
and reduce unnecessary relocations for all LP32 code. LP64 code should
be unaffected.

Bug: https://issuetracker.google.com/64450768
Bug: android/ndk#507
Test: ran tests, plus manual readelf on the _test.o files
Change-Id: I3de6015921195304ea9c829ef31665cd34664066
@enh
Copy link
Contributor

enh commented Sep 30, 2017

i think at this point everything's done and this should be in beta2...

@DanAlbert DanAlbert added this to the r16 milestone Oct 3, 2017
miodragdinic pushed a commit to MIPS/ndk that referenced this issue Apr 17, 2018
Bug: https://issuetracker.google.com/64450768
Bug: android/ndk#507
Test: built tests
Change-Id: I49b8a6008e5131b054eb1eefe0a0130699e3b082
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants