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 |
---|