안드로이드2013. 9. 10. 14:01

soinfo_link_image(linker.cpp:1635); could not load library "xxx.so" needed by "yyy"; caused by soinfo_relocate(linker.cpp:975);: cannot locate symbol "ZZZ" referenced by "xxx.so"...CANNOT LINK EXECUTABLE

 

android source code binoic/linker/linker.cpp에 보면 find_library(..)에서 에러가 남을 알수 있다.

1628    for(d = si->dynamic; *d; d += 2) {
1629        if(d[0] == DT_NEEDED){
1630 DEBUG("%5d %s needs %s\n", pid, si->name, si->strtab + d[1]);
1631            soinfo *lsi = find_library(si->strtab + d[1]);
1632            if(lsi == 0) {
1633                strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf));
1634                DL_ERR("could not load library \"%s\" needed by \"%s\"; caused by %s",
1635                       si->strtab + d[1], si->name, tmp_err_buf);
1636                goto fail;
1637            }
1638            *pneeded++ = lsi;
1639            lsi->refcount++;
1640        }
1641    }

si 는 soinfo* 형태이며, 아래와 같은 구조체이다.

101struct soinfo
102{
103    char name[SOINFO_NAME_LEN];
104    const Elf32_Phdr *phdr;
105    int phnum;
106    unsigned entry;
107    unsigned base;
108    unsigned size;
109
110    int unused// DO NOT USE, maintained for compatibility.
111
112    unsigned *dynamic;
113
114    unsigned unused2; // DO NOT USE, maintained for compatibility
115    unsigned unused3; // DO NOT USE, maintained for compatibility
116
117    soinfo *next;
118    unsigned flags;
119
120    const char *strtab;
121    Elf32_Sym *symtab;
122
123    unsigned nbucket;
124    unsigned nchain;
125    unsigned *bucket;
126    unsigned *chain;
127
128    unsigned *plt_got;
129
130    Elf32_Rel *plt_rel;
131    unsigned plt_rel_count;
132
133    Elf32_Rel *rel;
134    unsigned rel_count;
135
136    unsigned *preinit_array;
137    unsigned preinit_array_count;
138
139    unsigned *init_array;
140    unsigned init_array_count;
141    unsigned *fini_array;
142    unsigned fini_array_count;
143
144    void (*init_func)(void);
145    void (*fini_func)(void);
146
147#if defined(ANDROID_ARM_LINKER)
148    /* ARM EABI section used for stack unwinding. */
149    unsigned *ARM_exidx;
150    unsigned ARM_exidx_count;
151#elif defined(ANDROID_MIPS_LINKER)
152#if 0
153     /* not yet */
154     unsigned *mips_pltgot
155#endif
156     unsigned mips_symtabno;
157     unsigned mips_local_gotno;
158     unsigned mips_gotsym;
159#endif /* ANDROID_*_LINKER */
160
161    unsigned refcount;
162    struct link_map linkmap;
163
164    int constructors_called;
165
166    /* When you read a virtual address from the ELF file, add this
167     * value to get the corresponding address in the process' address space */

168    Elf32_Addr load_bias;
169    int has_text_relocations;
170};

soinfo_link_image는 __linker_init_post_relcation, __linker_init, 와 init_library() 에서 불린다.

__linker_init은 linker의 entry point이며, beging.S에서 불린다.  linker 자신을 위한 relocation을 행하며, __linker_init_post_relocation을 실행한다.  linker는 __linker_init에서 시작되며, 기본적으로 linker_so라는 soinfo구조체 변수가 세팅되면서 시작된다.  주의할 점은 링커 자체가 fix되기 전이기에 이 함수내에서 extern 변수나 함수 혹은 다른 GOT를 참조하면 segmentation fault가 난다.

 

__linker_init_post_relocation은 위에서 언급한대로, __linker_init이 끝나고 불리며,  elfdata베이스로 얻은 linker_addr을 인자로 받는다.

C 라이브러리의 런타임 initializer에 넘기기 위해 elfdata 포인터를 TLS에 저장하며 환경 변수에 대한 초기화를 한다.

