How to use ndk-stack with shared library in AAR file - android

I'm using shared object libraries in Android application. These shared object libraries are in .aar file.
One of library is crashing. In order to check crash logs and exact line no. I am using ndk-stack took.
Usage of ndk-stack is
$ adb logcat | ndk-stack -sym <Path to your shared libraries>
Now How can I get a path of shared libraries in AAR file?

You should keep in mind that not every .so file is useful for ndk-stack. Android NDK produces two kinds of .so files: stripped and non-stripped. The most difference is that last ones contain debug information, that is needed for ndk-stack and first ones don't. readelf may help to check if particular file is stripped or not:
$ readelf <non-stripped-lib> -S | grep debug
[23] .debug_info PROGBITS 00000000 00302c 0052d9 00 0 0 1
[24] .debug_abbrev PROGBITS 00000000 008305 000879 00 0 0 1
[25] .debug_loc PROGBITS 00000000 008b7e 001aa7 00 0 0 1
[26] .debug_aranges PROGBITS 00000000 00a628 000088 00 0 0 8
[27] .debug_ranges PROGBITS 00000000 00a6b0 0000d0 00 0 0 1
[28] .debug_line PROGBITS 00000000 00a780 0009de 00 0 0 1
[29] .debug_str PROGBITS 00000000 00b15e 002387 01 MS 0 0 1
[30] .debug_frame PROGBITS 00000000 00d4e8 0003d0 00 0 0 4
$
$ readelf <stripped-lib> -S | grep debug
$
As you see not-stripped ELF has a lot of .debug_* sections, that indeed contain line numbers, private / static function names, etc.
Next, .aar files, both debug and release ones, has only stripped binaries. So they are useless for ndk-stack.
AFAIK, the only place where non-stripped binaries may be found is a obj/ dir. Its location depends slightly on used build system:
for ndk-build it is under <module_name>/build/intermediates/ndk
for CMake-based it is under <module_name>/build/intermediates/cmake
Also it looks like out-of-the-box android gradle plugin offers no way to pack unstripped libraries to your aar, so the only way here is some custom task in your build.gradle.

Related

C++ shared libraries have duplicate symbols

