1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Routines for preparing tdata trees for conversion into CTF data, and 30 * for placing the resulting data into an output file. 31 */ 32 33 #if HAVE_NBTOOL_CONFIG_H 34 # include "nbtool_config.h" 35 #endif 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <strings.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <fcntl.h> 43 #include <libelf.h> 44 #include <gelf.h> 45 #include <unistd.h> 46 47 #include "ctftools.h" 48 #include "list.h" 49 #include "memory.h" 50 #include "traverse.h" 51 #include "symbol.h" 52 53 typedef struct iidesc_match { 54 int iim_fuzzy; 55 iidesc_t *iim_ret; 56 char *iim_name; 57 char *iim_file; 58 uchar_t iim_bind; 59 } iidesc_match_t; 60 61 static int 62 burst_iitypes(void *data, void *arg) 63 { 64 iidesc_t *ii = data; 65 iiburst_t *iiburst = arg; 66 67 switch (ii->ii_type) { 68 case II_GFUN: 69 case II_SFUN: 70 case II_GVAR: 71 case II_SVAR: 72 if (!(ii->ii_flags & IIDESC_F_USED)) 73 return (0); 74 break; 75 default: 76 break; 77 } 78 79 ii->ii_dtype->t_flags |= TDESC_F_ISROOT; 80 (void) iitraverse_td(ii, iiburst->iib_tdtd); 81 return (1); 82 } 83 84 /*ARGSUSED1*/ 85 static int 86 save_type_by_id(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private) 87 { 88 iiburst_t *iiburst = private; 89 90 /* 91 * Doing this on every node is horribly inefficient, but given that 92 * we may be suppressing some types, we can't trust nextid in the 93 * tdata_t. 94 */ 95 if (tdp->t_id > iiburst->iib_maxtypeid) 96 iiburst->iib_maxtypeid = tdp->t_id; 97 98 slist_add(&iiburst->iib_types, tdp, tdesc_idcmp); 99 100 return (1); 101 } 102 103 static tdtrav_cb_f burst_types_cbs[] = { 104 NULL, 105 save_type_by_id, /* intrinsic */ 106 save_type_by_id, /* pointer */ 107 save_type_by_id, /* reference */ 108 save_type_by_id, /* array */ 109 save_type_by_id, /* function */ 110 save_type_by_id, /* struct */ 111 save_type_by_id, /* union */ 112 save_type_by_id, /* class */ 113 save_type_by_id, /* enum */ 114 save_type_by_id, /* forward */ 115 save_type_by_id, /* typedef */ 116 tdtrav_assert, /* typedef_unres */ 117 save_type_by_id, /* volatile */ 118 save_type_by_id, /* const */ 119 save_type_by_id /* restrict */ 120 }; 121 122 123 static iiburst_t * 124 iiburst_new(tdata_t *td, int max) 125 { 126 iiburst_t *iiburst = xcalloc(sizeof (iiburst_t)); 127 iiburst->iib_td = td; 128 iiburst->iib_funcs = xcalloc(sizeof (iidesc_t *) * max); 129 iiburst->iib_nfuncs = 0; 130 iiburst->iib_objts = xcalloc(sizeof (iidesc_t *) * max); 131 iiburst->iib_nobjts = 0; 132 return (iiburst); 133 } 134 135 static void 136 iiburst_types(iiburst_t *iiburst) 137 { 138 tdtrav_data_t tdtd; 139 140 tdtrav_init(&tdtd, &iiburst->iib_td->td_curvgen, NULL, burst_types_cbs, 141 NULL, (void *)iiburst); 142 143 iiburst->iib_tdtd = &tdtd; 144 145 (void) hash_iter(iiburst->iib_td->td_iihash, burst_iitypes, iiburst); 146 } 147 148 static void 149 iiburst_free(iiburst_t *iiburst) 150 { 151 free(iiburst->iib_funcs); 152 free(iiburst->iib_objts); 153 list_free(iiburst->iib_types, NULL, NULL); 154 free(iiburst); 155 } 156 157 /* 158 * See if this iidesc matches the ELF symbol data we pass in. 159 * 160 * A fuzzy match is where we have a local symbol matching the name of a 161 * global type description. This is common when a mapfile is used for a 162 * DSO, but we don't accept it by default. 163 * 164 * A weak fuzzy match is when a weak symbol was resolved and matched to 165 * a global type description. 166 */ 167 static int 168 matching_iidesc(void *arg1, void *arg2) 169 { 170 iidesc_t *iidesc = arg1; 171 iidesc_match_t *match = arg2; 172 if (streq(iidesc->ii_name, match->iim_name) == 0) 173 return (0); 174 175 switch (iidesc->ii_type) { 176 case II_GFUN: 177 case II_GVAR: 178 if (match->iim_bind == STB_GLOBAL) { 179 match->iim_ret = iidesc; 180 return (-1); 181 } else if (match->iim_fuzzy && match->iim_ret == NULL) { 182 match->iim_ret = iidesc; 183 /* continue to look for strong match */ 184 return (0); 185 } 186 break; 187 case II_SFUN: 188 case II_SVAR: 189 if (match->iim_bind == STB_LOCAL && 190 match->iim_file != NULL && 191 streq(iidesc->ii_owner, match->iim_file)) { 192 match->iim_ret = iidesc; 193 return (-1); 194 } 195 break; 196 default: 197 break; 198 } 199 return (0); 200 } 201 202 static iidesc_t * 203 find_iidesc(tdata_t *td, iidesc_match_t *match) 204 { 205 match->iim_ret = NULL; 206 iter_iidescs_by_name(td, match->iim_name, 207 matching_iidesc, match); 208 return (match->iim_ret); 209 } 210 211 /* 212 * If we have a weak symbol, attempt to find the strong symbol it will 213 * resolve to. Note: the code where this actually happens is in 214 * sym_process() in cmd/sgs/libld/common/syms.c 215 * 216 * Finding the matching symbol is unfortunately not trivial. For a 217 * symbol to be a candidate, it must: 218 * 219 * - have the same type (function, object) 220 * - have the same value (address) 221 * - have the same size 222 * - not be another weak symbol 223 * - belong to the same section (checked via section index) 224 * 225 * If such a candidate is global, then we assume we've found it. The 226 * linker generates the symbol table such that the curfile might be 227 * incorrect; this is OK for global symbols, since find_iidesc() doesn't 228 * need to check for the source file for the symbol. 229 * 230 * We might have found a strong local symbol, where the curfile is 231 * accurate and matches that of the weak symbol. We assume this is a 232 * reasonable match. 233 * 234 * If we've got a local symbol with a non-matching curfile, there are 235 * two possibilities. Either this is a completely different symbol, or 236 * it's a once-global symbol that was scoped to local via a mapfile. In 237 * the latter case, curfile is likely inaccurate since the linker does 238 * not preserve the needed curfile in the order of the symbol table (see 239 * the comments about locally scoped symbols in libld's update_osym()). 240 * As we can't tell this case from the former one, we use this symbol 241 * iff no other matching symbol is found. 242 * 243 * What we really need here is a SUNW section containing weak<->strong 244 * mappings that we can consume. 245 */ 246 static int 247 check_for_weak(GElf_Sym *weak, char const *weakfile, 248 Elf_Data *data, int nent, Elf_Data *strdata, 249 GElf_Sym *retsym, char **curfilep) 250 { 251 char *curfile = NULL; 252 char *tmpfile1 = NULL; 253 GElf_Sym tmpsym; 254 int candidate = 0; 255 int i; 256 tmpsym.st_info = 0; 257 tmpsym.st_name = 0; 258 259 if (GELF_ST_BIND(weak->st_info) != STB_WEAK) 260 return (0); 261 262 for (i = 0; i < nent; i++) { 263 GElf_Sym sym; 264 uchar_t type; 265 266 if (gelf_getsym(data, i, &sym) == NULL) 267 continue; 268 269 type = GELF_ST_TYPE(sym.st_info); 270 271 if (type == STT_FILE) 272 curfile = (char *)strdata->d_buf + sym.st_name; 273 274 if (GELF_ST_TYPE(weak->st_info) != type || 275 weak->st_value != sym.st_value) 276 continue; 277 278 if (weak->st_size != sym.st_size) 279 continue; 280 281 if (GELF_ST_BIND(sym.st_info) == STB_WEAK) 282 continue; 283 284 if (sym.st_shndx != weak->st_shndx) 285 continue; 286 287 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL && 288 (curfile == NULL || weakfile == NULL || 289 strcmp(curfile, weakfile) != 0)) { 290 candidate = 1; 291 tmpfile1 = curfile; 292 tmpsym = sym; 293 continue; 294 } 295 296 *curfilep = curfile; 297 *retsym = sym; 298 return (1); 299 } 300 301 if (candidate) { 302 *curfilep = tmpfile1; 303 *retsym = tmpsym; 304 return (1); 305 } 306 307 return (0); 308 } 309 310 /* 311 * When we've found the underlying symbol's type description 312 * for a weak symbol, we need to copy it and rename it to match 313 * the weak symbol. We also need to add it to the td so it's 314 * handled along with the others later. 315 */ 316 static iidesc_t * 317 copy_from_strong(tdata_t *td, GElf_Sym *sym, iidesc_t *strongdesc, 318 const char *weakname, const char *weakfile) 319 { 320 iidesc_t *new = iidesc_dup_rename(strongdesc, weakname, weakfile); 321 uchar_t type = GELF_ST_TYPE(sym->st_info); 322 323 switch (type) { 324 case STT_OBJECT: 325 new->ii_type = II_GVAR; 326 break; 327 case STT_FUNC: 328 new->ii_type = II_GFUN; 329 break; 330 } 331 332 hash_add(td->td_iihash, new); 333 334 return (new); 335 } 336 337 /* 338 * Process the symbol table of the output file, associating each symbol 339 * with a type description if possible, and sorting them into functions 340 * and data, maintaining symbol table order. 341 */ 342 static iiburst_t * 343 sort_iidescs(Elf *elf, const char *file, tdata_t *td, int fuzzymatch, 344 int dynsym) 345 { 346 iiburst_t *iiburst; 347 Elf_Scn *scn; 348 GElf_Shdr shdr; 349 Elf_Data *data, *strdata; 350 int i, stidx; 351 int nent; 352 iidesc_match_t match; 353 354 match.iim_fuzzy = fuzzymatch; 355 match.iim_file = NULL; 356 357 if ((stidx = findelfsecidx(elf, file, 358 dynsym ? ".dynsym" : ".symtab")) < 0) 359 terminate("%s: Can't open symbol table\n", file); 360 scn = elf_getscn(elf, stidx); 361 data = elf_getdata(scn, NULL); 362 gelf_getshdr(scn, &shdr); 363 nent = shdr.sh_size / shdr.sh_entsize; 364 365 scn = elf_getscn(elf, shdr.sh_link); 366 strdata = elf_getdata(scn, NULL); 367 368 iiburst = iiburst_new(td, nent); 369 370 for (i = 0; i < nent; i++) { 371 GElf_Sym sym; 372 char *bname; 373 iidesc_t **tolist; 374 GElf_Sym ssym; 375 iidesc_match_t smatch; 376 int *curr; 377 iidesc_t *iidesc; 378 379 if (gelf_getsym(data, i, &sym) == NULL) 380 elfterminate(file, "Couldn't read symbol %d", i); 381 382 match.iim_name = (char *)strdata->d_buf + sym.st_name; 383 match.iim_bind = GELF_ST_BIND(sym.st_info); 384 385 switch (GELF_ST_TYPE(sym.st_info)) { 386 case STT_FILE: 387 bname = strrchr(match.iim_name, '/'); 388 match.iim_file = bname == NULL ? match.iim_name : bname + 1; 389 continue; 390 case STT_OBJECT: 391 tolist = iiburst->iib_objts; 392 curr = &iiburst->iib_nobjts; 393 break; 394 case STT_FUNC: 395 tolist = iiburst->iib_funcs; 396 curr = &iiburst->iib_nfuncs; 397 break; 398 default: 399 continue; 400 } 401 402 if (ignore_symbol(&sym, match.iim_name)) 403 continue; 404 405 iidesc = find_iidesc(td, &match); 406 407 if (iidesc != NULL) { 408 tolist[*curr] = iidesc; 409 iidesc->ii_flags |= IIDESC_F_USED; 410 (*curr)++; 411 continue; 412 } 413 414 if (!check_for_weak(&sym, match.iim_file, data, nent, strdata, 415 &ssym, &smatch.iim_file)) { 416 (*curr)++; 417 continue; 418 } 419 420 smatch.iim_fuzzy = fuzzymatch; 421 smatch.iim_name = (char *)strdata->d_buf + ssym.st_name; 422 smatch.iim_bind = GELF_ST_BIND(ssym.st_info); 423 424 debug(3, "Weak symbol %s resolved to %s\n", match.iim_name, 425 smatch.iim_name); 426 427 iidesc = find_iidesc(td, &smatch); 428 429 if (iidesc != NULL) { 430 tolist[*curr] = copy_from_strong(td, &sym, 431 iidesc, match.iim_name, match.iim_file); 432 tolist[*curr]->ii_flags |= IIDESC_F_USED; 433 } 434 435 (*curr)++; 436 } 437 438 /* 439 * Stabs are generated for every function declared in a given C source 440 * file. When converting an object file, we may encounter a stab that 441 * has no symbol table entry because the optimizer has decided to omit 442 * that item (for example, an unreferenced static function). We may 443 * see iidescs that do not have an associated symtab entry, and so 444 * we do not write records for those functions into the CTF data. 445 * All others get marked as a root by this function. 446 */ 447 iiburst_types(iiburst); 448 449 /* 450 * By not adding some of the functions and/or objects, we may have 451 * caused some types that were referenced solely by those 452 * functions/objects to be suppressed. This could cause a label, 453 * generated prior to the evisceration, to be incorrect. Find the 454 * highest type index, and change the label indicies to be no higher 455 * than this value. 456 */ 457 tdata_label_newmax(td, iiburst->iib_maxtypeid); 458 459 return (iiburst); 460 } 461 462 static void 463 write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname, 464 caddr_t ctfdata, size_t ctfsize, int flags) 465 { 466 GElf_Ehdr sehdr, dehdr; 467 Elf_Scn *sscn, *dscn; 468 Elf_Data *sdata, *ddata; 469 GElf_Shdr shdr; 470 GElf_Word symtab_type; 471 int symtab_idx = -1; 472 off_t new_offset = 0; 473 off_t ctfnameoff = 0; 474 int dynsym = (flags & CTF_USE_DYNSYM); 475 int keep_stabs = (flags & CTF_KEEP_STABS); 476 int *secxlate; 477 int srcidx, dstidx; 478 int curnmoff = 0; 479 int changing = 0; 480 int pad; 481 int i; 482 483 if (gelf_newehdr(dst, gelf_getclass(src)) == NULL) 484 elfterminate(dstname, "Cannot copy ehdr to temp file"); 485 gelf_getehdr(src, &sehdr); 486 memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr)); 487 gelf_update_ehdr(dst, &dehdr); 488 489 symtab_type = dynsym ? SHT_DYNSYM : SHT_SYMTAB; 490 491 /* 492 * Neither the existing stab sections nor the SUNW_ctf sections (new or 493 * existing) are SHF_ALLOC'd, so they won't be in areas referenced by 494 * program headers. As such, we can just blindly copy the program 495 * headers from the existing file to the new file. 496 */ 497 if (sehdr.e_phnum != 0) { 498 (void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT); 499 if (gelf_newphdr(dst, sehdr.e_phnum) == NULL) 500 elfterminate(dstname, "Cannot make phdrs in temp file"); 501 502 for (i = 0; i < sehdr.e_phnum; i++) { 503 GElf_Phdr phdr; 504 505 gelf_getphdr(src, i, &phdr); 506 gelf_update_phdr(dst, i, &phdr); 507 } 508 } 509 510 secxlate = xmalloc(sizeof (int) * sehdr.e_shnum); 511 for (srcidx = dstidx = 0; srcidx < sehdr.e_shnum; srcidx++) { 512 Elf_Scn *scn = elf_getscn(src, srcidx); 513 GElf_Shdr shdr1; 514 char *sname; 515 516 gelf_getshdr(scn, &shdr1); 517 sname = elf_strptr(src, sehdr.e_shstrndx, shdr1.sh_name); 518 if (sname == NULL) { 519 elfterminate(srcname, "Can't find string at %u", 520 shdr1.sh_name); 521 } 522 523 if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) { 524 secxlate[srcidx] = -1; 525 } else if (!keep_stabs && 526 (strncmp(sname, ".stab", 5) == 0 || 527 strncmp(sname, ".debug", 6) == 0 || 528 strncmp(sname, ".rel.debug", 10) == 0 || 529 strncmp(sname, ".rela.debug", 11) == 0)) { 530 secxlate[srcidx] = -1; 531 } else if (dynsym && shdr1.sh_type == SHT_SYMTAB) { 532 /* 533 * If we're building CTF against the dynsym, 534 * we'll rip out the symtab so debuggers aren't 535 * confused. 536 */ 537 secxlate[srcidx] = -1; 538 } else { 539 secxlate[srcidx] = dstidx++; 540 curnmoff += strlen(sname) + 1; 541 } 542 543 new_offset = (off_t)dehdr.e_phoff; 544 } 545 546 for (srcidx = 1; srcidx < sehdr.e_shnum; srcidx++) { 547 char *sname; 548 549 sscn = elf_getscn(src, srcidx); 550 gelf_getshdr(sscn, &shdr); 551 552 if (secxlate[srcidx] == -1) { 553 changing = 1; 554 continue; 555 } 556 557 dscn = elf_newscn(dst); 558 559 /* 560 * If this file has program headers, we need to explicitly lay 561 * out sections. If none of the sections prior to this one have 562 * been removed, then we can just use the existing location. If 563 * one or more sections have been changed, then we need to 564 * adjust this one to avoid holes. 565 */ 566 if (changing && sehdr.e_phnum != 0) { 567 pad = new_offset % shdr.sh_addralign; 568 569 if (pad) 570 new_offset += shdr.sh_addralign - pad; 571 shdr.sh_offset = new_offset; 572 } 573 574 shdr.sh_link = secxlate[shdr.sh_link]; 575 576 if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) 577 shdr.sh_info = secxlate[shdr.sh_info]; 578 579 sname = elf_strptr(src, sehdr.e_shstrndx, shdr.sh_name); 580 if (sname == NULL) { 581 elfterminate(srcname, "Can't find string at %u", 582 shdr.sh_name); 583 } 584 585 #if !defined(sun) 586 if (gelf_update_shdr(dscn, &shdr) == 0) 587 elfterminate(dstname, "Cannot update sect %s", sname); 588 #endif 589 590 if ((sdata = elf_getdata(sscn, NULL)) == NULL) 591 elfterminate(srcname, "Cannot get sect %s data", sname); 592 if ((ddata = elf_newdata(dscn)) == NULL) 593 elfterminate(dstname, "Can't make sect %s data", sname); 594 #if defined(sun) 595 bcopy(sdata, ddata, sizeof (Elf_Data)); 596 #else 597 /* 598 * FreeBSD's Elf_Data has private fields which the 599 * elf_* routines manage. Simply copying the 600 * entire structure corrupts the data. So we need 601 * to copy the public fields explictly. 602 */ 603 ddata->d_align = sdata->d_align; 604 ddata->d_off = sdata->d_off; 605 ddata->d_size = sdata->d_size; 606 ddata->d_type = sdata->d_type; 607 ddata->d_version = sdata->d_version; 608 #endif 609 610 if (srcidx == sehdr.e_shstrndx) { 611 char seclen = strlen(CTF_ELF_SCN_NAME); 612 613 ddata->d_buf = xmalloc(ddata->d_size + shdr.sh_size + 614 seclen + 1); 615 bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); 616 strcpy((caddr_t)ddata->d_buf + shdr.sh_size, 617 CTF_ELF_SCN_NAME); 618 ctfnameoff = (off_t)shdr.sh_size; 619 shdr.sh_size += seclen + 1; 620 ddata->d_size += seclen + 1; 621 622 if (sehdr.e_phnum != 0) 623 changing = 1; 624 } 625 626 if (shdr.sh_type == symtab_type && shdr.sh_entsize != 0) { 627 int nsym = shdr.sh_size / shdr.sh_entsize; 628 629 symtab_idx = secxlate[srcidx]; 630 631 ddata->d_buf = xmalloc(shdr.sh_size); 632 bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); 633 634 for (i = 0; i < nsym; i++) { 635 GElf_Sym sym; 636 short newscn; 637 638 if (gelf_getsym(ddata, i, &sym) == NULL) 639 printf("Could not get symbol %d\n",i); 640 641 if (sym.st_shndx >= SHN_LORESERVE) 642 continue; 643 644 if ((newscn = secxlate[sym.st_shndx]) != 645 sym.st_shndx) { 646 sym.st_shndx = 647 (newscn == -1 ? 1 : newscn); 648 649 gelf_update_sym(ddata, i, &sym); 650 } 651 } 652 } 653 654 #if !defined(sun) 655 if (ddata->d_buf == NULL && sdata->d_buf != NULL) { 656 ddata->d_buf = xmalloc(shdr.sh_size); 657 bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); 658 } 659 #endif 660 661 if (gelf_update_shdr(dscn, &shdr) == 0) 662 elfterminate(dstname, "Cannot update sect %s", sname); 663 664 new_offset = (off_t)shdr.sh_offset; 665 if (shdr.sh_type != SHT_NOBITS) 666 new_offset += shdr.sh_size; 667 } 668 669 if (symtab_idx == -1) { 670 terminate("%s: Cannot find %s section\n", srcname, 671 dynsym ? "SHT_DYNSYM" : "SHT_SYMTAB"); 672 } 673 674 /* Add the ctf section */ 675 dscn = elf_newscn(dst); 676 gelf_getshdr(dscn, &shdr); 677 shdr.sh_name = ctfnameoff; 678 shdr.sh_type = SHT_PROGBITS; 679 shdr.sh_size = ctfsize; 680 shdr.sh_link = symtab_idx; 681 shdr.sh_addralign = 4; 682 if (changing && sehdr.e_phnum != 0) { 683 pad = new_offset % shdr.sh_addralign; 684 685 if (pad) 686 new_offset += shdr.sh_addralign - pad; 687 688 shdr.sh_offset = new_offset; 689 new_offset += shdr.sh_size; 690 } 691 692 ddata = elf_newdata(dscn); 693 ddata->d_buf = ctfdata; 694 ddata->d_size = ctfsize; 695 ddata->d_align = shdr.sh_addralign; 696 ddata->d_off = 0; 697 698 gelf_update_shdr(dscn, &shdr); 699 700 /* update the section header location */ 701 if (sehdr.e_phnum != 0) { 702 size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT); 703 size_t r = new_offset % align; 704 705 if (r) 706 new_offset += align - r; 707 708 dehdr.e_shoff = new_offset; 709 } 710 711 /* commit to disk */ 712 dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx]; 713 gelf_update_ehdr(dst, &dehdr); 714 if (elf_update(dst, ELF_C_WRITE) < 0) 715 elfterminate(dstname, "Cannot finalize temp file"); 716 717 free(secxlate); 718 } 719 720 static caddr_t 721 make_ctf_data(tdata_t *td, Elf *elf, const char *file, size_t *lenp, int flags) 722 { 723 iiburst_t *iiburst; 724 caddr_t data; 725 726 iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH, 727 flags & CTF_USE_DYNSYM); 728 data = ctf_gen(iiburst, lenp, flags & (CTF_COMPRESS | CTF_SWAP_BYTES)); 729 730 iiburst_free(iiburst); 731 732 return (data); 733 } 734 735 void 736 write_ctf(tdata_t *td, const char *curname, const char *newname, int flags) 737 { 738 struct stat st; 739 Elf *elf = NULL; 740 Elf *telf = NULL; 741 GElf_Ehdr ehdr; 742 caddr_t data; 743 size_t len; 744 int fd = -1; 745 int tfd = -1; 746 int byteorder; 747 748 (void) elf_version(EV_CURRENT); 749 if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0) 750 terminate("%s: Cannot open for re-reading", curname); 751 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) 752 elfterminate(curname, "Cannot re-read"); 753 754 if ((tfd = open(newname, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) 755 terminate("Cannot open temp file %s for writing", newname); 756 if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL) 757 elfterminate(curname, "Cannot write"); 758 759 if (gelf_getehdr(elf, &ehdr)) { 760 #if BYTE_ORDER == BIG_ENDIAN 761 byteorder = ELFDATA2MSB; 762 #else 763 byteorder = ELFDATA2LSB; 764 #endif 765 /* 766 * If target and host has the same byte order 767 * clear byte swapping request 768 */ 769 if (ehdr.e_ident[EI_DATA] == byteorder) 770 flags &= ~CTF_SWAP_BYTES; 771 } 772 else 773 elfterminate(curname, "Failed to get EHDR"); 774 775 data = make_ctf_data(td, elf, curname, &len, flags); 776 write_file(elf, curname, telf, newname, data, len, flags); 777 free(data); 778 779 elf_end(telf); 780 elf_end(elf); 781 (void) close(fd); 782 (void) close(tfd); 783 } 784