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 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 unsigned 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 unsigned 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 %zd 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 (%zd) 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 (size_t)num_symbols != symdata->d_size / elsize, 309 "Length of dynsym filter (%d) must equal the number" 310 " of dynamic symbols (%zd)!\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 %zd).\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 %zd), " 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