I am new to c++ symbol tables and libraries, wanted to understand the behavior of symbol table.
We are having an android application with native support on it. In process of analyzing symbol tables of shared libraries, I am noticing duplicate symbols present in .so file. Please find the sample list of symbol table.
0162502c w DO .data 00000004 Base boost::asio::error::get_addrinfo_category()::instance
00aaa4f4 w DF .text 0000009c Base boost::asio::error::get_misc_category()
01626334 w DO .bss 00000004 Base guard variable for boost::asio::error::get_misc_category()::instance
00aab4d0 w DF .text 0000003c Base boost::asio::error::detail::misc_category::~misc_category()
00aab368 w DF .text 0000003c Base boost::asio::error::detail::addrinfo_category::~addrinfo_category()
00aab3a4 w DF .text 00000034 Base boost::asio::error::detail::addrinfo_category::name() const
00aab3d8 w DF .text 000000f8 Base boost::asio::error::detail::addrinfo_category::message(int) const
00aab50c w DF .text 0000003c Base boost::asio::error::detail::misc_category::~misc_category()
Here you can notice following symbol "boost::asio::error::detail::misc_category::~misc_category()" appearing twice.
I wanted to understand why are we getting duplicate symbols in symbol table. Also interested to know why my app is running fine when there are duplicate symbols [ which linker should ideally throw duplicate symbols error ] Also would like to know does having duplicate symbols in symbol tables would increase the size of "so" eventually leading to increasing in the size of app
If this happens, how could I ensure that I get only unique entries in symbol table.
Note:- we are using clang
I am noticing duplicate symbols present in .so file
Like this?
$ cat foo.c
int foo(void)
{
return 42;
}
Compile:
$ gcc -Wall -fPIC -c foo.c
Check symbols in the object file for foo:
$ readelf -s foo.o | grep foo
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
8: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 foo
One hit.
Make a shared library:
$ gcc -Wall -shared -o libfoo.so foo.o
Check symbols in the shared library for foo:
$ readelf -s libfoo.so | grep foo
5: 000000000000057a 11 FUNC GLOBAL DEFAULT 9 foo
29: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
44: 000000000000057a 11 FUNC GLOBAL DEFAULT 9 foo
Now two hits.
Nothing is wrong here. See some more of the picture:
$ readelf -s foo.o | egrep '(foo|Symbol table|Ndx)'
Symbol table '.symtab' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
8: 0000000000000000 11 FUNC GLOBAL DEFAULT 1 foo
An object file has one symbol table, its static symbol table .symtab,
that is used by the linker for link-time symbol resolution. But:
$ readelf -s libfoo.so | egrep '(foo|Symbol table|Ndx)'
Symbol table '.dynsym' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
5: 000000000000057a 11 FUNC GLOBAL DEFAULT 9 foo
Symbol table '.symtab' contains 48 entries:
Num: Value Size Type Bind Vis Ndx Name
29: 0000000000000000 0 FILE LOCAL DEFAULT ABS foo.c
44: 000000000000057a 11 FUNC GLOBAL DEFAULT 9 foo
a shared library has two symbol tables: a static symbol table .symtab, like
an object file, plus a dynamic symbol table, .dynsym, used by the loader for run-time symbol resolution.
When you link object files into a shared library, the linker by default transcribes the
GLOBAL symbols from their .symtabs into the .symtab and the .dynsym of the shared
library, except for those symbols that have HIDDEN visibility in the object files
(which they get from being defined with the attribute of hidden visibility
at compilation).
Any GLOBAL symbols with HIDDEN visibility in the object files are transcribed as LOCAL symbols
with DEFAULT visibility into the .symtab of the shared library and are not transcribed
into the .dynsym of the shared library at all. So when the shared library is linked with
anything else, neither the linker nor the loader can see the global symbols that were HIDDEN at compilation.
But apart from hidden symbols, of which there are often none, the same global symbols
will appear in the .symtab and the .dynsym tables of a shared library. Each defined symbol
that appears in both tables addresses the same definition.
Later, OP comments
I took the symbol table by running objdump -T command, which should ideally list symbols present only in dynamic symbol table.
This steers us to a different explanation, because objdump -T does indeed report only
the dynamic symbol table (like readelf --dyn-syms).
Notice that the symbol reported twice:
...
00aab4d0 w DF .text 0000003c Base boost::asio::error::detail::misc_category::~misc_category()
...
00aab50c w DF .text 0000003c Base boost::asio::error::detail::misc_category::~misc_category()
...
is classified w in column 2 (as are all the other symbols in your snippet). What objdump means by that is
that the symbol is weak.
Let's repoduce the observation:
foo.hpp
#pragma once
#include <iostream>
struct foo
{
explicit foo(int i)
: _i{i}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
~foo()
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int _i = 0;
};
bar.cpp
#include "foo.hpp"
foo bar()
{
return foo(2);
}
gum.cpp
#include "foo.hpp"
foo gum()
{
return foo(1);
}
Compile and make a shared library:
$ g++ -Wall -Wextra -c -fPIC bar.cpp gum.cpp
$ g++ -shared -o libbargum.so bar.o gum.o
See what dynamic symbols objdump reports from struct foo:
$ objdump -CT libbargum.so | grep 'foo::'
00000000000009bc w DF .text 0000000000000046 Base foo::foo(int)
00000000000009bc w DF .text 0000000000000046 Base foo::foo(int)
Duplicate weak exports of the constructor foo::foo(int). Just like what you
noticed.
Hang on a tick though. foo::foo(int) is a C++ method signature, but not
actually a symbol that the linker can recognise. Let's do that again, this time
without demangling:
$ objdump -T libbargum.so | grep 'foo'
00000000000009bc w DF .text 0000000000000046 Base _ZN3fooC1Ei
00000000000009bc w DF .text 0000000000000046 Base _ZN3fooC2Ei
Now we see the symbols the linker sees, and the duplication is no longer to be seen:
_ZN3fooC1Ei != _ZN3fooC2Ei, although both symbols have the same address and
$ c++filt _ZN3fooC1Ei
foo::foo(int)
$ c++filt _ZN3fooC2Ei
foo::foo(int)
they both demangle to the same thing, foo::foo(int). There are in fact 5
distinct symbols - _ZN3fooCNEi, for 1 <= N <= 5 - that demangle to foo::foo(int).
(And g++ actually uses _ZN3fooC1Ei, _ZN3fooC2Ei and _ZN3fooC5Ei in the object
files bar.o and gum.o).
So in reality, there are no duplicated symbols in the dynamic symbol table: the
sneaky many-to-one nature of the name-demangling mapping just makes it look that way.
But why?
I'm afraid the answer to that is too long and complicated for here.
Executive Summary
The GCC C++ compiler employs the two weak symbols that
demangle identically to refer to a global inline class-method in different ways, as part of
its stock formula for enabling the successful linkaqe of global inline class-methods in Position Independent Code.
This is a non-neglible problem for any compiler, and the GCC formula for it is not the only possible one. Clang has a different
solution, that does involve the use of synonymous but distinct symbols and so doesn't
give rise to the illusory "duplication" of symbols that you've seen.

Cross Compile with autoconf with Android toolchain

