안드로이드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