blob: 33b1ee7004bc064ec82a73e684448b2085a1da44 [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001#include <stdio.h>
2//#include <common.h>
3#include <debug.h>
4#include <libelf.h>
5#include <libebl.h>
6#include <libebl_arm.h>
7#include <elf.h>
8#include <gelf.h>
9#include <string.h>
10#include <errno.h>
11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16#ifdef SUPPORT_ANDROID_PRELINK_TAGS
17#include <prelink_info.h>
18#endif
19
20#include <elfcopy.h>
21
22void clone_elf(Elf *elf, Elf *newelf,
23 const char *elf_name,
24 const char *newelf_name,
25 bool *sym_filter, int num_symbols,
26 int shady
27#ifdef SUPPORT_ANDROID_PRELINK_TAGS
28 , int *prelinked,
29 int *elf_little,
Hristo Bojinov96be7202010-08-02 10:26:17 -070030 long *prelink_addr,
31 int *retouched,
32 unsigned int *retouch_byte_cnt,
33 char *retouch_buf
The Android Open Source Project88b60792009-03-03 19:28:42 -080034#endif
35 , bool rebuild_shstrtab,
36 bool strip_debug,
37 bool dry_run)
38{
39 GElf_Ehdr ehdr_mem, *ehdr; /* store ELF header of original library */
40 size_t shstrndx; /* section-strings-section index */
41 size_t shnum; /* number of sections in the original file */
42 /* string table for section headers in new file */
43 struct Ebl_Strtab *shst = NULL;
44 int dynamic_idx = -1; /* index in shdr_info[] of .dynamic section */
45 int dynsym_idx = -1; /* index in shdr_info[] of dynamic symbol table
46 section */
47
Kenny Rootafb36e72010-06-26 22:39:38 -070048 unsigned int cnt; /* general-purpose counter */
The Android Open Source Project88b60792009-03-03 19:28:42 -080049 /* This flag is true when at least one section is dropped or when the
50 relative order of sections has changed, so that section indices in
51 the resulting file will be different from those in the original. */
52 bool sections_dropped_or_rearranged;
53 Elf_Scn *scn; /* general-purpose section */
54 size_t idx; /* general-purporse section index */
55
56 shdr_info_t *shdr_info = NULL;
Kenny Rootafb36e72010-06-26 22:39:38 -070057 unsigned int shdr_info_len = 0;
The Android Open Source Project88b60792009-03-03 19:28:42 -080058 GElf_Phdr *phdr_info = NULL;
59
60 /* Get the information from the old file. */
61 ehdr = gelf_getehdr (elf, &ehdr_mem);
62 FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
63
64 /* Create new program header for the elf file */
65 FAILIF(gelf_newehdr (newelf, gelf_getclass (elf)) == 0 ||
66 (ehdr->e_type != ET_REL && gelf_newphdr (newelf,
67 ehdr->e_phnum) == 0),
68 "Cannot create new file: %s", elf_errmsg (-1));
69
70#ifdef SUPPORT_ANDROID_PRELINK_TAGS
71 ASSERT(prelinked);
72 ASSERT(prelink_addr);
73 ASSERT(elf_little);
74 *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
75 *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr);
Hristo Bojinov96be7202010-08-02 10:26:17 -070076 ASSERT(retouched);
77 ASSERT(retouch_byte_cnt);
78 ASSERT(retouch_buf);
79 *retouched = check_retouched(elf_name, *elf_little,
80 retouch_byte_cnt, retouch_buf);
The Android Open Source Project88b60792009-03-03 19:28:42 -080081#endif
82
83 INFO("\n\nCALCULATING MODIFICATIONS\n\n");
84
85 /* Copy out the old program header: notice that if the ELF file does not
86 have a program header, this loop won't execute.
87 */
88 INFO("Copying ELF program header...\n");
89 phdr_info = (GElf_Phdr *)CALLOC(ehdr->e_phnum, sizeof(GElf_Phdr));
90 for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) {
91 INFO("\tRetrieving entry %d\n", cnt);
92 FAILIF_LIBELF(NULL == gelf_getphdr(elf, cnt, phdr_info + cnt),
93 gelf_getphdr);
94 /* -- we update the header at the end
95 FAILIF_LIBELF(gelf_update_phdr (newelf, cnt, phdr_info + cnt) == 0,
96 gelf_update_phdr);
97 */
98 }
99
100 /* Get the section-header strings section. This section contains the
101 strings used to name the other sections. */
102 FAILIF_LIBELF(elf_getshstrndx(elf, &shstrndx) < 0, elf_getshstrndx);
103
104 /* Get the number of sections. */
105 FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
Kenny Rootafb36e72010-06-26 22:39:38 -0700106 INFO("Original ELF file has %zd sections.\n", shnum);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800107
108 /* Allocate the section-header-info buffer. We allocate one more entry
109 for the section-strings section because we regenerate that one and
110 place it at the very end of the file. Note that just because we create
111 an extra entry in the shdr_info array, it does not mean that we create
112 one more section the header. We just mark the old section for removal
113 and create one as the last section.
114 */
Kenny Rootafb36e72010-06-26 22:39:38 -0700115 INFO("Allocating section-header info structure (%zd) bytes...\n",
The Android Open Source Project88b60792009-03-03 19:28:42 -0800116 shnum*sizeof (shdr_info_t));
117 shdr_info_len = rebuild_shstrtab ? shnum + 1 : shnum;
118 shdr_info = (shdr_info_t *)CALLOC(shdr_info_len, sizeof (shdr_info_t));
119
120 /* Iterate over all the sections and initialize the internal section-info
121 array...
122 */
123 INFO("Initializing section-header info structure...\n");
124 /* Gather information about the sections in this file. */
125 scn = NULL;
126 cnt = 1;
127 while ((scn = elf_nextscn (elf, scn)) != NULL) {
128 ASSERT(elf_ndxscn(scn) == cnt);
129 shdr_info[cnt].scn = scn;
130 FAILIF_LIBELF(NULL == gelf_getshdr(scn, &shdr_info[cnt].shdr),
131 gelf_getshdr);
132
133 /* Get the name of the section. */
134 shdr_info[cnt].name = elf_strptr (elf, shstrndx,
135 shdr_info[cnt].shdr.sh_name);
136
137 INFO("\tname: %s\n", shdr_info[cnt].name);
138 FAILIF(shdr_info[cnt].name == NULL,
139 "Malformed file: section %d name is null\n",
140 cnt);
141
142 /* Mark them as present but not yet investigated. By "investigating"
143 sections, we mean that we check to see if by stripping other
144 sections, the sections under investigation will be compromised. For
145 example, if we are removing a section of code, then we want to make
146 sure that the symbol table does not contain symbols that refer to
147 this code, so we investigate the symbol table. If we do find such
148 symbols, we will not strip the code section.
149 */
150 shdr_info[cnt].idx = 1;
151
152 /* Remember the shdr.sh_link value. We need to remember this value
153 for those sections that refer to other sections. For example,
154 we need to remember it for relocation-entry sections, because if
155 we modify the symbol table that a relocation-entry section is
156 relative to, then we need to patch the relocation section. By the
157 time we get to deciding whether we need to patch the relocation
158 section, we will have overwritten its header's sh_link field with
159 a new value.
160 */
161 shdr_info[cnt].old_shdr = shdr_info[cnt].shdr;
162 INFO("\t\toriginal sh_link: %08d\n", shdr_info[cnt].old_shdr.sh_link);
163 INFO("\t\toriginal sh_addr: %lld\n", shdr_info[cnt].old_shdr.sh_addr);
164 INFO("\t\toriginal sh_offset: %lld\n",
165 shdr_info[cnt].old_shdr.sh_offset);
166 INFO("\t\toriginal sh_size: %lld\n", shdr_info[cnt].old_shdr.sh_size);
167
168 if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) {
169 INFO("\t\tthis is the SHT_DYNAMIC section [%s] at index %d\n",
170 shdr_info[cnt].name,
171 cnt);
172 dynamic_idx = cnt;
173 }
174 else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM) {
175 INFO("\t\tthis is the SHT_DYNSYM section [%s] at index %d\n",
176 shdr_info[cnt].name,
177 cnt);
178 dynsym_idx = cnt;
179 }
180
181 FAILIF(shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX,
182 "Cannot handle sh_type SHT_SYMTAB_SHNDX!\n");
183 FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP,
184 "Cannot handle sh_type SHT_GROUP!\n");
185 FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
186 "Cannot handle sh_type SHT_GNU_versym!\n");
187
188 /* Increment the counter. */
189 ++cnt;
190 } /* while */
191
192 /* Get the EBL handling. */
193 Ebl *ebl = ebl_openbackend (elf);
194 FAILIF_LIBELF(NULL == ebl, ebl_openbackend);
195 FAILIF_LIBELF(0 != arm_init(elf, ehdr->e_machine, ebl, sizeof(Ebl)),
196 arm_init);
197
198 if (strip_debug) {
199
200 /* This will actually strip more than just sections. It will strip
201 anything not essential to running the image.
202 */
203
204 INFO("Finding debug sections to strip.\n");
205
206 /* Now determine which sections can go away. The general rule is that
207 all sections which are not used at runtime are stripped out. But
208 there are a few exceptions:
209
210 - special sections named ".comment" and ".note" are kept
211 - OS or architecture specific sections are kept since we might not
212 know how to handle them
213 - if a section is referred to from a section which is not removed
214 in the sh_link or sh_info element it cannot be removed either
215 */
216 for (cnt = 1; cnt < shnum; ++cnt) {
217 /* Check whether the section can be removed. */
218 if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
219 shdr_info[cnt].name,
220 1, /* remove .comment sections */
221 1 /* remove all debug sections */) ||
222 /* The macro above is broken--check for .comment explicitly */
223 !strcmp(".comment", shdr_info[cnt].name)
224#ifdef ARM_SPECIFIC_HACKS
225 ||
226 /* We ignore this section, that's why we can remove it. */
227 !strcmp(".stack", shdr_info[cnt].name)
228#endif
229 )
230 {
231 /* For now assume this section will be removed. */
232 INFO("Section [%s] will be stripped from image.\n",
233 shdr_info[cnt].name);
234 shdr_info[cnt].idx = 0;
235 }
236#ifdef STRIP_STATIC_SYMBOLS
237 else if (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB) {
238 /* Mark the static symbol table for removal */
239 INFO("Section [%s] (static symbol table) will be stripped from image.\n",
240 shdr_info[cnt].name);
241 shdr_info[cnt].idx = 0;
242 if (shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type ==
243 SHT_STRTAB)
244 {
245 /* Mark the symbol table's string table for removal. */
246 INFO("Section [%s] (static symbol-string table) will be stripped from image.\n",
Iliyan Malchev90209952009-03-24 19:58:46 -0700247 shdr_info[shdr_info[cnt].shdr.sh_link].name);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800248 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 0;
249 }
250 else {
251 ERROR("Expecting the sh_link field of a symbol table to point to"
252 " associated symbol-strings table! This is not mandated by"
253 " the standard, but is a common practice and the only way "
254 " to know for sure which strings table corresponds to which"
255 " symbol table!\n");
256 }
257 }
258#endif
259 }
260
261 /* Mark the SHT_NULL section as handled. */
262 shdr_info[0].idx = 2;
263
264 /* Handle exceptions: section groups and cross-references. We might have
265 to repeat this a few times since the resetting of the flag might
266 propagate.
267 */
268 int exceptions_pass = 0;
269 bool changes;
270 do {
271 changes = false;
272 INFO("\nHandling exceptions, pass %d\n\n", exceptions_pass++);
273 for (cnt = 1; cnt < shnum; ++cnt) {
274 if (shdr_info[cnt].idx == 0) {
275 /* If a relocation section is marked as being removed but the
276 section it is relocating is not, then do not remove the
277 relocation section.
278 */
279 if ((shdr_info[cnt].shdr.sh_type == SHT_REL
280 || shdr_info[cnt].shdr.sh_type == SHT_RELA)
281 && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) {
282 PRINT("\tSection [%s] will not be removed because the "
283 "section it is relocating (%s) stays.\n",
284 shdr_info[cnt].name,
285 shdr_info[shdr_info[cnt].shdr.sh_info].name);
286 }
287 }
288 if (shdr_info[cnt].idx == 1) {
289 INFO("Processing section [%s]...\n", shdr_info[cnt].name);
290
291 /* The content of symbol tables we don't remove must not
292 reference any section which we do remove. Otherwise
293 we cannot remove the referred section.
294 */
295 if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM ||
296 shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
297 {
298 Elf_Data *symdata;
299 size_t elsize;
300
301 INFO("\tSection [%s] is a symbol table that's not being"
302 " removed.\n\tChecking to make sure that no symbols"
303 " refer to sections that are being removed.\n",
304 shdr_info[cnt].name);
305
306 /* Make sure the data is loaded. */
307 symdata = elf_getdata (shdr_info[cnt].scn, NULL);
308 FAILIF_LIBELF(NULL == symdata, elf_getdata);
309
310 /* Go through all symbols and make sure the section they
311 reference is not removed. */
312 elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
313
314 /* Check the length of the dynamic-symbol filter. */
315 FAILIF(sym_filter != NULL &&
Kenny Rootafb36e72010-06-26 22:39:38 -0700316 (size_t)num_symbols != symdata->d_size / elsize,
The Android Open Source Project88b60792009-03-03 19:28:42 -0800317 "Length of dynsym filter (%d) must equal the number"
Kenny Rootafb36e72010-06-26 22:39:38 -0700318 " of dynamic symbols (%zd)!\n",
The Android Open Source Project88b60792009-03-03 19:28:42 -0800319 num_symbols,
320 symdata->d_size / elsize);
321
322 size_t inner;
323 for (inner = 0;
324 inner < symdata->d_size / elsize;
325 ++inner)
326 {
327 GElf_Sym sym_mem;
328 GElf_Sym *sym;
329 size_t scnidx;
330
331 sym = gelf_getsymshndx (symdata, NULL,
332 inner, &sym_mem, NULL);
333 FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);
334
335 scnidx = sym->st_shndx;
336 FAILIF(scnidx == SHN_XINDEX,
337 "Can't handle SHN_XINDEX!\n");
338 if (scnidx == SHN_UNDEF ||
339 scnidx >= shnum ||
340 (scnidx >= SHN_LORESERVE &&
341 scnidx <= SHN_HIRESERVE) ||
342 GELF_ST_TYPE (sym->st_info) == STT_SECTION)
343 {
344 continue;
345 }
346
347 /* If the symbol is going to be thrown and it is a
348 global or weak symbol that is defined (not imported),
349 then continue. Since the symbol is going away, we
350 do not care whether it refers to a section that is
351 also going away.
352 */
353 if (sym_filter && !sym_filter[inner])
354 {
355 bool global_or_weak =
356 ELF32_ST_BIND(sym->st_info) == STB_GLOBAL ||
357 ELF32_ST_BIND(sym->st_info) == STB_WEAK;
358 if (!global_or_weak && sym->st_shndx != SHN_UNDEF)
359 continue;
360 }
361
362 /* -- far too much output
363 INFO("\t\t\tSymbol [%s] (%d)\n",
364 elf_strptr(elf,
365 shdr_info[cnt].shdr.sh_link,
366 sym->st_name),
367 shdr_info[cnt].shdr.sh_info);
368 */
369
370 if (shdr_info[scnidx].idx == 0)
371 {
372 PRINT("\t\t\tSymbol [%s] refers to section [%s], "
373 "which is being removed. Will keep that "
374 "section.\n",
375 elf_strptr(elf,
376 shdr_info[cnt].shdr.sh_link,
377 sym->st_name),
378 shdr_info[scnidx].name);
379 /* Mark this section as used. */
380 shdr_info[scnidx].idx = 1;
381 changes |= scnidx < cnt;
382 }
383 } /* for each symbol */
384 } /* section type is SHT_DYNSYM or SHT_SYMTAB */
385 /* Cross referencing happens:
386 - for the cases the ELF specification says. That are
387 + SHT_DYNAMIC in sh_link to string table
388 + SHT_HASH in sh_link to symbol table
389 + SHT_REL and SHT_RELA in sh_link to symbol table
390 + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
391 + SHT_GROUP in sh_link to symbol table
392 + SHT_SYMTAB_SHNDX in sh_link to symbol table
393 Other (OS or architecture-specific) sections might as
394 well use this field so we process it unconditionally.
395 - references inside section groups
396 - specially marked references in sh_info if the SHF_INFO_LINK
397 flag is set
398 */
399
400 if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0) {
401 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
402 changes |= shdr_info[cnt].shdr.sh_link < cnt;
403 }
404
405 /* Handle references through sh_info. */
406 if (SH_INFO_LINK_P (&shdr_info[cnt].shdr) &&
407 shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) {
408 PRINT("\tSection [%s] links to section [%s], which was "
409 "marked for removal--it will not be removed.\n",
410 shdr_info[cnt].name,
411 shdr_info[shdr_info[cnt].shdr.sh_info].name);
412
413 shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
414 changes |= shdr_info[cnt].shdr.sh_info < cnt;
415 }
416
417 /* Mark the section as investigated. */
418 shdr_info[cnt].idx = 2;
419 } /* if (shdr_info[cnt].idx == 1) */
420 } /* for (cnt = 1; cnt < shnum; ++cnt) */
421 } while (changes);
422 }
423 else {
424 INFO("Not stripping sections.\n");
425 /* Mark the SHT_NULL section as handled. */
426 shdr_info[0].idx = 2;
427 }
428
429 /* Mark the section header string table as unused, we will create
430 a new one as the very last section in the new ELF file.
431 */
432 shdr_info[shstrndx].idx = rebuild_shstrtab ? 0 : 2;
433
434 /* We need a string table for the section headers. */
435 FAILIF_LIBELF((shst = ebl_strtabinit (1 /* null-terminated */)) == NULL,
436 ebl_strtabinit);
437
438 /* Assign new section numbers. */
439 INFO("Creating new sections...\n");
440 //shdr_info[0].idx = 0;
441 for (cnt = idx = 1; cnt < shnum; ++cnt) {
442 if (shdr_info[cnt].idx > 0) {
443 shdr_info[cnt].idx = idx++;
444
445 /* Create a new section. */
446 FAILIF_LIBELF((shdr_info[cnt].newscn =
447 elf_newscn(newelf)) == NULL, elf_newscn);
448 ASSERT(elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
449
450 /* Add this name to the section header string table. */
451 shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
452
453 INFO("\tsection [%s] (old offset %lld, old size %lld) will have index %d "
Kenny Rootafb36e72010-06-26 22:39:38 -0700454 "(was %zd).\n",
The Android Open Source Project88b60792009-03-03 19:28:42 -0800455 shdr_info[cnt].name,
456 shdr_info[cnt].old_shdr.sh_offset,
457 shdr_info[cnt].old_shdr.sh_size,
458 shdr_info[cnt].idx,
459 elf_ndxscn(shdr_info[cnt].scn));
460 } else {
Kenny Rootafb36e72010-06-26 22:39:38 -0700461 INFO("\tIgnoring section [%s] (offset %lld, size %lld, index %zd), "
The Android Open Source Project88b60792009-03-03 19:28:42 -0800462 "it will be discarded.\n",
463 shdr_info[cnt].name,
464 shdr_info[cnt].shdr.sh_offset,
465 shdr_info[cnt].shdr.sh_size,
466 elf_ndxscn(shdr_info[cnt].scn));
467 }
468 } /* for */
469
470 sections_dropped_or_rearranged = idx != cnt;
471
472 Elf_Data *shstrtab_data = NULL;
473
474#if 0
475 /* Fail if sections are being dropped or rearranged (except for moving shstrtab) or the
476 symbol filter is not empty, AND the file is an executable.
477 */
478 FAILIF(((idx != cnt && !(cnt - idx == 1 && rebuild_shstrtab)) || sym_filter != NULL) &&
479 ehdr->e_type != ET_DYN,
480 "You may not rearrange sections or strip symbols on an executable file!\n");
481#endif
482
483 INFO("\n\nADJUSTING ELF FILE\n\n");
484
485 adjust_elf(elf, elf_name,
486 newelf, newelf_name,
487 ebl,
488 ehdr, /* store ELF header of original library */
489 sym_filter, num_symbols,
490 shdr_info, shdr_info_len,
491 phdr_info,
492 idx, /* highest_scn_num */
493 shnum,
494 shstrndx,
495 shst,
496 sections_dropped_or_rearranged,
497 dynamic_idx, /* index in shdr_info[] of .dynamic section */
498 dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
499 shady,
500 &shstrtab_data,
501 ehdr->e_type == ET_DYN, /* adjust section ofsets only when the file is a shared library */
502 rebuild_shstrtab);
503
504 /* We have everything from the old file. */
505 FAILIF_LIBELF(elf_cntl(elf, ELF_C_FDDONE) != 0, elf_cntl);
506
507 /* The ELF library better follows our layout when this is not a
508 relocatable object file. */
509 elf_flagelf (newelf,
510 ELF_C_SET,
511 (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0));
512
513 /* Finally write the file. */
514 FAILIF_LIBELF(!dry_run && elf_update(newelf, ELF_C_WRITE) == -1, elf_update);
515
516 if (shdr_info != NULL) {
517 /* For some sections we might have created an table to map symbol
518 table indices. */
519 for (cnt = 1; cnt < shdr_info_len; ++cnt) {
520 FREEIF(shdr_info[cnt].newsymidx);
521 FREEIF(shdr_info[cnt].symse);
522 if(shdr_info[cnt].dynsymst != NULL)
523 ebl_strtabfree (shdr_info[cnt].dynsymst);
524 }
525 /* Free the memory. */
526 FREE (shdr_info);
527 }
528 FREEIF(phdr_info);
529
530 ebl_closebackend(ebl);
531
532 /* Free other resources. */
533 if (shst != NULL) ebl_strtabfree (shst);
534 if (shstrtab_data != NULL)
535 FREEIF(shstrtab_data->d_buf);
536}