"Undefined reference to `mcount'" when trying to use -pg [Termux] - android

I've completed the first part of my project, and I want to know how well / bad it performs by profiling it with gprof. I am working on Android using a Linux emulator named Termux, and I am using g++ as the compiler.
Everything compiles without errors and even warnings, and the binary runs perfectly.
So I decided to put the -pg flag among the other flags in my makefile, (meaning that both compilation and linking is performed with -pg) and tried recompiling everything. But something seems to not work properly: during compilation, everything is normal. But when linking I get a argument unused during compilation: '-pg' warning and then a lot of undefined reference to 'mcount' (it doesn't even display all of them, after a bit it says more undefined references to 'mcount' follows) errors, and at the end a linker command failed with exit code 1 error.
What is causing this behaviour? Is something broken / missing on the platform I am using? Can I fix that? How?

Sorry for the short answer, but I'm on mobile. Making a community wiki.
In Termux, g++ is a symlink to clang. -pg is a gnu feature, so does not function when linking using clang.
You could use clang-appropriate techniques for profiling, or install a real g++. One reference is https://android.stackexchange.com/questions/182130/use-gcc-compiler-in-termux but there is also "google performance tools" for profiling out there somewhere.

Related

Prevent specific functions or classes from being removed through optimization in native code in release build version

On trying to build APK for 64bit devices, the compiler seems to do extra optimizations on native CPP code which is breaking some core functionalities of my app. When I build with the flag #set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O0") it works fine.
I'm trying to figure out
If I can prevent the compiler from doing the certain optimizations which break the functionalities.
or
If I can understand why compiler is seeing my code as un-used code via something like this
In the quest of achieving the first option, I tried using pragma pre-processor directive according to the answer here
- by using the line #pragma optimize("", off) before the required function,
- also by using the line #pragma GCC optimize ("O0") at the beginning of the file.
However, I see the same set of symbols in the shared library, and it seems to have no effect on the build process. It also seems that NDK r18 already has GCC version 4.9, which should mean pragma directive should work properly, but I can't figure out why it is failing.
I also tried using attribute
__attribute__((optimize("O0"))). But couldn't see the symbol get added to my shared library after this as well.
So I want to ask if either pragma or attribute(optimize) are still supported and if I am doing something wrong here. Or if there is a better way to solve this problem or to understand how to prevent compiler from optimizing the required functions.

Visual Studio Android building assembly files into app

We've got a Visual Studio Android solution with (among others) a static library project that contains functionality implemented in assembly. Like:
my.S -> libMine.a -> libMyApp.so
Some hoops (below) have already been jumped through, to get it to compile. Then, the linking of the main app shared library project fails (on both architectures that we care about - x64 and arm64), with undefined references to the functions that are implemented in [the] assembly [file].
It appears that Visual Studio (or its Cross Platform Mobile Dev / Android plug-in) doesn't handle assembly file project items quite correctly - treated as C/C++ Compiler files, it'll error out on the first dot character (i.e. in .text); and the Microsoft Macro Assembler is "not supported on this platform". So I looked into setting up a custom build step, with the following command:
$(ClangToolExe) %(FullPath) --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o
This will preprocess, compile and link - but with the wrong linker: instead of the one for the particular Android toolchain, it'll go for the one in my MinGW install, which doesn't recognise the emulation mode - anyway, that's not the location of my NDK toolchain.
We can skip the linking of the object for now (add -c to the above command). Much to our dismay, the resulting object file still doesn't get added to the static library, as confirmed by {Rest of the toolchain path}ar t libMine.a. And indeed, the library will have undefined symbols for our functions, as shown by {Rest of the toolchain path}objdump -t libMine.a.
Let's add the object file to the resulting library quite manually, as a post build step. Command:
$(ToolChainPrebuiltPath){Rest of the toolchain path}ar.exe ru $(TargetPath) $(IntDir)my.o
objdump -t libMine.a will now show that we've got the symbols. There is however also the *UND*efined pair.
Fast forward:
Adding my.o with ar rub otherObjectThatReferencesMyFunctions.o libMine.a, to have the good symbols show up before the undefined ones doesn't make a difference.
Linking my compiled assembly file with a second custom build step, $(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(IntDir)%(FileName).o -o $(IntDir)%(FileName).o doesn't make a meaningful difference.
Running the linker again on the static library, as a second post-build step $(ToolChainPrebuiltPath){Rest of the toolchain path}ld.exe $(TargetPath) doesn't make a meaningful difference.
The last two steps result in a warning about a missing symbol _start (entry point?). I'm guessing this is in reference to linking an executable, which we don't want.
What am I doing wrong? How can I resolve those undefined references?
What seems to have worked was to:
1, Make sure that the extension of the assembly file is .S, i.e. capital S. This is one of the few instances I've found, where the case of a filename matters on Windows.
2, Configure the project so that the assembly file is built with clang.exe {full/path/to/assembly.S, i.e. %(FullPath)} -c --target=$(ClangTarget) -g -o $(IntDir)%(FileName).o. In the case of VS Android, we need to specify the build output separately, which is the $(IntDir)%(FileName).o part all over again.
3, Run ar as a post build command: {correct toolchain}/ar.exe rus $(TargetPath) {output from assembly compilation}, for each assembly file.
One thing this solution is lacking is detecting [a lack of] changes, meaning that the assembly file will be rebuilt on each compilation, and everything that depends on it.

Git Built On Android Throws 'undefined reference to dlopen' Error

I'm building git on my Android device in KBOX2 using gcc 4.8 with libcurl, which I also built on device. I'm building with libcurl for http/https support
Configure, make and make install run successfully. However, when I try to clone an https git, I get the following error:
fakechroot: dlopen: undefined symbol: dlopen
I'm aware that fakechroot only intercepts dynamic libc calls. I've dynamically linked all of the supporting libs. What could be causing this error and how do I fix it?
Please let me know what I should post (env vars, configure and/or make options) that would be helpful.
The problem turned out to be rooted in curl...which also threw the same error when performing basic operations.
Short Answer: I scrapped everything...openssl, curl, git...and started over. I made sure that I included -ldl and -lc with all of the builds and I made sure to specify -Wl,--dynamic-linker=/system/bin/linker in the LDFLAGS with all of the builds.
Since I'm still learning about Linux and Android in general and various aspects of configure and make in particular, I'm not sure what fixed the problem. I'll leave this open in case someone with more knowledge wants to chime in.

OpenSSL Compiled to Run on Android x86 Architecture

I've been knocking my head against the wall this one: I've gotten openssl to compile just fine for the android armeabi architecture, but there's so much less aid for x86, and nothing on it that I can find on openSSL's site.
Something I eventually found was an intel article (https://software.intel.com/en-us/articles/using-intel-advanced-encryption-standard-new-instructions-on-android#openssl) on using openssl for x86 architecture's, and after creating a standalone toolchain, and going through their provided code and fixing some of it, I'm at the point where make will get almost all the way through compilation before failing with a bunch of undefined reference to 'XXX' statements. I cannot figure out how to get past this at this point, any help would be greatly appreciated.
I apologize if this ends up being somewhat trivial, I am very new to make.
Trace:
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: ts.o: in function ts_main:ts.c(.text+0x1e8a): error: undefined reference to 'TS_RESP_set_tst_info'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: ts.o: in function ts_main:ts.c(.text+0x1ea2): error: undefined reference to 'TS_TST_INFO_free'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: srp.o: in function srp_verify_user:srp.c(.text+0xb3): error: undefined reference to 'SRP_create_verifier'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: srp.o: in function srp_create_user:srp.c(.text+0x1e3): error: undefined reference to 'SRP_create_verifier'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: srp.o: in function srp_main:srp.c(.text+0x1014): error: undefined reference to 'X509_get_default_cert_area'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: srp.o: in function srp_main:srp.c(.text+0x10c0): error: undefined reference to 'SRP_get_default_gN'
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: srp.o: in function srp_main:srp.c(.text+0x16dd): error: undefined reference to 'TXT_DB_insert'
Edit:
Sorry, by the fact that they were specifying eabi in the setenv script, I thought that meant you could only select one of the ARM eabi's, since the other architectures weren't specified with it. I've been to openSSL's instructions on android for compiling ARM, but I wasn't aware it would also function for x86. If that's the case then I feel dumb.
I set the --sysroot option to the sysroot on the android independent keychain.
These are the commands I used for x86 compilation, as per the intel article on the subject.
export CC="$STANDALONE_TOOCHAIN_PATH/bin/i686-linux-android-gcc -mtune=atom -march=atom --sysroot=$STANDALONE_TOOCHAIN_PATH/sysroot"
export AR=$STANDALONE_TOOCHAIN_PATH/bin/i686-linux-android-ar
export RANLIB=/private/tmp/my-android-toolchain/bin/i686-li
./Configure android-x86 -DOPENSSL_IA32_SSE2 -DAES_ASM -DVPAES_ASM
It seems I've figured it out. Using the code I posted (as the code in the article is slightly syntactically incorrect, but the idea is right) and after having made a custom android toolchain, I was able to run make successfully after a fresh installation of OpenSSL. My guess is that the work I did on it in order to compile the ARM architecture *.a and *.so files probably goofed something up when I went back to it for the x86 architecture.
If unsure of how to create a standalone toolchain (use the easy way option): http://www.kandroid.org/ndk/docs/STANDALONE-TOOLCHAIN.html
but there's so much less aid for x86, and nothing on it that I can find on openSSL's site
I believe the OpenSSL wiki covers the topic: OpenSSL and Android.
Something I eventually found was an intel article... on using openssl for x86 architecture
You simply select the correct abi. According to the Android wiki page, you adjust the following in the setenv-android.sh script:
_ANDROID_NDK – the version of the NDK. For example, android-ndk-r8e
_ANDROID_EABI – the version of the EABI tools. For example, arm-linux-androideabi-4.6
_ANDROID_API – the API level. For example, android-14
There's an entire subsection on it at the wiki: Adjust the Cross-Compile Script. Please let us know if there are any gaps. (I tested it against ARM, but not x86).
There's plenty of ABI's to select. You probably want x86-4.6 and API 14 or API 18.
You might have to modify Configure, but it does not appear you are that far so its hard to say at the moment. You don't need to modify configure - the android-x86 target is already present.
/private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld: ts.o:
in function ts_main:ts.c(.text+0x1e8a): error: undefined reference to 'TS_RESP_set_tst_info' /private/tmp/my-android-toolchain/bin/../lib/gcc/i686-linux-android/4.6/../../../../i686-linux-android/bin/ld
This almost looks like you are missing --sysroot. Something is munged up for sure.
You should probably show us one of your compile line and a link line (what one of the C files looks like, not a dump of all of them).
I have a similar answer here https://stackoverflow.com/a/37043683/2210080 but this is for ArmV7. Just do the same procedure as what I did in the previous but use this particular setenv-android.sh script: https://github.com/rjmangubat23/OpenSSL/blob/master/x86/setenv-android.sh

Setting up an Android build environment for JNI applications

I've got a hold of a proprietary JNI application which I need to build for a MIPS device. I've read "Initializing a Build Environment", parts of the NDK docs, some Google Groups threads and numerous StackOverflow questions, but I'm still short of my answer.
So far, I've checked out the Android source using Google's repo script and have it under ~/AndroidSource. I've also separately downloaded the SDK under ~/AndroidSDK and the NDK under ~/AndroidNDK. The code I'm trying to build is in a separate location. The SDK and NDK binaries are in my path. For building, I tried to use two different versions of the NDK as well as the one under the Android source tree, and experienced different sets of problems. My current setup uses NDK r8b, downloaded separately from the Android source.
The application has its Android.mk and jni/Android.mk. However, several directives in the latter point to paths such as
frameworks/base/include
system/core/include
with no prefixes. I thought these were meant to point to the respective directories in the Android source, so I symlinked them to the current directory. After some more symlinking and makefile and source hacking, I got the application to compile, but am currently stuck on the linking phase with lots of references to missing method bodies. During the whole time I knew I was doing something wrong.
I'm on a Linux x86_64 host, if it is of any concern.
So my question is:
What is the proper method to set up a build environment for JNI applications? What environment variables, symlinks and/or path expansions should I set up? Do I need to call any scripts once or before each ndk-build invocation?
Also, I'd be happy if you corrected me on any concepts or terminology I've gotten wrong.
Your approach wiyh symlinking the AOSP tree for system headers is correct. What you need now are the system libraries compiled for MIPS. The easiest way to get them is to adb pull them from a target device (or emulator image). But you can also build these libraries yourself, as part of the AOSP build (see build instructions for the source tree you downloaded).
If you still have any problems remaining, run your ndk-build with parameter V=1 and publish the link command and its results.
I use the following in my build (YMMV).
Explicitly invoke arm-linux-androideabi-gcc as your compiler or linker (should be in PATH).
NDK_PLATFORM=/path/to/android-ndk-r*/platforms/android-14
Pass -I"$(NDK_PLATFORM)/arch-arm/usr/include" to the compiler
Pass -nostdlib -L"$(NDK_PLATFORM)/arch-arm/usr/lib/" -lgcc -lc -lm to the linker

Categories

Resources