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