soinfo_link_image를 부르기 전 LD_LIBRARY_PATH와 LD_PRELOAD에 대한 파싱을 한다.

 

(계속...)

 

.

'안드로이드' 카테고리의 다른 글

Google I/O, Android TV  (0) 2014.06.26
Posted by code cat

영문은

warning: overriding commands for target '...'


한글번역된 메세지는

경고: 타켓 '...'에 대한 명령어보다 다른 것이 우선합니다.


우선해서 어쩌라고..????????


이래서 overriding이 되는 줄 몰랐다.  왜 저렇게 번역했는지는 모르겠지만, 영문 메세지로 확인하니 overriding이 되는걸 확인 할 수 있었다.

'리눅스 > 스크립트/유틸' 카테고리의 다른 글

openssl 을 이용한 암호화 방법  (0) 2013.11.25
GDB  (0) 2013.09.24
[byobu] vertical line 없애기  (0) 2013.09.01
ubuntu에 설치된 패키지 리스트 보기  (0) 2013.07.25
[screen/byobu] 윈도우 숫자 바꾸기  (0) 2013.06.29
Posted by code cat

byobu를 쓰는 이유 중 하나가 바로 vertical line split 기능일 것이다. (나만 그럴 수도..)

물론 screen에도 vertical line patch가 있지만... byobu가 더 이쁘니까..


어쨌든, vertical line을 만들고 나서 없애는 방법에 대해서 몰라 그냥 죽이는 방법을 썼었는데, 오늘 찾아보니 다음과 같이 하면 vertical line을 없앨 수 있다.


ctrl + a :remove {enter}


역시 찾아보면 다 나온다...

Posted by code cat
리눅스/커널2013. 8. 9. 17:06

출처: http://dtbaker.net/random-bits/android-unknown-symbol-_global_offset_table_/

 

커널 올리는 중에 에러가 나길래 찾아본 결과, 아래와 같은 글이 있었다.  결론적으로 이 방법이 솔루션이 되지는 못했지만, 참고 사항으로 올린다.

 

 

Android: Unknown symbol _GLOBAL_OFFSET_TABLE_

[ 1525.047424] bcm4329: Unknown symbol _GLOBAL_OFFSET_TABLE_ (err 0)

I received this error after compiling a custom Android kernel and modules using the arm-linux-androideabi-4.4.3 prebuilt toolchain.

I used arm-linux-androideabi-4.4.3 instead of arm-eabi-4.4.0 because arm-eabi-4.4.0 did not work for me on 64bit ubuntu ( * shrug * )

To fix this and to get my kernel modules loading I opened the Makefile within my kernel source folder and changed this:

MODFLAGS        = -DMODULE -march=armv7-a -mfpu=vfpv3 -ftree-vectorize

to this:

MODFLAGS        = -DMODULE -march=armv7-a -mfpu=vfpv3 -ftree-vectorize -fno-pic

Then re-built the kernel modules:

make clean
make modules

and copied my new module back over to android, away she goes!

————————-

if you cannot find MODFLAGS in the Makefile then look for:

CFLAGS_MODULE   =

and change it to

CFLAGS_MODULE   = -fno-pic

 

 

아 그리고  -fno-pic이 도대체 뭔 옵션인지 궁금해서 찾아보았다.

정말 더럽게 안 나온다.

gcc 메뉴얼을 찾아보니, -fpic에 대해 다음과 같이 설명하고 있다.

 

"타겟 머신에서 지원하는 경우, 공유 라이브러리를 위한 position-independent 코드 (PIC)을 생성한다.  이러한 코드는 global offset table(GOT)를 통해 모든 상수 주소에 대한 접근을 시도한다.  dynamic loader는 프로그램 실행의 시작시에 GOT 엔트리들을 처리한다.(참고로 dynamic loader는 GCC의 일부가 아니며 operating system의 일부이다).  ...

Position-indenpendent code 는 특정 머신의 지원이 필요하다...

이 플래그가 설정 된 경우, "__pic__""__PIC__" 는 1로 정의된다."

 