Objective Cross compile Cisco libsrtp for Android using NDK toolchain and use libsrtp.a to statically link against my own library.
Setup : I make use of the following file
<setup.sh>
export CROSS_SYSROOT=/home/psurana/aa/sysroot
export CROSS_COMPILE=aarch64-linux-android-
export SYSROOT=/home/psurana/aa/sysroot
export CC="${CROSS_COMPILE}gcc --sysroot=${SYSROOT}"
export CXX="${CROSS_COMPILE}gxx --sysroot=${SYSROOT}"
PATH=/home/psurana/aa/bin:$PATH
then I do the following configure:
source setup.sh && ./configure --host=aarch64-linux-android --build=`./config.guess` && make -j
This compiles it for me. doing a readelf -h libsrtp.a, yields--
File: libsrtp.a(ut_sim.o)
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: AArch64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 1480 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 10
Section header string table index: 7
So far so good.
Problem
However, when I link libsrtp.a as a prebuilt static library, I get following errors:
./srtp/libsrtp.a(rand_source.o): In function `rand_source_init':
err.c:(.text+0x0): undefined reference to `stdout'
err.c:(.text+0xc): undefined reference to `stdout'
and,
rand_source.c:(.text+0x28): undefined reference to `stderr'
rand_source.c:(.text+0x3c): undefined reference to `stderr'
My understanding is that Android does not have stderr in its libc, but then how does libsrtp get these?
I have previously built the same library using something similar and I know it builds. I do not know what the error might be.
I usually get this undefined reference with libc in any platform after 21 so I usually add -D__ANDROID_API__=21 to CFLAGS and it ends up fixing it. I believe the issue comes from the new unified headers in newer ndk versions.

android - BufferOverflowException when trying to unzip obb file

when I try to unzip a encrypted obb file using the jobb tool jumps me the following error:
jobb -dump /temp/obb-output/ -o my-app-assets.obb -k secret-key
Package Name: com.example.sample
Package Version: 1
SALT: -63dddd10f3a63bb
29eb26a5c9227f6efeab677fc53a7348
[LFN = video.avi / SFN = ShortName [/> ifl -- 5 2f 1d 10 3 3e c 1d 69 66 6c ]]
Alignment off reading from sector: 2433
Partial read from sector: 2433
Exception in thread "main" java.nio.BufferOverflowException
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:183)
at java.nio.ByteBuffer.put(ByteBuffer.java:832)
at com.android.jobb.EncryptedBlockFile$EncryptedBlockFileChannel.readDecryptedSector(EncryptedBlockFile.java:292)
at com.android.jobb.EncryptedBlockFile$EncryptedBlockFileChannel.read(EncryptedBlockFile.java:142)
at de.waldheinz.fs.util.FileDisk.read(FileDisk.java:118)
at de.waldheinz.fs.fat.ClusterChain.readData(ClusterChain.java:214)
at de.waldheinz.fs.fat.FatFile.read(FatFile.java:126)
at com.android.jobb.Main.dumpDirectory(Main.java:137)
at com.android.jobb.Main.dumpDirectory(Main.java:112)
at com.android.jobb.Main.main(Main.java:315)
Can anyone help me?
It is to do with expansion file version numbers. I just needed to increment versionCode in my manifest and in the obb file. Android doesn't seem to like you updating with a new obb file with the same version number, Hope it helps.

Using dd to change a hex value in Android script

What I am doing is trying to build a script that can be flashed in a custom android recovery like TWRP or ClockWorkMod.
The beginning: So using this command at a ADB shell prompt will modify the partition in which the locked or unlocked flag lives for the bootloader on many HTC devices-
echo -ne '\x00\x00\x00\x00' | dd of=/dev/block/mmcblk0p3 bs=1 seek=33796
I am trying to be able to do the same thing from recovery (Aroma script, but shouldn't matter)
The issue is that while CWM recovery can use these 2 simple lines to complete it:
echo -ne "\000\000\000\000" > /tmp/data_new
dd if=/tmp/data_new of=/dev/block/mmcblk0p3 bs=1 seek=33796 conv=notrunc
TWRP environment cannot. The issue seems to be with the quotes and/or the backslashes in the echo.
To get around this I have tried to package a file called data_new with the output of the echo (which is just 4 nul bytes) and then use the DD command, but it doesn't read the data_new correctly because I get 0+0 records in and 0+0 records out. I have also tried writing a shell script to execute the commands, but same issue in TWRP.
To add a layer of complexity the commands in the aroma script are quoted like this:
run_program("/sbin/busybox", "dd", "if=/tmp/data_new", "of=/dev/block/mmcblk0p3" etc
I have tried many combinations of single and double quotes and leading backticks but still fails.
Bottom line - Is there a different way of expressing 4 zeroed out hex values?
The reverse is not a problem because it's echo to Lock is this: (no backticks and quotes on HTCU don't come into play, since echo output is the same with or without)
echo -ne "HTCU" | dd of=/dev/block/mmcblk0p3 bs=1 seek=33796
The issue is in getting a DD command to change the HTCU values to 4 zeroes without using backticks in the echo.
Can anyone help?
PS - I think that this could be done by pulling the partition with DD to /tmp and then find the HTCU string (48 54 43 55) and replace with 00 00 00 00, but the partition is large with only a small amount of data actually in it so the process would take a while and the script would be more complicated than I think I could write, as yes I am a noob to coding.
Thanks
EDIT: I tried using /dev/null as that seems like a good idea and a way to avoid echo altogether. However that fails as well. Same result as using a preloaded 4 nul byte file. I know it is not the recovery as the /dev/null method produced the same failure in a ADB shell.
0+0 records in
0+0 records out
0 bytes copied
Here is the full string of code:
run_program("/sbin/busybox", "dd", "if=/dev/null", "of=/dev/block/mmcblk0p3", "bs=1", "count=4", "seek=33796", "conv=notrunc")
After dd, what might be the best alternate way to do a quick hex edit?
This is my requirement:
writting into parttion mmcblk0p3 at offset 0x8404. HTCU for unlocked, HTCL for relocked or 0x00000000 for locked
Thanks again
Could you not read directly from /dev/null reading 4 bytes; I believe the syntax is:
dd if=/dev/null of=/dev/block/mmcblk0p3 bs=1 count=4 seek=33796 conv=notrunc
Please double check the above code, I've not used dd in a while.
Update
After playing around with dd I managed to get it to write 4 null bytes to a position I specified within a file:
Firstly create the example file:
$ dd if=/dev/urandom of=randomfile bs=64 count=1
1+0 records in
1+0 records out
64 bytes (64 B) copied, 4.5401e-05 s, 1.4 MB/s
$ od -b randomfile
0000000 105 342 131 116 213 371 352 344 217 236 320 106 010 154 074 375
0000020 360 215 014 203 030 357 144 053 302 265 012 310 217 362 236 303
0000040 156 033 266 035 303 061 262 055 253 102 222 037 372 105 230 321
0000060 117 277 322 277 166 174 316 176 010 202 302 151 120 045 120 334
0000100
Then zeroing 4 bytes, skipping the first two bytes:
$ dd if=/dev/zero of=randomfile seek=2 bs=1 count=4 conv=notrunc
4+0 records in
4+0 records out
4 bytes (4 B) copied, 4.4779e-05 s, 89.3 kB/s
$ od -b randomfile
0000000 105 342 000 000 000 000 352 344 217 236 320 106 010 154 074 375
0000020 360 215 014 203 030 357 144 053 302 265 012 310 217 362 236 303
0000040 156 033 266 035 303 061 262 055 253 102 222 037 372 105 230 321
0000060 117 277 322 277 166 174 316 176 010 202 302 151 120 045 120 334
0000100
This should extend to your larger file.
dd if=/dev/null of=/dev/block/mmcblk2p3 bs=1 count=4 seek=33796 conv=notrunc
This above Ans worked for me... Thanks for the Ans.
dd if=/dev/null of=/dev/block/mmcblk2p3 bs=1 count=4 seek=33796
without conv=notrunc argument it used to give
dd: ftruncate: Invalid argument error.

Finding usage of resources (CPU and memory) by threads of a process in Android

I have a multi-threaded application(C++,C and pthread library) and I will like to know how much resources(CPU and memory) each thread uses. Is there a way to find out these details on Android?
I have tried
$ adb shell ps -p -t
But, this gives information in the below format,
USER PID PPID VSIZE RSS PRIO NICE RTPRI SCHED WCHAN PC NAME
root 1 0 476 312 20 0 0 0 c037c0e0 000087bc S /init
root 2 0 0 0 20 0 0 0 c031f114 00000000 S kthreadd
root 3 2 0 0 20 0 0 0 c030e5d0 00000000 S ksoftirqd/0
root 4 2 0 0 -100 0 99 1 c033fc50 00000000 S watchdog/0
root 5 2 0 0 20 0 0 0 c031b4b4 00000000 S events/0
root 6 2 0 0 20 0 0 0 c031b4b4 00000000 S khelper
Any way to know which threads are running along with their parent's id will be really helpful.
using
$ adb logcat -v threadtime
prints info about the running process (PID) and the thread (TID).
But, its not enough for my purpose. I want to know how much resources is a particular thread consuming. Any pointers.
ps command in android seems to be very limited compared to linux.
You could try:
ps -t -c APP_NAME
This will show you threads(-t) and the CPU assigned to the thread (-c)
Example:
ps -t -c -p com.whatsapp
-p is thread priority(linux nice value)

Categories

Resources