How is a symbol name generated in a .so (shared library) file? - android

How are the names that appear for a symbol generated in a shared library file? For example, when using elfread -Ws to read the symbols in the libutils.so file (android system utils library), I get several symbol names of the format:
_ZN7android10VectorImpl14insertVectorAtERKS0_j
etc. How do you decipher this symbol name?

That appears to be a mangled name, e.g., for C++, and you can make better sense of those using the -C option of nm:
-C
--demangle[=style]
Decode (demangle) low-level symbol names into user-level names. Besides removing any initial underscore prepended by the system, this makes C++ function names readable. Different compilers have different mangling styles. The optional demangling style argument can be used to choose an appropriate demangling style for your compiler. See c++filt, for more information on demangling.
When using nm on shared libraries, this option shows their symbols:
-D
--dynamic
Display the dynamic symbols rather than the normal symbols. This is only meaningful for dynamic objects, such as certain types of shared libraries.

Related

How to add rpath $ORIGIN to native executable for android cross build

I am trying to build an executable for Android with cross compiling, everything works but the executable complains that it could not find the .so file it needs, which is in the same directory as the executable.
So what I did is to add the following lines
set(TARGET myapp)
# following 4 lines added to add RPATH of ./ to the binary
# so it searches the .so in the same directory
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_SKIP_RPATH FALSE)
set(CMAKE_INSTALL_RPATH $ORIGIN)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
# add source code to target
add_executable(${TARGET} src.cpp)
...
However, it builds the executable, but RPATH seems not working no matter how I play with the four lines above, I just could not find any RPATH info in the binary using readelf or objdump.
I also tried set_target_properties(${TARGET} PROPERTIES INSTALL_RPATH $ORIGIN) but still not working.
Did I miss use anything here for RPATH configuration?
update
just to note that if I build the app for host(Linux) (using the same cmake file except using the android ndk tool chain) then everything is fine, I see $ORIGIN in the binary RPATH using readelf.
although i dont know what is been done in android ndk tool chain
This is probably not what you want:
(I am mentioning it just to be complete with my answer)
I assume that $ORIGIN is an environment variable. If that is the case you need to explain to CMake that it is such an variable. You can use $ENV{VAR} to do this, e.g.:
set(CMAKE_INSTALL_RPATH $ENV{ORIGIN})
This is probably what you want:
Ofcourse if the variable is not accessible during CMake generation step. You can try to use bracket arguments, however I do not think that alone would work (see last note at the bottom). Bracket arguments [=[...]=] tell CMake to skip the evaluation, because $ is a special character. e.g.:
set(CMAKE_INSTALL_RPATH [=[$ORIGIN]=])
To understand what [=[]=] do here is a simple example:
set(FOO "bar")
message(STATUS ${FOO})
message(STATUS [=[${FOO}]=])
Should output
bar
${FOO} #<-- evaluation of ${FOO} was skipped
Also if I'm not mistaken you also need to pass $ORIGIN to linker with single quotes so that it doesn't get evaluated during linking, i.e.
'$ORIGIN'
#and not $ORIGIN

Symbol from C file is not being added even though the MakeFile includes its object file