따라서 -fno-pic의 경우 position-independent 코드를 생성하지 말라는 것으로 보인다.

'리눅스 > 커널' 카테고리의 다른 글

FrameBuffer size 구하기  (0) 2013.12.11
[커널] FB 문서  (0) 2013.12.09
Kernel Oops의 Taint 종류  (0) 2013.07.25
[OS] priority inversion 해결방법  (0) 2013.01.13
monolithic vs microkernel  (0) 2013.01.13
Posted by code cat
프로그래밍/C2013. 8. 7. 21:36

출처: http://www.technovelty.org/code/why-symbol-visibility-is-good.html

 

ELF 는 프로그램의 심볼을 관리하는데 있어서 두가지 방법이 있는데, 그중 하나가 symbol binding 이다.

symbol binding에는 크게 다음의 두가지 종류가 있다.

 

1. Global binding

2. Local binding

 

Global 바인딩은 현재 빌드되는 file 밖에까지의 visibility scope을 가지고 있다.(즉 외부참조가 가능하다고 할 수 있겠다)

Local 바인딩은 반대로 local scope(static)을 가지고 있다.  추가로 weak의 경우 global가 같으나 overriding이 가능하다고 볼 수 있겠다.

 

다음의 예를 보자.

sym.c


컴파일 해보면,(참고로 gcc -c는 컴파일/어셈블은 하되, 링크는 하지 말라는 소리이다)

$ gcc -o sym -c sym.c

$ readelf -s sym
 Symbol table '.symtab' contains 11 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
     5: 00000000     6 FUNC    LOCAL   DEFAULT    1 local
     8: 00000006     6 FUNC    GLOBAL DEFAULT    1 global
     9: 0000000c     6 FUNC    WEAK    DEFAULT    1 weak

 

위에서 말한 바와 같이 LOCAL, GLOBAL, WEAK으로 각각 분류된 것을 볼 수 있다.

 

다음의 경우를 보자.

 

This is all well and good, but starts breaking down when you want to load many different modules and keep strict API's (such as, say, dynamic libraries!).

Consider that for two files to share a common function, the function must end up with a global visibility.

file1.c

 

file2.c

file1 & file2는 같은 함수를 공유 하는데, 보면 알겠지만 common의 경우 함수 내부에서만 사용되고 있어, 외부로 노출 할 필요가 없는 함수이다.

 

컴파일 후 내용을 보면 다음과 같다.

$ gcc -shared -fPIC  -o libfile file1.c file2.c
$ readelf --syms libfile

 

Symbol table '.symtab' contains 55 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
    48: 000005fc    6   FUNC    GLOBAL DEFAULT   12 common
    50: 00000604    11 FUNC    GLOBAL DEFAULT   12 func

앞서 말했듯이, common의 경우 외부로 노출할 필요가 없음에도 GLOBAL 바인딩되어 있는 것을 볼 수 있다.

링킹도 잘 되고 동작성에 문제 없으나, 이렇게 외부로 노출 될 필요가 없는 경우를 대비해 ELF는 심볼에 대한 visibility를 제공한다.

이 visibility에는 default, protected, hidden 혹은 internal이 있다.

 

가장 안전한 방법으로는 전부 hidden으로 세팅하고(-fvisibility=hidden) 필요 시에,

file1.c

file2.c

 

 

$ gcc -fvisibility=hidden -shared -fPIC  -o library file1.c file2.c
$ readelf --syms ./library

Symbol table '.symtab' contains 55 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
    48: 000003cc     5 FUNC    LOCAL  HIDDEN   12 common
    54: 000003d4    29 FUNC    GLOBAL DEFAULT  12 func

 

 

이렇게 되면 dynamic loader는 더 이상 common쪽에 접근을 허용치 않는다.

참고로 이러한 방식은 퍼포먼스 향상에도 도움을 준다.  보통 심볼이 override됐을 때, dynamic loader가 function을 제대로 가리킬 수 있도록 컴파일러는 program lookup table(PLT)를 생성해야 한다.  그러나 위와 같이 한다면 PLT 생성을 생략 할 수 있다.

Posted by code cat