Menu

#223 doesn't work packed .so(library) file in android.

upx392
closed-fixed
None
5
2015-02-20
2013-10-22
sonh
No

Hello,
i really thanks to solve packed executable issue.
and i tried to pack my .so file, but upx shows an error "UnknownExecutableFormatException",
so i fixed file offset 0x10, 0x3(.so) -> 0x2(executable).

my test files

  • main (no packed executable / call .so's function)
  • libmymath.so (upx packed)

main.c includes the follow codes.


include "mymath.h"

include <stdio.h></stdio.h>

include <dlfcn.h></dlfcn.h>

include <string.h></string.h>

include <stdlib.h></stdlib.h>

int main(int argc, char argv)
{
void
handle = NULL;
int (
result)(int, int);

printf("one");
getchar();
handle = dlopen("./libmymath.so", RTLD_NOW);
if ( !handle )
{ 
    printf("fail to dlopen, %s\n", dlerror());
    return 0;
}

printf("two");
getchar();
result = dlsym(handle, "sum");
if ( dlerror() != NULL )
{
    printf("fail to dlsym, %s\n", dlerror());
    return 0;
}
printf("three");
getchar();

printf("10 + 20 = %d\n", result(10, 20));
dlclose(handle);
return 0;

}


mymath.c and mymath.h include the follow codes.


  • mymath.h

include <math.h></math.h>

extern int sum(int n1, int n2);

  • mymath.c

include "mymath.h"

int sum(int n1, int n2)
{
return n1+n2;
}
and many dummy codes(ex: __asm emit 0x90) in order to make big file size. (i got an error "file is too small")


But it occurs an error.

root@android:/data/local/tmp # ./main
./main
one

[1] + Stopped (signal) ./main
root@android:/data/local/tmp #
[1] + Bus error ./main

it just printed "one" and i guess dlopen() doesn't work.


and i debug the executable with gdb.

root@android:/data/local/tmp # ./gdb ./main
(gdb) r
Starting program: /data/local/tmp/main
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
one

Program received signal SIGBUS, Bus error.
0xb0001458 in ?? () from /system/bin/linker


and strace results

root@android:/data/local/tmp # ./strace -p 14121

Process 14121 attached - interrupt to quit
read(0, "\n", 1024) = 1
stat64("/vendor/lib/./libmymath.so", 0xbed577c8) = -1 ENOENT (No such file or di
rectory)
stat64("/system/lib/./libmymath.so", 0xbed577c8) = -1 ENOENT (No such file or di
rectory)
stat64("/data/local/gcc/lib/./libmymath.so", {st_mode=S_IFREG|0666, st_size=4004
, ...}) = 0
open("/data/local/gcc/lib/./libmymath.so", O_RDONLY|O_LARGEFILE) = 3
lseek(3, 0, SEEK_SET) = 0
read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\2\0(\0\1\0\0\0(\3\0\000"..., 4096) = 40
04
lseek(3, -8, SEEK_END) = 3996
read(3, "P\0\0o\200\0\0\0", 8) = 8
mmap2(NULL, 45056, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40
0a1000
mmap2(0x400a1000, 3260, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40
0a1000
mprotect(0x400a1000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
mmap2(0x400ab000, 3652, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x2) = 0
x400ab000
--- SIGBUS (Bus error) @ 0 (0) ---
open("/dev/log/main", O_WRONLY|O_LARGEFILE) = 4
writev(4, [{"\7", 1}, {"libc\0", 5}, {"Fatal signal 7 (SIGBUS) at 0x400"..., 47}
]
, 3) = 53
gettid() = 14121
socket(PF_FILE, SOCK_STREAM, 0) = 5
connect(5, {sa_family=AF_FILE, path=@android:debuggerd}, 20) = 0
write(5, ")7\0\0", 4) = 4
read(5, 0xbed57428, 1) = ? ERESTARTSYS (To be restarted)
--- SIGCONT (Continued) @ 0 (0) ---
read(5, ")", 1) = 1
close(5) = 0
sigaction(SIGBUS, {SIG_DFL}, {0xb0005a1d, [], SA_RESTART|SA_SIGINFO}, 0) = 0
rt_sigreturn(0) = 1074445892
--- SIGBUS (Bus error) @ 0 (0) ---
Process 14121 detached

no working in my phones.
I'll send more logs and informations which you want in order to solve this problm.
and I will send you my test phone if you want.

thanks.

Discussion

1 2 > >> (Page 1 of 2)
  • John Reiser

    John Reiser - 2013-10-22

    i tried to pack my .so file, but upx shows an error "UnknownExecutableFormatException",
    so i fixed file offset 0x10, 0x3(.so) -> 0x2(executable).

    Please show the output from "readelf --headers libmymath.so" (before upx packing, before "fixing" the byte at offset 0x10), where then upx complains "UnknownExecutableFormatException". If applying gzip to libmymath.so gives something small enough, then please upload that to an attachment, too.

    UPX does not complain when I try to pack /lib/libm-2.11.3.so, where readelf shows:

    ELF Header:
      Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
      Class:                             ELF32
      Data:                              2's complement, little endian
      Version:                           1 (current)
      OS/ABI:                            UNIX - System V
      ABI Version:                       0
      Type:                              DYN (Shared object file)
      Machine:                           ARM
      Version:                           0x1
      Entry point address:               0x31fc
      Start of program headers:          52 (bytes into file)
      Start of section headers:          651752 (bytes into file)
      Flags:                             0x5000002, has entry point, Version5 EABI
      Size of this header:               52 (bytes)
      Size of program headers:           32 (bytes)
      Number of program headers:         8
      Size of section headers:           40 (bytes)
      Number of section headers:         29
      Section header string table index: 28
    
    Program Headers:
      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      PHDR           0x000034 0x00000034 0x00000034 0x00100 0x00100 R E 0x4
      INTERP         0x09d038 0x0009d038 0x0009d038 0x00014 0x00014 R   0x4
          [Requesting program interpreter: /lib/ld-linux.so.3]
      LOAD           0x000000 0x00000000 0x00000000 0x9def8 0x9def8 R E 0x8000
      LOAD           0x09eeec 0x000a6eec 0x000a6eec 0x001b4 0x001bc RW  0x8000
      DYNAMIC        0x09eef8 0x000a6ef8 0x000a6ef8 0x00108 0x00108 RW  0x4
      NOTE           0x000134 0x00000134 0x00000134 0x00044 0x00044 R   0x4
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
      GNU_RELRO      0x09eeec 0x000a6eec 0x000a6eec 0x00114 0x00114 R   0x1
    
     Section to Segment mapping:
      Segment Sections...
       00     
       01     .interp 
       02     .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_d .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .interp .eh_frame .hash 
       03     .init_array .fini_array .jcr .dynamic .got .data .bss 
       04     .dynamic 
       05     .note.gnu.build-id .note.ABI-tag 
       06     
       07     .init_array .fini_array .jcr .dynamic 
    
     
  • John Reiser

    John Reiser - 2013-10-22

    For UPX to compress a shared library, then there must be a DT_INIT entry in the Dynamic section. This is created if there is a function called "_init" or when some other function is named in a command-line argument to the linker "-init=my_function", which is written as "-Wl,-init=my_function" on a gcc command line.

    $ readelf --dynamic libm-2.11.3.so
    Dynamic section at offset 0x9eef8 contains 29 entries:
      Tag        Type                         Name/Value
     0x00000001 (NEEDED)                     Shared library: [ld-linux.so.3]
     0x00000001 (NEEDED)                     Shared library: [libc.so.6]
     0x0000000e (SONAME)                     Library soname: [libm.so.6]
     0x0000000c (INIT)                       0x3124
     0x0000000d (FINI)                       0x681d8
     0x00000019 (INIT_ARRAY)                 0xa6eec
     0x0000001b (INIT_ARRAYSZ)               4 (bytes)
     0x0000001a (FINI_ARRAY)                 0xa6ef0
     0x0000001c (FINI_ARRAYSZ)               4 (bytes)
     0x00000004 (HASH)                       0x9d050
     0x6ffffef5 (GNU_HASH)                   0x178
    
     
  • John Reiser

    John Reiser - 2013-10-22

    See the comment in p_lx_elf.cpp, and the code which follows.

            // Heuristic HACK for shared libraries (compare Darwin (MacOS) Dylib.)
            // If there is an existing DT_INIT, and if everything that the dynamic
            // linker ld-linux needs to perform relocations before calling DT_INIT
            // resides below the first SHT_EXECINSTR Section in one PT_LOAD, then
            // compress from the first executable Section to the end of that PT_LOAD.
            // We must not alter anything that ld-linux might touch before it calls
            // the DT_INIT function.
    
            if (elf_find_dynamic(Elf32_Dyn::DT_INIT)) {
    [[snip]]
                goto proceed;  // But proper packing depends on checking xct_va.
            }
            else
                infoWarning("no DT_INIT: %s", fi->getName());
    abandon:
    
     
  • sonh

    sonh - 2013-10-23

    thanks for the reply!

    i checked "(INIT)" in dynamic section but it doesn't exist.

    so i added,

    mymath.h :

    define init __attribute ((section (".text.init")))

    void __init smp_init(void)

    mymath.c :
    void __init smp_init(void)
    {
    printf("init!!");

    }

    gcc -Wall -c mymath.c -fPIC

    gcc -shared -o libmymath.so mymath.o

    i made libmymath.so and check readelf --dynamic.
    but there is no (INIT) section in .so file.
    (sorry, i'm a newbie of linux/elf)

    so i checked some .so (located at /system/lib) but i couldn't find (INIT) sections.
    (just i found (INIT_ARRAY or INIT_ARRAYSZ)

    i'll check more information in order to make init section,
    and i'll re-post the result of testing.

    I really appreciate your guide and help.
    thanks

     
  • John Reiser

    John Reiser - 2013-10-23
    ----- mymath.c
        #include "mymath.h"
        #include <stdio.h>
    
        int const dummy_to_make_this_compressible[10000] = {1,2,3};
        void my_init()
        {
            fprintf(stderr, "mymath my_init\n");
        }
    
        int sum(int n1, int n2)
        {
            return n1+n2;
        }
    ----- mymain.c
        #include <stdio.h>
        #include <dlfcn.h>
        #include "mymath.h"
    
    
        int main(int argc, char argv)
        {
    
            printf("one");
            getchar();
            void *handle = dlopen("./libmymath.so", RTLD_NOW);
            if ( !handle ) { 
                printf("fail to dlopen, %s\n", dlerror());
                return 0;
            }
    
            printf("two");
            getchar();
            int (*result)(int, int) = (int (*)(int, int))dlsym(handle, "sum");
            if ( dlerror() != NULL ) {
                printf("fail to dlsym, %s\n", dlerror());
                return 0;
            }
    
            printf("three");
            getchar();
    
            printf("10 + 20 = %d\n", result(10, 20));
            dlclose(handle);
            return 0;
        }
    -----
    $ gcc -shared -o libmymath.so -Wl,-init=my_init -fPIC mymath.c
    $ readelf --dynamic libmymath.so
    Dynamic section at offset 0xa2cc contains 25 entries:
      Tag        Type                         Name/Value
     0x00000001 (NEEDED)                     Shared library: [libc.so.6]
     0x0000000c (INIT)                       0x5e4   ## my_init (see --symbols)
     0x0000000d (FINI)                       0x660
     0x00000019 (INIT_ARRAY)                 0x122c0
     0x0000001b (INIT_ARRAYSZ)               4 (bytes)
     0x0000001a (FINI_ARRAY)                 0x122c4
     0x0000001c (FINI_ARRAYSZ)               4 (bytes)
      [[snip]]
    $ readelf --symbols libmymath.so  |  grep my_init
        13: 000005e4    76 FUNC    GLOBAL DEFAULT   12 my_init
        45: 000122c0     0 OBJECT  LOCAL  DEFAULT   16 __frame_dummy_init_array_
        66: 000005e4    76 FUNC    GLOBAL DEFAULT   12 my_init
    $ upx -f -o libmymath-upx.so libmymath.so
         45189 ->      9220   20.40%   linux/armel   libmymath-upx.so          
    $ gcc -o mymain -L$PWD -lmymath -ldl mymain.c
    $ export LD_LIBRARY_PATH=$PWD
    $ ./mymain   ## remember to type <Enter> three times
    mymath my_init
    one
    two
    three
    10 + 20 = 30
    $ 
    $ mv libmymath.so     libmymath-orig.so
    $ ln libmymath-upx.so libmymath.so
    $ ./mymain   ## remember to type <Enter> three times
    mymath my_init
    one
    two
    three
    10 + 20 = 30
    $ 
    
     
  • John Reiser

    John Reiser - 2013-10-23

    $ gcc -o mymain mymain.c -ldl ## here without -lmymath
    $ ./mymain
    one
    mymath my_init ## after dlopen and after dlsym
    two
    three
    10 + 20 = 30
    $

     
  • sonh

    sonh - 2013-10-24

    it works perfectly in my phone!
    thanks for the guide :)

    ultimately, I'll make Android dynamic library(called "JNI or NDK") and try to pack it.
    i made .so library with NDK cross compiler and it has init section, but there is no entry point(0x0) in header.
    now i'm checking the Makefile, in order to check whether to set wrong compile option or not.
    and i'm wondering about that entry point must have non zero If there is init section. (for calling decompress stub)

     

    Last edit: sonh 2013-10-24
  • sonh

    sonh - 2013-10-25

    I tested the following two cases :

    1) phone library

    • works well

    2) Android App Library (aka JNI)

    • doesn't work

    of course, I set -Wl,-init=my_init -fPIC

    so I traced Android App Prcoess, I catched an error.

    mprotect(0x4a2e9000, 8192, PROT_READ|PROT_EXEC) = 0

    mmap2(NULL, 7480, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0x2a) = 0x4d7bd000

    syscall_983042(0x4d7bea8c, 0x4d7bed38, 0, 0x1afffffb, 0xffffffff, 0, 0x31, 0xf0002, 0xb00147b8, 0x4a2ee000, 0x4000, 0x4a2e9000, 0, 0xbebe8264, 0x4d7bec91, 0x4a2eae8a, 0x30, 0x4d7bea8c, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0

    mmap2(0x4a2e9000, 9091, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a2e9000

    syscall_983042(0x4a2e9c60, 0x4a2eb383, 0, 0x4a2e9c60, 0, 0, 0x4a2e9000, 0xf0002, 0xb00147b8, 0x4a2ee000, 0x4000, 0x4a2e9000, 0, 0xbebe826c, 0x4d7beb08, 0x4d7bead0, 0x60000010, 0x4a2e9c60, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0

    syscall_983042(0x4a2e9000, 0x4a2eb383, 0, 0x5, 0x4d7bec59, 0x318, 0x4a2e9000, 0xf0002, 0xb00147b8, 0x4a2ee000, 0x4000, 0x4a2e9000, 0, 0xbebe8294, 0x4d7becd3, 0x4d7bed32, 0x30, 0x4a2e9000, 0, 0, 0xc764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = 0

    mprotect(0x4a2e9000, 9091, PROT_READ|PROT_EXEC) = 0

    munmap(0x4d7bd000, 7480) = 0

    futex(0x1610c58, 0x81 / FUTEX_??? /, 2147483647) = 0

    writev(3, [{"\5", 1}, {"dalvikvm\0", 9}, {"JNI WARNING: input is not valid "..., 72}], 3) = 82

    writev(3, [{"\5", 1}, {"dalvikvm\0", 9}, {" string: \'...This is"..., 46}], 3) = 56

    writev(3, [{"\5", 1}, {"dalvikvm\0", 9}, {" in Lcom/sklee/jnite"..., 91}], 3) = 101

    i tested it at Eclipse Android Virtual Machine, and it shows

    10-25 17:33:42.107: W/dalvikvm(32587): JNI WARNING: input is not valid Modified UTF-8: illegal start byte 0xfe
    10-25 17:33:42.107: W/dalvikvm(32587): string: '...This is JNI test �.'
    10-25 17:33:42.107: W/dalvikvm(32587): in Lcom/sklee/jnitest/HelloJNI;.getString:()Ljava/lang/String; (NewStringUTF)

    I attached three files for strace log.

    Plase check out this file.
    Thanks always

     

    Last edit: sonh 2013-10-25
    • sonh

      sonh - 2013-10-25

      /data/data/com.sklee.jnitest/lib/libhellojni.so is my library file.

      it just contains the following code

      include jni.h
      include HelloJNI.h
      include log.h

      void my_init()
      {
      log("my_init");
      }

      JNIEXPORT jstring JNICALL Java_com_sklee_jnitest_HelloJNI_getString(JNIEnv env, jobject object)
      {
      log("function");
      return (
      env)->NewStringUTF( env, "...This is JNI test :)" );
      }

      Tag Type Name/Value
      0x00000003 (PLTGOT) 0x3fc8
      0x00000002 (PLTRELSZ) 88 (bytes)
      0x00000017 (JMPREL) 0xc08
      0x00000014 (PLTREL) REL
      0x00000011 (REL) 0xbc0
      0x00000012 (RELSZ) 72 (bytes)
      0x00000013 (RELENT) 8 (bytes)
      0x6ffffffa (RELCOUNT) 6
      0x00000006 (SYMTAB) 0x114
      0x0000000b (SYMENT) 16 (bytes)
      0x00000005 (STRTAB) 0x504
      0x0000000a (STRSZ) 1314 (bytes)
      0x00000004 (HASH) 0xa28
      0x00000001 (NEEDED) Shared library: [liblog.so]
      0x00000001 (NEEDED) Shared library: [libstdc++.so]
      0x00000001 (NEEDED) Shared library: [libm.so]
      0x00000001 (NEEDED) Shared library: [libc.so]
      0x00000001 (NEEDED) Shared library: [libdl.so]
      0x0000000e (SONAME) Library soname: [libhellojni.so]
      0x0000000c (INIT) 0x1b51
      0x0000001a (FINI_ARRAY) 0x3e94
      0x0000001c (FINI_ARRAYSZ) 8 (bytes)
      0x00000019 (INIT_ARRAY) 0x3e9c
      0x0000001b (INIT_ARRAYSZ) 4 (bytes)
      0x00000010 (SYMBOLIC) 0x0
      0x0000001e (FLAGS) SYMBOLIC BIND_NOW
      0x6ffffffb (FLAGS_1) Flags: NOW
      0x00000000 (NULL) 0x0

       
  • John Reiser

    John Reiser - 2013-10-26

    When a shared library contains both a DT_INIT and a JNI_OnLoad, then which one gets called first when loaded by Java? Put a unique string in a call to fprintf(stderr, ...) or log(...) inside each of DT_INIT and JNI_OnLoad, then see which string appears first.

     
  • sonh

    sonh - 2013-10-28

    10-27 20:24:05.284: I/log(1060): [f:my_init][l:7]my_init log
    10-27 20:24:05.315: I/log(1060): [f:JNI_OnLoad][l:24]OnLoad log

    actually my_init() runs earlier than JNI_OnLoad()

    in case of packed file, there is no my_init() and JNI_OnLoad() logs

    10-27 20:27:03.724: D/dalvikvm(1153): Trying to load lib /data/app-lib/com.sklee.jnitest-1/libhellojni.so 0x416ef890
    10-27 20:27:03.734: A/libc(1153): Fatal signal 11 (SIGSEGV) at 0x00000007 (code=1), thread 1153 (m.sklee.jnitest)

    just it shows those errors.
    Please let me know what to do for testing.

     
  • John Reiser

    John Reiser - 2013-10-28

    Thank you for determining that DT_INIT runs before JNI_OnLoad for a dynamically-loaded, non-compressed shared library. For the next step, I don't understand what happens when "in the case of packed file, there is no my_init() and JNI_OnLoad logs an error."

    Earlier we had success with dlopen of a packed shared library, and saw that the DT_INIT my_init() was called. So what is different about "in the case of packed file, there is no my_init() and JNI_OnLoad logs an error"? Does the file (before packing by UPX) contain both JNI_OnLoad and a DT_INIT of my_init? Or does the file (before packing by UPX) contain only JNI_OnLoad, and does not contain any DT_INIT? UPX insists on a DT_INIT in order to proceed with packing, and in previous cases we saw that a library that does contain a DT_INIT could be packed then dlopen()ed successfully.

    It would help me understand what is going on if you would please Attach an actual file that fails for this current case.

    If that is not possible, then perhaps some experiments with gdb can give insight. When the main program is waiting for a read(), then attach the main program with gdb, and activate the gdb commands for debugging shared libraries. These are "catch load" and/or "set stop-on-solib-events 1". For "catch load" see https://sourceware.org/gdb/onlinedocs/gdb/Set-Catchpoints.html#Set-Catchpoints and for "set stop-on-solib-events 1" see https://sourceware.org/gdb/onlinedocs/gdb/Files.html. Then "continue" from gdb. gdb will stop when the dlopen has gotten far enough, but before running very much farther. Try to see if gdb can find my_init and JNI_OnLoad:
    (gdb) print &my_init
    (gdb) print &JNI_OnLoad

     
    • sonh

      sonh - 2013-10-28

      Please check out the attach file.
      it contains library source and .apk / .so files
      also it contains full android source. (very simple source)
      you can check this source with eclipse(with android plugin)

       
      • sonh

        sonh - 2013-10-28

        (gdb) print &my_init
        print &my_init
        No symbol "my_init" in current context.
        (gdb) continue
        continue
        Continuing.
        ///////----------------- I press the button at Phone UI
        Program received signal SIGSEGV, Segmentation fault.
        0xb0005492 in ?? () from /system/bin/linker
        (gdb) print &my_init
        print &my_init
        No symbol "my_init" in current context.
        (gdb)

        cat /proc/pid/maps shows the following map

        b0001000-b0009000 r-xp 00001000 b3:18 498 /system/bin/linker
        b0009000-b000a000 rw-p 00009000 b3:18 498 /system/bin/linker
        b000a000-b0016000 rw-p 00000000 00:00 0
        befcb000-befec000 rw-p 00000000 00:00 0 [stack]
        ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
        root@android:/ #

         
  • John Reiser

    John Reiser - 2013-10-28

    Thank you for the attach.zip containing an actual example which fails. Using libhellojni.so I have found problems which require work in UPX. Due to my $DAYJOB it probably will take several days before more progress on UPX.

     
  • John Reiser

    John Reiser - 2013-11-02

    How do I use the source that you have provided for HelloJNI? I unzipped FullSource.zip and got directory HelloJNI. Then from developer.android.com/sdk I downloaded adt-bundle-linux-x86_64-20130917.zip, unzipped it, went to the eclipse directory, and ran ./eclipse. Then I File > Import an Android Project, then Browse and select the HelloJNI directory. But Project > Run says "An internal error occurred during: "Launching New_configuration (1)".
    Path for project must have only one segment." and now I'm lost.

     
  • John Reiser

    John Reiser - 2013-11-02

    Some progress: a web search for that error message reveals that I must Run > Run configurations... > Android tab > Project > Browse then choose JNItest as the project name. Connecting my device, then Run or Debug, the device then displays "printHelloJNI With JNI" and the title bar has "JNITest". So I guess it works? Where is the log?

     
  • John Reiser

    John Reiser - 2013-11-02

    Please tell me the steps to run strace, starting as soon as possible during the execution of HelloJNI. Also, how can I single-step the app from eclipse?

     
  • sonh

    sonh - 2013-11-04

    I didn't run Debug mode and single-step.
    You can see log functions at /HelloJNI/jni/HelloJNI.c
    also you can see those logs at LogCat.
    When you press the button at UI, you can see the attached file's log. (errors, in case of upx library)
    Button function includes "LoadLibrary libhellojni.so", also you can see the source at HelloJNI.java

    Steps

    1. Click Window > Android Virtual Device Manager
    2. New > Create new Android Virtual Device (AVD)
    3. Click Start and Launch AVD
    4. Click Project > Run Configurations > Android Application (Left Bar)
    5. and Click Right Tab's Android > Launch : com.sklee.jnitest.JNITestActivity
    6. and Click Target > Launch on All compatible devices/AVD'S > Active AVD's
    7. Click Run

    then you can see APP's UI.

    1. Run Console and unzip attach.tar
    2. and search ADB executable file (in my case, it located at /android/platform-tools)
    3. command "adb push strace /data/local/tmp"
    4. command "adb shell"
    5. command "ps" and check com.sklee.jnitest's pid
    6. command "cd /data/local/tmp"
    7. ./strace -p [pid]
    8. Click button at APP's UI
    9. then you can see the strace logs
     

    Last edit: sonh 2013-11-04
    • John Reiser

      John Reiser - 2013-11-09

      Thank you for the attach.tar which contains strace.

      In my adt-bundle-linux-x86_64-20130917 the "Run Configurations" command (above, first list of instructions, step 4) is under the Run menu, not the Project menu.

      Apparently the way to use a upx-compressed library in place of the original libhellojni.so is to "adb push" the new library to /data/app-lib/com.sklee.jnitest*/libhellojni.so.

      I was able to run your ptrace and see that the upx-compressed library failed. Now instead of attaching ptrace, I want to attach gdb so that I can look at process memory, plant breakpoints, and single step. I want to do something like what is discussed at http://www.kandroid.org/online-pdk/guide/debugging_gdb.html "Debugging with gdb". However, I see no arm-eabi-gdb in my adt bundle; how should I get arm-eabi-gdb?

      [When I start the emulated environment, then sometimes I see "Starting emulator for AVD 'emulator-1'
      WARNING: Data partition already in use. Changes will not persist!
      WARNING: SD Card image already in use: /home/jreiser/.android/avd/emulator-1.avd/sdcard.img
      WARNING: Cache partition already in use. Changes will not persist!"
      I don't understand this, and I hope that it does not matter. Starting the emulator takes about 2 minutes on a 2.5GHz x86_64; is this normal?]

      In the emulated Android environment, I found 'gdbserver' in /system/bin. "gdbserver my_host:1234 --attach <pid>" does run and waits for a connection. On my host x86_64 machine, then "adb forward tcp:1234 tcp:1234" gives no complaint. So I think I'm ready to connect to the gdbserver. Because I don't have arm-eabi-gdb, then I try "(gdb) target remote my-host:1234" using a gdb for ARM ("GNU gdb (GDB) 7.4.1-debian") from my sheevaplug ARM machine. But gdb complains "my-host🔢 No route to host." despite "ping my-host" works. Using the correct numeric IP4 instead of "my-host" also fails from the ARM gdb. Using port 5309 instead of 1234 also fails. (my-host is my x86_64 box which is running the android emulator, and because of "adb forward ..." then my-host supposedly is forwarding the tcp port to-and-from the emulated android environment.)

      So, I think I'm stuck until I can figure out how to run gdb on the HelloJNI app, attaching to the app just before it loads the libhellojni.so. Of course another way would be to have a gdb itself, much like the strace that you sent.

       

      Last edit: John Reiser 2013-11-09
  • John Reiser

    John Reiser - 2013-11-10

    I created a gdb for arm: yumdownloader --source gdb; rpm --install gdb*.src.rpm; cd SPECS; rpmbuild -ba gdb.spec; cd BUILD/gdb*; rm */config.cache; ./configure --target=arm-none-elf --with-system-readline --prefix=...; cp gdb/gdb gdb-arm. Then "adb forward my-host:1234 my-host:1234" and "gdbserver my-host:1234 --attach <pid>" and "(gdb) target remote localhost:1234". Symbols work via "(gdb) add-symbol-file libc.so 0x400339b8" where the address is 0x40027000 [find ELFMAG there] plus the .text address from "objdump -h libc.so | grep text". ["adb pull" files from /system/lib etc so that gdb-arm on my-host can read them.]

    I also found a crash dump report: "logcat" in an adb shell; look for lines with "I/DEBUG". It even includes a short traceback and some symbols. This better than nothing!

    Breakpoints in Thumb mode turn into an infinite loop, but Control-C interrupts. Working backwards in Thumb mode still is slow and hard.

     
  • sonh

    sonh - 2013-11-11

    i attached the app's process with local gdb (no gdb-server)

    step

    1. run app
    2. command "ps" in adb shell and check process id
    3. ./gdb --pid=app's pid
    4. command "continue" and press the UI's button, then app's would load library.

    this is everything about the attaching process that i know.
    and i didn't try it with gdb-server. i have read the lastest your post, and did you success the attaching process and debugging?

    the emulator takes long time, in my pc(Intel I7 / 3.4G@QuadCore) - 1 min

     

    Last edit: sonh 2013-11-11
  • John Reiser

    John Reiser - 2013-11-11

    Thank you for the gdb-static.

    Yes, I was able to use the emulator's own gdbserver with my gdb-arm running on x86_64. I successfully attached to the process, continued, and caught the error. It is SIGSEGV from "strlen(7)": seven bytes beyond a NULL string, and of course there is no page mapped for page 0. strlen was called from __vfprintf, from vsnprintf, from __android_log_print. (That's from the traceback given by "logcat" on the emulator, looking at lines "I/DEBUG". Perhaps that was from Run > Debug, instead of from Run > Run.)

    The problem now is that I want to go farther up the call chain. Perhaps gdb-static will let me. My gdb-arm somehow cannot do tracebacks. What is worse is that it cannot single-step Thumb code, and hitting a breakpoint in Thumb code turns into an infinite loop, instead of breaking. Control-C breaks the loop and permits examining registers and memory, but the only way to proceed is to remove the breakpoint and continue. It would be really nice if gdb-static can give tracebacks and single-step Thumb mode. I will test this in a few days.

     
  • John Reiser

    John Reiser - 2013-11-16

    There was a bug in the unfilter (last) stage of decompression of a shared library on ARM. The practical effect was data-specific for the characters "+;K[k{" near the end of the compressed segment. Get the fix from the source tree https://www.pysol.org:4443/hg/upx.hg .

    Thank you for the gdb-static. When I tried, I still could not single-step Thumb code. I fell back to compiled-in breakpoints (.short 0xde01) in the UPX stub code, and hand patching "(gdb) x/xw $pc" and "(gdb) set *(short *)addr = 0xde01" and "(gdb) set *(short *)addr=0x46c0".

     

    Last edit: John Reiser 2013-11-16
  • John Reiser

    John Reiser - 2013-11-16
    • status: open --> pending
    • Group: -->
     
1 2 > >> (Page 1 of 2)

Log in to post a comment.

MongoDB Logo MongoDB