I'm trying to build libavformat with this MAKEFILE. Although the makefile includes avio.o file in its build instruction but it doesn't add any symbol for the functions that are declared on the header file url.h. Source folder which includes the avio.c, avio.h and url.h files can be found HERE.
The nm command for avio.o returns
nm: avio.o: File format not recognized
file command on avio.o shows the following output
avio.o: LLVM IR bitcode
I have checked the nm command on the generated libavformat.so and did not find any symbols for the functions declared on the url.h file
I have been stuck on this for two days. Could not figure out how to solve this problem!
Calling the ff_check_interrupt method and results in
undefined reference to 'ff_check_interrupt'
Configurations and flags.
FFmpeg Configuration File: Config.h
FFmpeg Root MakeFile: Root MakeFile
CC, CXX, CFLAGS, LDFLAGS: FLAGS
First off, a function declared by url.h should be defined in url.c, not in avio.c.
Second the only use of the ff_check_interrupt in avoi.c is within a static inline function, so indeed the toolchain is likely optimizing this symbol away.
I think what's occurring for you is that the toolchain making the decision that this is only used in this compilation unit.
Moving the definition of ff_check_interrupt to 'url.c' should resolve the issue. This is a library though, so out of your control.
However, this doesn't answer why thousands of users on Github have this same library in their code. I'd suggest comparing your Makefile against those (e.g. first search return is this one.

Disable compiler optimization for a variable in JNI C code

I have a variable definition in an Android JNI C function that does nothing but define itself as a string. I want this string to appear in the binary, but when I build the project, the .so file does not contain the string.
Here's what I've tried in the C code.
#pragma GCC push_options
#pragma GCC optimize ("O0")
const char volatile myString[32] = "Some string that must be there";
#pragma GCC pop_options
How can I get disable the compiler from optimizing away this unused variable definition?
I suspect that your problem is not with the compilation, but with the linking. Linkers often leave out data that is not used, to reduce the size of the binary. To check this, use the strings command or equivalent on the .o file generated from your C file: if the string is in that, but not in your .so your problem is the linking.
Unfortunately, I don't know how to work around this problem with the linker command(s), because all of my Android C programming has been done with a standalone tool-chain and a custom build system.
Your easiest solution is simply to make a copy of the string at run-time. You need to do this in your C code, so that the linker knows the string gets used.

arm-linux-androideabi-g++ can not find header cstdarg

Trying to cross-compile an android app from linux using arm-linux-androideabi-g++, I get an error that the header file cstdarg can not be found.
common.h:27:19: fatal error: cstdarg: No such file or directory
compilation terminated.
If I look into the /usr/arm-linux-androideabi/include/, the header is not there but other c++ header files are present. How can I fix this problem ?
<cstdarg> is not a system header, in sense that it comes from C++ standard library. Looks like you've missed to add C++ headers to command line. They are placed under $ANDROID_NDK/sources/cxx-stl/. Of course ensure that you're using header for appropriate library implementation.
Also you may need to include complier-specific C-headers (at least <stdarg.h> as it is used by <cstdarg>).
Some of standard headers are compiler-specific because they use some compiler-specific extensions, intrinsics, so on. <stdarg.h> is one of them. Because of their nature there is no much sense to put them to generic sysroot include directory. Look under $ANDROID_NDK/toolchains/ directory.

smd_private.h: No such file or directory

I'm trying to build a stand alone Android kernel and i want to write loadable kernel module, but when i build my module.c file, i have this error
error: smd_private.h: No such file or directory
search at google told me that i should change <smd_private.h> into "smd_private.h" .but the error still exist!!
Can you help me?
Check to make sure smd_private.h is in the same directory as my module.c
Here is info from https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html#Include-Syntax
2.1 Include Syntax
Both user and system header files are included using the preprocessing
directive ‘#include’. It has two variants:
#include <file>
This variant is used for system header files. It searches for a file
named file in a standard list of system directories. You can prepend
directories to this list with the -I option (see Invocation).
#include "file"
This variant is used for header files of your own program. It searches
for a file named file first in the directory containing the current
file, then in the quote directories and then the same directories used
for <file>. You can prepend directories to the list of quote directories
with the -iquote option.
The argument of ‘#include’, whether delimited with quote marks or angle
brackets, behaves like a string constant in that comments are not
recognized, and macro names are not expanded. Thus, #include <x/*y>
specifies inclusion of a system header file named x/*y.
However, if backslashes occur within file, they are considered ordinary
text characters, not escape characters. None of the character escape
sequences appropriate to string constants in C are processed.
Thus, #include "x\n\\y" specifies a filename containing three
backslashes. (Some systems interpret ‘\’ as a pathname separator.
All of these also interpret ‘/’ the same way. It is most portable to
use only ‘/’.)
It is an error if there is anything (other than comments) on the line
after the file name.

Categories

Resources