1260684Skaiw/*- 2276398Semaste * Copyright (c) 2007-2011,2014 Kai Wang 3260684Skaiw * All rights reserved. 4260684Skaiw * 5260684Skaiw * Redistribution and use in source and binary forms, with or without 6260684Skaiw * modification, are permitted provided that the following conditions 7260684Skaiw * are met: 8260684Skaiw * 1. Redistributions of source code must retain the above copyright 9260684Skaiw * notice, this list of conditions and the following disclaimer. 10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 11260684Skaiw * notice, this list of conditions and the following disclaimer in the 12260684Skaiw * documentation and/or other materials provided with the distribution. 13260684Skaiw * 14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17260684Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24260684Skaiw * SUCH DAMAGE. 25260684Skaiw */ 26260684Skaiw 27260684Skaiw#include <sys/param.h> 28260684Skaiw#include <sys/stat.h> 29260684Skaiw#include <err.h> 30260684Skaiw#include <libgen.h> 31367466Sdim#include <stdbool.h> 32260684Skaiw#include <stdio.h> 33260684Skaiw#include <stdlib.h> 34260684Skaiw#include <string.h> 35260684Skaiw 36260684Skaiw#include "elfcopy.h" 37260684Skaiw 38367466SdimELFTC_VCSID("$Id: sections.c 3758 2019-06-28 01:16:50Z emaste $"); 39260684Skaiw 40260684Skaiwstatic void add_gnu_debuglink(struct elfcopy *ecp); 41260684Skaiwstatic uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); 42260684Skaiwstatic void check_section_rename(struct elfcopy *ecp, struct section *s); 43260684Skaiwstatic void filter_reloc(struct elfcopy *ecp, struct section *s); 44260684Skaiwstatic int get_section_flags(struct elfcopy *ecp, const char *name); 45260684Skaiwstatic void insert_sections(struct elfcopy *ecp); 46260684Skaiwstatic int is_append_section(struct elfcopy *ecp, const char *name); 47260684Skaiwstatic int is_compress_section(struct elfcopy *ecp, const char *name); 48260684Skaiwstatic int is_debug_section(const char *name); 49280932Semastestatic int is_dwo_section(const char *name); 50260684Skaiwstatic int is_modify_section(struct elfcopy *ecp, const char *name); 51260684Skaiwstatic int is_print_section(struct elfcopy *ecp, const char *name); 52260684Skaiwstatic void modify_section(struct elfcopy *ecp, struct section *s); 53260684Skaiwstatic void pad_section(struct elfcopy *ecp, struct section *s); 54260684Skaiwstatic void print_data(const char *d, size_t sz); 55260684Skaiwstatic void print_section(struct section *s); 56260684Skaiwstatic void *read_section(struct section *s, size_t *size); 57367466Sdimstatic void set_shstrtab(struct elfcopy *ecp); 58260684Skaiwstatic void update_reloc(struct elfcopy *ecp, struct section *s); 59283616Semastestatic void update_section_group(struct elfcopy *ecp, struct section *s); 60260684Skaiw 61260684Skaiwint 62260684Skaiwis_remove_section(struct elfcopy *ecp, const char *name) 63260684Skaiw{ 64260684Skaiw 65260684Skaiw /* Always keep section name table */ 66260684Skaiw if (strcmp(name, ".shstrtab") == 0) 67260684Skaiw return 0; 68260684Skaiw if (strcmp(name, ".symtab") == 0 || 69260684Skaiw strcmp(name, ".strtab") == 0) { 70260684Skaiw if (ecp->strip == STRIP_ALL && lookup_symop_list( 71260684Skaiw ecp, NULL, SYMOP_KEEP) == NULL) 72260684Skaiw return (1); 73260684Skaiw else 74260684Skaiw return (0); 75260684Skaiw } 76260684Skaiw 77280932Semaste if (ecp->strip == STRIP_DWO && is_dwo_section(name)) 78280932Semaste return (1); 79280932Semaste if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name)) 80280932Semaste return (1); 81280932Semaste 82260684Skaiw if (is_debug_section(name)) { 83260684Skaiw if (ecp->strip == STRIP_ALL || 84260684Skaiw ecp->strip == STRIP_DEBUG || 85260684Skaiw ecp->strip == STRIP_UNNEEDED || 86260684Skaiw (ecp->flags & DISCARD_LOCAL)) 87260684Skaiw return (1); 88260684Skaiw if (ecp->strip == STRIP_NONDEBUG) 89260684Skaiw return (0); 90260684Skaiw } 91260684Skaiw 92260684Skaiw if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { 93260684Skaiw struct sec_action *sac; 94260684Skaiw 95260684Skaiw sac = lookup_sec_act(ecp, name, 0); 96260684Skaiw if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) 97260684Skaiw return (1); 98260684Skaiw if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) 99260684Skaiw return (1); 100260684Skaiw } 101260684Skaiw 102260684Skaiw return (0); 103260684Skaiw} 104260684Skaiw 105260684Skaiw/* 106260684Skaiw * Relocation section needs to be removed if the section it applies to 107260684Skaiw * will be removed. 108260684Skaiw */ 109260684Skaiwint 110260684Skaiwis_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) 111260684Skaiw{ 112260684Skaiw const char *name; 113260684Skaiw GElf_Shdr ish; 114260684Skaiw Elf_Scn *is; 115260684Skaiw size_t indx; 116260684Skaiw int elferr; 117260684Skaiw 118260684Skaiw if (elf_getshstrndx(ecp->ein, &indx) == 0) 119260684Skaiw errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 120260684Skaiw elf_errmsg(-1)); 121260684Skaiw 122367466Sdim is = elf_getscn(ecp->ein, sh_info); 123367466Sdim if (is != NULL) { 124367466Sdim if (gelf_getshdr(is, &ish) == NULL) 125367466Sdim errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 126367466Sdim elf_errmsg(-1)); 127367466Sdim if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == 128367466Sdim NULL) 129367466Sdim errx(EXIT_FAILURE, "elf_strptr failed: %s", 130367466Sdim elf_errmsg(-1)); 131367466Sdim if (is_remove_section(ecp, name)) 132367466Sdim return (1); 133367466Sdim else 134367466Sdim return (0); 135260684Skaiw } 136260684Skaiw elferr = elf_errno(); 137260684Skaiw if (elferr != 0) 138260684Skaiw errx(EXIT_FAILURE, "elf_nextscn failed: %s", 139260684Skaiw elf_errmsg(elferr)); 140260684Skaiw 141260684Skaiw /* Remove reloc section if we can't find the target section. */ 142260684Skaiw return (1); 143260684Skaiw} 144260684Skaiw 145260684Skaiwstatic int 146260684Skaiwis_append_section(struct elfcopy *ecp, const char *name) 147260684Skaiw{ 148260684Skaiw struct sec_action *sac; 149260684Skaiw 150260684Skaiw sac = lookup_sec_act(ecp, name, 0); 151260684Skaiw if (sac != NULL && sac->append != 0 && sac->string != NULL) 152260684Skaiw return (1); 153260684Skaiw 154260684Skaiw return (0); 155260684Skaiw} 156260684Skaiw 157260684Skaiwstatic int 158260684Skaiwis_compress_section(struct elfcopy *ecp, const char *name) 159260684Skaiw{ 160260684Skaiw struct sec_action *sac; 161260684Skaiw 162260684Skaiw sac = lookup_sec_act(ecp, name, 0); 163260684Skaiw if (sac != NULL && sac->compress != 0) 164260684Skaiw return (1); 165260684Skaiw 166260684Skaiw return (0); 167260684Skaiw} 168260684Skaiw 169260684Skaiwstatic void 170260684Skaiwcheck_section_rename(struct elfcopy *ecp, struct section *s) 171260684Skaiw{ 172260684Skaiw struct sec_action *sac; 173260684Skaiw char *prefix; 174260684Skaiw size_t namelen; 175260684Skaiw 176260684Skaiw if (s->pseudo) 177260684Skaiw return; 178260684Skaiw 179260684Skaiw sac = lookup_sec_act(ecp, s->name, 0); 180260684Skaiw if (sac != NULL && sac->rename) 181260684Skaiw s->name = sac->newname; 182260684Skaiw 183260684Skaiw if (!strcmp(s->name, ".symtab") || 184260684Skaiw !strcmp(s->name, ".strtab") || 185260684Skaiw !strcmp(s->name, ".shstrtab")) 186260684Skaiw return; 187260684Skaiw 188260684Skaiw prefix = NULL; 189260684Skaiw if (s->loadable && ecp->prefix_alloc != NULL) 190260684Skaiw prefix = ecp->prefix_alloc; 191260684Skaiw else if (ecp->prefix_sec != NULL) 192260684Skaiw prefix = ecp->prefix_sec; 193260684Skaiw 194260684Skaiw if (prefix != NULL) { 195260684Skaiw namelen = strlen(s->name) + strlen(prefix) + 1; 196260684Skaiw if ((s->newname = malloc(namelen)) == NULL) 197260684Skaiw err(EXIT_FAILURE, "malloc failed"); 198260684Skaiw snprintf(s->newname, namelen, "%s%s", prefix, s->name); 199260684Skaiw s->name = s->newname; 200260684Skaiw } 201260684Skaiw} 202260684Skaiw 203260684Skaiwstatic int 204260684Skaiwget_section_flags(struct elfcopy *ecp, const char *name) 205260684Skaiw{ 206260684Skaiw struct sec_action *sac; 207260684Skaiw 208260684Skaiw sac = lookup_sec_act(ecp, name, 0); 209260684Skaiw if (sac != NULL && sac->flags) 210260684Skaiw return sac->flags; 211260684Skaiw 212260684Skaiw return (0); 213260684Skaiw} 214260684Skaiw 215260684Skaiw/* 216260684Skaiw * Determine whether the section are debugging section. 217260684Skaiw * According to libbfd, debugging sections are recognized 218260684Skaiw * only by name. 219260684Skaiw */ 220260684Skaiwstatic int 221260684Skaiwis_debug_section(const char *name) 222260684Skaiw{ 223260684Skaiw const char *dbg_sec[] = { 224295577Semaste ".apple_", 225260684Skaiw ".debug", 226260684Skaiw ".gnu.linkonce.wi.", 227260684Skaiw ".line", 228260684Skaiw ".stab", 229260684Skaiw NULL 230260684Skaiw }; 231260684Skaiw const char **p; 232260684Skaiw 233260684Skaiw for(p = dbg_sec; *p; p++) { 234260684Skaiw if (strncmp(name, *p, strlen(*p)) == 0) 235260684Skaiw return (1); 236260684Skaiw } 237260684Skaiw 238260684Skaiw return (0); 239260684Skaiw} 240260684Skaiw 241260684Skaiwstatic int 242280932Semasteis_dwo_section(const char *name) 243280932Semaste{ 244280932Semaste size_t len; 245280932Semaste 246280932Semaste if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0) 247280932Semaste return (1); 248280932Semaste return (0); 249280932Semaste} 250280932Semaste 251280932Semastestatic int 252260684Skaiwis_print_section(struct elfcopy *ecp, const char *name) 253260684Skaiw{ 254260684Skaiw struct sec_action *sac; 255260684Skaiw 256260684Skaiw sac = lookup_sec_act(ecp, name, 0); 257260684Skaiw if (sac != NULL && sac->print != 0) 258260684Skaiw return (1); 259260684Skaiw 260260684Skaiw return (0); 261260684Skaiw} 262260684Skaiw 263260684Skaiwstatic int 264260684Skaiwis_modify_section(struct elfcopy *ecp, const char *name) 265260684Skaiw{ 266260684Skaiw 267260684Skaiw if (is_append_section(ecp, name) || 268260684Skaiw is_compress_section(ecp, name)) 269260684Skaiw return (1); 270260684Skaiw 271260684Skaiw return (0); 272260684Skaiw} 273260684Skaiw 274260684Skaiwstruct sec_action* 275260684Skaiwlookup_sec_act(struct elfcopy *ecp, const char *name, int add) 276260684Skaiw{ 277260684Skaiw struct sec_action *sac; 278260684Skaiw 279260684Skaiw if (name == NULL) 280260684Skaiw return NULL; 281260684Skaiw 282260684Skaiw STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 283260684Skaiw if (strcmp(name, sac->name) == 0) 284260684Skaiw return sac; 285260684Skaiw } 286260684Skaiw 287260684Skaiw if (add == 0) 288260684Skaiw return NULL; 289260684Skaiw 290260684Skaiw if ((sac = malloc(sizeof(*sac))) == NULL) 291260684Skaiw errx(EXIT_FAILURE, "not enough memory"); 292260684Skaiw memset(sac, 0, sizeof(*sac)); 293260684Skaiw sac->name = name; 294260684Skaiw STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); 295260684Skaiw 296260684Skaiw return (sac); 297260684Skaiw} 298260684Skaiw 299260684Skaiwvoid 300260684Skaiwfree_sec_act(struct elfcopy *ecp) 301260684Skaiw{ 302260684Skaiw struct sec_action *sac, *sac_temp; 303260684Skaiw 304260684Skaiw STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { 305260684Skaiw STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); 306260684Skaiw free(sac); 307260684Skaiw } 308260684Skaiw} 309260684Skaiw 310260684Skaiwvoid 311260684Skaiwinsert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) 312260684Skaiw{ 313260684Skaiw struct section *s; 314260684Skaiw 315367466Sdim if (tail || TAILQ_EMPTY(&ecp->v_sec) || 316367466Sdim TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) { 317367466Sdim TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); 318367466Sdim } else { 319260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 320260684Skaiw if (sec->off < s->off) { 321260684Skaiw TAILQ_INSERT_BEFORE(s, sec, sec_list); 322367466Sdim break; 323260684Skaiw } 324260684Skaiw } 325260684Skaiw } 326260684Skaiw 327260684Skaiw if (sec->pseudo == 0) 328260684Skaiw ecp->nos++; 329260684Skaiw} 330260684Skaiw 331260684Skaiw/* 332260684Skaiw * First step of section creation: create scn and internal section 333260684Skaiw * structure, discard sections to be removed. 334260684Skaiw */ 335260684Skaiwvoid 336260684Skaiwcreate_scn(struct elfcopy *ecp) 337260684Skaiw{ 338260684Skaiw struct section *s; 339260684Skaiw const char *name; 340260684Skaiw Elf_Scn *is; 341260684Skaiw GElf_Shdr ish; 342260684Skaiw size_t indx; 343260684Skaiw uint64_t oldndx, newndx; 344298085Semaste int elferr, sec_flags, reorder; 345367466Sdim bool sections_added; 346260684Skaiw 347260684Skaiw /* 348260684Skaiw * Insert a pseudo section that contains the ELF header 349260684Skaiw * and program header. Used as reference for section offset 350260684Skaiw * or load address adjustment. 351260684Skaiw */ 352260684Skaiw if ((s = calloc(1, sizeof(*s))) == NULL) 353260684Skaiw err(EXIT_FAILURE, "calloc failed"); 354260684Skaiw s->off = 0; 355260684Skaiw s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + 356260684Skaiw gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); 357260684Skaiw s->align = 1; 358260684Skaiw s->pseudo = 1; 359260684Skaiw s->loadable = add_to_inseg_list(ecp, s); 360260684Skaiw insert_to_sec_list(ecp, s, 0); 361260684Skaiw 362260684Skaiw /* Create internal .shstrtab section. */ 363260684Skaiw init_shstrtab(ecp); 364260684Skaiw 365260684Skaiw if (elf_getshstrndx(ecp->ein, &indx) == 0) 366260684Skaiw errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 367260684Skaiw elf_errmsg(-1)); 368260684Skaiw 369367466Sdim sections_added = false; 370298085Semaste reorder = 0; 371260684Skaiw is = NULL; 372260684Skaiw while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 373260684Skaiw if (gelf_getshdr(is, &ish) == NULL) 374295577Semaste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 375260684Skaiw elf_errmsg(-1)); 376260684Skaiw if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) 377260684Skaiw errx(EXIT_FAILURE, "elf_strptr failed: %s", 378260684Skaiw elf_errmsg(-1)); 379260684Skaiw 380260684Skaiw /* Skip sections to be removed. */ 381260684Skaiw if (is_remove_section(ecp, name)) 382260684Skaiw continue; 383260684Skaiw 384260684Skaiw /* 385260684Skaiw * Relocation section need to be remove if the section 386260684Skaiw * it applies will be removed. 387260684Skaiw */ 388260684Skaiw if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 389260684Skaiw if (ish.sh_info != 0 && 390260684Skaiw is_remove_reloc_sec(ecp, ish.sh_info)) 391260684Skaiw continue; 392260684Skaiw 393276371Semaste /* 394276371Semaste * Section groups should be removed if symbol table will 395276371Semaste * be removed. (section group's signature stored in symbol 396276371Semaste * table) 397276371Semaste */ 398276371Semaste if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL) 399276371Semaste continue; 400276371Semaste 401260684Skaiw /* Get section flags set by user. */ 402260684Skaiw sec_flags = get_section_flags(ecp, name); 403260684Skaiw 404260684Skaiw /* Create internal section object. */ 405260684Skaiw if (strcmp(name, ".shstrtab") != 0) { 406260684Skaiw if ((s = calloc(1, sizeof(*s))) == NULL) 407260684Skaiw err(EXIT_FAILURE, "calloc failed"); 408260684Skaiw s->name = name; 409260684Skaiw s->is = is; 410260684Skaiw s->off = ish.sh_offset; 411260684Skaiw s->sz = ish.sh_size; 412260684Skaiw s->align = ish.sh_addralign; 413260684Skaiw s->type = ish.sh_type; 414333770Smarius s->flags = ish.sh_flags; 415260684Skaiw s->vma = ish.sh_addr; 416260684Skaiw 417260684Skaiw /* 418260684Skaiw * Search program headers to determine whether section 419260684Skaiw * is loadable, but if user explicitly set section flags 420260684Skaiw * while neither "load" nor "alloc" is set, we make the 421260684Skaiw * section unloadable. 422295577Semaste * 423295577Semaste * Sections in relocatable object is loadable if 424295577Semaste * section flag SHF_ALLOC is set. 425260684Skaiw */ 426260684Skaiw if (sec_flags && 427260684Skaiw (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 428260684Skaiw s->loadable = 0; 429295577Semaste else { 430260684Skaiw s->loadable = add_to_inseg_list(ecp, s); 431295577Semaste if ((ecp->flags & RELOCATABLE) && 432295577Semaste (ish.sh_flags & SHF_ALLOC)) 433295577Semaste s->loadable = 1; 434295577Semaste } 435260684Skaiw } else { 436260684Skaiw /* Assuming .shstrtab is "unloadable". */ 437260684Skaiw s = ecp->shstrtab; 438260684Skaiw s->off = ish.sh_offset; 439260684Skaiw } 440260684Skaiw 441260684Skaiw oldndx = newndx = SHN_UNDEF; 442260684Skaiw if (strcmp(name, ".symtab") != 0 && 443260684Skaiw strcmp(name, ".strtab") != 0) { 444367466Sdim /* Add new sections before .shstrtab if we have one. */ 445260684Skaiw if (!strcmp(name, ".shstrtab")) { 446260684Skaiw /* 447260684Skaiw * Add sections specified by --add-section and 448260684Skaiw * gnu debuglink. we want these sections have 449260684Skaiw * smaller index than .shstrtab section. 450260684Skaiw */ 451367466Sdim sections_added = true; 452260684Skaiw if (ecp->debuglink != NULL) 453260684Skaiw add_gnu_debuglink(ecp); 454260684Skaiw if (ecp->flags & SEC_ADD) 455260684Skaiw insert_sections(ecp); 456260684Skaiw } 457260684Skaiw if ((s->os = elf_newscn(ecp->eout)) == NULL) 458260684Skaiw errx(EXIT_FAILURE, "elf_newscn failed: %s", 459260684Skaiw elf_errmsg(-1)); 460260684Skaiw if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 461260684Skaiw errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 462260684Skaiw elf_errmsg(-1)); 463260684Skaiw } 464260684Skaiw if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 465260684Skaiw errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 466260684Skaiw elf_errmsg(-1)); 467260684Skaiw if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 468260684Skaiw ecp->secndx[oldndx] = newndx; 469260684Skaiw 470260684Skaiw /* 471260684Skaiw * If strip action is STRIP_NONDEBUG(only keep debug), 472292120Semaste * change sections type of loadable sections and section 473292120Semaste * groups to SHT_NOBITS, and the content of those sections 474292120Semaste * will be discarded. However, SHT_NOTE sections should 475292120Semaste * be kept. 476260684Skaiw */ 477292120Semaste if (ecp->strip == STRIP_NONDEBUG) { 478292120Semaste if (((ish.sh_flags & SHF_ALLOC) || 479292120Semaste (ish.sh_flags & SHF_GROUP)) && 480292120Semaste ish.sh_type != SHT_NOTE) 481292120Semaste s->type = SHT_NOBITS; 482292120Semaste } 483260684Skaiw 484260684Skaiw check_section_rename(ecp, s); 485260684Skaiw 486260684Skaiw /* create section header based on input object. */ 487260684Skaiw if (strcmp(name, ".symtab") != 0 && 488260684Skaiw strcmp(name, ".strtab") != 0 && 489298085Semaste strcmp(name, ".shstrtab") != 0) { 490260684Skaiw copy_shdr(ecp, s, NULL, 0, sec_flags); 491298085Semaste /* 492298085Semaste * elfcopy puts .symtab, .strtab and .shstrtab 493298085Semaste * sections in the end of the output object. 494298085Semaste * If the input objects have more sections 495298085Semaste * after any of these 3 sections, the section 496298085Semaste * table will be reordered. section symbols 497298085Semaste * should be regenerated for relocations. 498298085Semaste */ 499298085Semaste if (reorder) 500298085Semaste ecp->flags &= ~SYMTAB_INTACT; 501298085Semaste } else 502298085Semaste reorder = 1; 503260684Skaiw 504260684Skaiw if (strcmp(name, ".symtab") == 0) { 505260684Skaiw ecp->flags |= SYMTAB_EXIST; 506260684Skaiw ecp->symtab = s; 507260684Skaiw } 508260684Skaiw if (strcmp(name, ".strtab") == 0) 509260684Skaiw ecp->strtab = s; 510260684Skaiw 511260684Skaiw insert_to_sec_list(ecp, s, 0); 512260684Skaiw } 513367466Sdim if (!sections_added) { 514367466Sdim if (ecp->debuglink != NULL) 515367466Sdim add_gnu_debuglink(ecp); 516367466Sdim if (ecp->flags & SEC_ADD) 517367466Sdim insert_sections(ecp); 518367466Sdim } 519260684Skaiw elferr = elf_errno(); 520260684Skaiw if (elferr != 0) 521260684Skaiw errx(EXIT_FAILURE, "elf_nextscn failed: %s", 522260684Skaiw elf_errmsg(elferr)); 523260684Skaiw} 524260684Skaiw 525260684Skaiwstruct section * 526260684Skaiwinsert_shtab(struct elfcopy *ecp, int tail) 527260684Skaiw{ 528260684Skaiw struct section *s, *shtab; 529260684Skaiw GElf_Ehdr ieh; 530260684Skaiw int nsecs; 531260684Skaiw 532260684Skaiw /* 533260684Skaiw * Treat section header table as a "pseudo" section, insert it 534260684Skaiw * into section list, so later it will get sorted and resynced 535260684Skaiw * just as normal sections. 536260684Skaiw */ 537260684Skaiw if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 538260684Skaiw errx(EXIT_FAILURE, "calloc failed"); 539260684Skaiw if (!tail) { 540276398Semaste /* 541276398Semaste * "shoff" of input object is used as a hint for section 542276398Semaste * resync later. 543276398Semaste */ 544260684Skaiw if (gelf_getehdr(ecp->ein, &ieh) == NULL) 545260684Skaiw errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 546260684Skaiw elf_errmsg(-1)); 547260684Skaiw shtab->off = ieh.e_shoff; 548260684Skaiw } else 549260684Skaiw shtab->off = 0; 550260684Skaiw /* Calculate number of sections in the output object. */ 551260684Skaiw nsecs = 0; 552260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 553260684Skaiw if (!s->pseudo) 554260684Skaiw nsecs++; 555260684Skaiw } 556260684Skaiw /* Remember there is always a null section, so we +1 here. */ 557260684Skaiw shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 558260684Skaiw if (shtab->sz == 0) 559260684Skaiw errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 560260684Skaiw shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 561260684Skaiw shtab->loadable = 0; 562260684Skaiw shtab->pseudo = 1; 563260684Skaiw insert_to_sec_list(ecp, shtab, tail); 564260684Skaiw 565260684Skaiw return (shtab); 566260684Skaiw} 567260684Skaiw 568260684Skaiwvoid 569260684Skaiwcopy_content(struct elfcopy *ecp) 570260684Skaiw{ 571260684Skaiw struct section *s; 572260684Skaiw 573260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 574260684Skaiw /* Skip pseudo section. */ 575260684Skaiw if (s->pseudo) 576260684Skaiw continue; 577260684Skaiw 578260684Skaiw /* Skip special sections. */ 579260684Skaiw if (strcmp(s->name, ".symtab") == 0 || 580260684Skaiw strcmp(s->name, ".strtab") == 0 || 581260684Skaiw strcmp(s->name, ".shstrtab") == 0) 582260684Skaiw continue; 583260684Skaiw 584260684Skaiw /* 585260684Skaiw * If strip action is STRIP_ALL, relocation info need 586260684Skaiw * to be stripped. Skip filtering otherwisw. 587260684Skaiw */ 588260684Skaiw if (ecp->strip == STRIP_ALL && 589260684Skaiw (s->type == SHT_REL || s->type == SHT_RELA)) 590260684Skaiw filter_reloc(ecp, s); 591260684Skaiw 592283616Semaste /* 593283616Semaste * The section indices in the SHT_GROUP section needs 594283616Semaste * to be updated since we might have stripped some 595283616Semaste * sections and changed section numbering. 596283616Semaste */ 597283616Semaste if (s->type == SHT_GROUP) 598283616Semaste update_section_group(ecp, s); 599283616Semaste 600260684Skaiw if (is_modify_section(ecp, s->name)) 601260684Skaiw modify_section(ecp, s); 602260684Skaiw 603260684Skaiw copy_data(s); 604260684Skaiw 605260684Skaiw /* 606260684Skaiw * If symbol table is modified, relocation info might 607260684Skaiw * need update, as symbol index may have changed. 608260684Skaiw */ 609260684Skaiw if ((ecp->flags & SYMTAB_INTACT) == 0 && 610260684Skaiw (ecp->flags & SYMTAB_EXIST) && 611260684Skaiw (s->type == SHT_REL || s->type == SHT_RELA)) 612260684Skaiw update_reloc(ecp, s); 613260684Skaiw 614260684Skaiw if (is_print_section(ecp, s->name)) 615260684Skaiw print_section(s); 616260684Skaiw } 617260684Skaiw} 618260684Skaiw 619283616Semaste 620260684Skaiw/* 621283616Semaste * Update section group section. The section indices in the SHT_GROUP 622283616Semaste * section need update after section numbering changed. 623283616Semaste */ 624283616Semastestatic void 625283616Semasteupdate_section_group(struct elfcopy *ecp, struct section *s) 626283616Semaste{ 627283616Semaste GElf_Shdr ish; 628283616Semaste Elf_Data *id; 629283616Semaste uint32_t *ws, *wd; 630283616Semaste uint64_t n; 631283616Semaste size_t ishnum; 632283616Semaste int i, j; 633283616Semaste 634283616Semaste if (!elf_getshnum(ecp->ein, &ishnum)) 635283616Semaste errx(EXIT_FAILURE, "elf_getshnum failed: %s", 636283616Semaste elf_errmsg(-1)); 637283616Semaste 638283616Semaste if (gelf_getshdr(s->is, &ish) == NULL) 639283616Semaste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 640283616Semaste elf_errmsg(-1)); 641283616Semaste 642283616Semaste if ((id = elf_getdata(s->is, NULL)) == NULL) 643283616Semaste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 644283616Semaste elf_errmsg(-1)); 645283616Semaste 646283616Semaste if (ish.sh_size == 0) 647283616Semaste return; 648283616Semaste 649283616Semaste if (ish.sh_entsize == 0) 650283616Semaste ish.sh_entsize = 4; 651283616Semaste 652283616Semaste ws = id->d_buf; 653283616Semaste 654283616Semaste /* We only support COMDAT section. */ 655283616Semaste#ifndef GRP_COMDAT 656283616Semaste#define GRP_COMDAT 0x1 657283616Semaste#endif 658283616Semaste if ((*ws & GRP_COMDAT) == 0) 659283616Semaste return; 660283616Semaste 661283616Semaste if ((s->buf = malloc(ish.sh_size)) == NULL) 662283616Semaste err(EXIT_FAILURE, "malloc failed"); 663283616Semaste 664283616Semaste s->sz = ish.sh_size; 665283616Semaste 666283616Semaste wd = s->buf; 667283616Semaste 668283616Semaste /* Copy the flag word as-is. */ 669283616Semaste *wd = *ws; 670283616Semaste 671283616Semaste /* Update the section indices. */ 672283616Semaste n = ish.sh_size / ish.sh_entsize; 673283616Semaste for(i = 1, j = 1; (uint64_t)i < n; i++) { 674283616Semaste if (ws[i] != SHN_UNDEF && ws[i] < ishnum && 675283616Semaste ecp->secndx[ws[i]] != 0) 676283616Semaste wd[j++] = ecp->secndx[ws[i]]; 677283616Semaste else 678283616Semaste s->sz -= 4; 679283616Semaste } 680283616Semaste 681283616Semaste s->nocopy = 1; 682283616Semaste} 683283616Semaste 684283616Semaste/* 685260684Skaiw * Filter relocation entries, only keep those entries whose 686260684Skaiw * symbol is in the keep list. 687260684Skaiw */ 688260684Skaiwstatic void 689260684Skaiwfilter_reloc(struct elfcopy *ecp, struct section *s) 690260684Skaiw{ 691260684Skaiw const char *name; 692260684Skaiw GElf_Shdr ish; 693260684Skaiw GElf_Rel rel; 694260684Skaiw GElf_Rela rela; 695260684Skaiw Elf32_Rel *rel32; 696260684Skaiw Elf64_Rel *rel64; 697260684Skaiw Elf32_Rela *rela32; 698260684Skaiw Elf64_Rela *rela64; 699260684Skaiw Elf_Data *id; 700339710Semaste uint64_t cap, n, nrels, sym; 701260684Skaiw int elferr, i; 702260684Skaiw 703260684Skaiw if (gelf_getshdr(s->is, &ish) == NULL) 704260684Skaiw errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 705260684Skaiw elf_errmsg(-1)); 706260684Skaiw 707260684Skaiw /* We don't want to touch relocation info for dynamic symbols. */ 708260684Skaiw if ((ecp->flags & SYMTAB_EXIST) == 0) { 709339710Semaste /* 710339710Semaste * No symbol table in output. If sh_link points to a section 711339710Semaste * that exists in the output object, this relocation section 712339710Semaste * is for dynamic symbols. Don't touch it. 713339710Semaste */ 714339710Semaste if (ish.sh_link != 0 && ecp->secndx[ish.sh_link] != 0) 715339710Semaste return; 716260684Skaiw } else { 717260684Skaiw /* Symbol table exist, check if index equals. */ 718260684Skaiw if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 719260684Skaiw return; 720260684Skaiw } 721260684Skaiw 722260684Skaiw#define COPYREL(REL, SZ) do { \ 723260684Skaiw if (nrels == 0) { \ 724260684Skaiw if ((REL##SZ = malloc(cap * \ 725336521Smarkj sizeof(*REL##SZ))) == NULL) \ 726260684Skaiw err(EXIT_FAILURE, "malloc failed"); \ 727260684Skaiw } \ 728260684Skaiw if (nrels >= cap) { \ 729260684Skaiw cap *= 2; \ 730260684Skaiw if ((REL##SZ = realloc(REL##SZ, cap * \ 731336521Smarkj sizeof(*REL##SZ))) == NULL) \ 732260684Skaiw err(EXIT_FAILURE, "realloc failed"); \ 733260684Skaiw } \ 734260684Skaiw REL##SZ[nrels].r_offset = REL.r_offset; \ 735260684Skaiw REL##SZ[nrels].r_info = REL.r_info; \ 736260684Skaiw if (s->type == SHT_RELA) \ 737260684Skaiw rela##SZ[nrels].r_addend = rela.r_addend; \ 738260684Skaiw nrels++; \ 739260684Skaiw} while (0) 740260684Skaiw 741260684Skaiw nrels = 0; 742260684Skaiw cap = 4; /* keep list is usually small. */ 743260684Skaiw rel32 = NULL; 744260684Skaiw rel64 = NULL; 745260684Skaiw rela32 = NULL; 746260684Skaiw rela64 = NULL; 747260684Skaiw if ((id = elf_getdata(s->is, NULL)) == NULL) 748260684Skaiw errx(EXIT_FAILURE, "elf_getdata() failed: %s", 749260684Skaiw elf_errmsg(-1)); 750260684Skaiw n = ish.sh_size / ish.sh_entsize; 751260684Skaiw for(i = 0; (uint64_t)i < n; i++) { 752260684Skaiw if (s->type == SHT_REL) { 753260684Skaiw if (gelf_getrel(id, i, &rel) != &rel) 754260684Skaiw errx(EXIT_FAILURE, "gelf_getrel failed: %s", 755260684Skaiw elf_errmsg(-1)); 756339710Semaste sym = GELF_R_SYM(rel.r_info); 757260684Skaiw } else { 758260684Skaiw if (gelf_getrela(id, i, &rela) != &rela) 759260684Skaiw errx(EXIT_FAILURE, "gelf_getrel failed: %s", 760260684Skaiw elf_errmsg(-1)); 761339710Semaste sym = GELF_R_SYM(rela.r_info); 762260684Skaiw } 763339710Semaste /* 764339710Semaste * If a relocation references a symbol and we are omitting 765339710Semaste * either that symbol or the entire symbol table we cannot 766339710Semaste * produce valid output, and so just omit the relocation. 767339710Semaste * Broken output like this is generally not useful, but some 768339710Semaste * uses of elfcopy/strip rely on it - for example, GCC's build 769339710Semaste * process uses it to check for build reproducibility by 770339710Semaste * stripping objects and comparing them. 771339710Semaste * 772339710Semaste * Relocations that do not reference a symbol are retained. 773339710Semaste */ 774339710Semaste if (sym != 0) { 775339710Semaste if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) 776339710Semaste continue; 777339710Semaste name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 778339710Semaste sym); 779339710Semaste if (name == NULL) 780339710Semaste errx(EXIT_FAILURE, "elf_strptr failed: %s", 781339710Semaste elf_errmsg(-1)); 782339710Semaste if (lookup_symop_list(ecp, name, SYMOP_KEEP) == NULL) 783339710Semaste continue; 784260684Skaiw } 785339710Semaste if (ecp->oec == ELFCLASS32) { 786339710Semaste if (s->type == SHT_REL) 787339710Semaste COPYREL(rel, 32); 788339710Semaste else 789339710Semaste COPYREL(rela, 32); 790339710Semaste } else { 791339710Semaste if (s->type == SHT_REL) 792339710Semaste COPYREL(rel, 64); 793339710Semaste else 794339710Semaste COPYREL(rela, 64); 795339710Semaste } 796260684Skaiw } 797260684Skaiw elferr = elf_errno(); 798260684Skaiw if (elferr != 0) 799260684Skaiw errx(EXIT_FAILURE, "elf_getdata() failed: %s", 800260684Skaiw elf_errmsg(elferr)); 801260684Skaiw 802260684Skaiw if (ecp->oec == ELFCLASS32) { 803260684Skaiw if (s->type == SHT_REL) 804260684Skaiw s->buf = rel32; 805260684Skaiw else 806260684Skaiw s->buf = rela32; 807260684Skaiw } else { 808260684Skaiw if (s->type == SHT_REL) 809260684Skaiw s->buf = rel64; 810260684Skaiw else 811260684Skaiw s->buf = rela64; 812260684Skaiw } 813260684Skaiw s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 814260684Skaiw ELF_T_RELA), nrels, EV_CURRENT); 815260684Skaiw s->nocopy = 1; 816260684Skaiw} 817260684Skaiw 818260684Skaiwstatic void 819260684Skaiwupdate_reloc(struct elfcopy *ecp, struct section *s) 820260684Skaiw{ 821260684Skaiw GElf_Shdr osh; 822260684Skaiw GElf_Rel rel; 823260684Skaiw GElf_Rela rela; 824260684Skaiw Elf_Data *od; 825260684Skaiw uint64_t n; 826260684Skaiw int i; 827260684Skaiw 828260684Skaiw#define UPDATEREL(REL) do { \ 829260684Skaiw if (gelf_get##REL(od, i, &REL) != &REL) \ 830260684Skaiw errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 831260684Skaiw elf_errmsg(-1)); \ 832260684Skaiw REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 833260684Skaiw GELF_R_TYPE(REL.r_info)); \ 834260684Skaiw if (!gelf_update_##REL(od, i, &REL)) \ 835260684Skaiw errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 836260684Skaiw elf_errmsg(-1)); \ 837260684Skaiw} while(0) 838260684Skaiw 839260684Skaiw if (s->sz == 0) 840260684Skaiw return; 841260684Skaiw if (gelf_getshdr(s->os, &osh) == NULL) 842260684Skaiw errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 843260684Skaiw elf_errmsg(-1)); 844260684Skaiw /* Only process .symtab reloc info. */ 845260684Skaiw if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 846260684Skaiw return; 847260684Skaiw if ((od = elf_getdata(s->os, NULL)) == NULL) 848260684Skaiw errx(EXIT_FAILURE, "elf_getdata() failed: %s", 849260684Skaiw elf_errmsg(-1)); 850260684Skaiw n = osh.sh_size / osh.sh_entsize; 851260684Skaiw for(i = 0; (uint64_t)i < n; i++) { 852260684Skaiw if (s->type == SHT_REL) 853260684Skaiw UPDATEREL(rel); 854260684Skaiw else 855260684Skaiw UPDATEREL(rela); 856260684Skaiw } 857260684Skaiw} 858260684Skaiw 859260684Skaiwstatic void 860260684Skaiwpad_section(struct elfcopy *ecp, struct section *s) 861260684Skaiw{ 862260684Skaiw GElf_Shdr osh; 863260684Skaiw Elf_Data *od; 864260684Skaiw 865260684Skaiw if (s == NULL || s->pad_sz == 0) 866260684Skaiw return; 867260684Skaiw 868260684Skaiw if ((s->pad = malloc(s->pad_sz)) == NULL) 869260684Skaiw err(EXIT_FAILURE, "malloc failed"); 870260684Skaiw memset(s->pad, ecp->fill, s->pad_sz); 871260684Skaiw 872260684Skaiw /* Create a new Elf_Data to contain the padding bytes. */ 873260684Skaiw if ((od = elf_newdata(s->os)) == NULL) 874260684Skaiw errx(EXIT_FAILURE, "elf_newdata() failed: %s", 875260684Skaiw elf_errmsg(-1)); 876260684Skaiw od->d_align = 1; 877260684Skaiw od->d_off = s->sz; 878260684Skaiw od->d_buf = s->pad; 879260684Skaiw od->d_type = ELF_T_BYTE; 880260684Skaiw od->d_size = s->pad_sz; 881260684Skaiw od->d_version = EV_CURRENT; 882260684Skaiw 883260684Skaiw /* Update section header. */ 884260684Skaiw if (gelf_getshdr(s->os, &osh) == NULL) 885260684Skaiw errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 886260684Skaiw elf_errmsg(-1)); 887260684Skaiw osh.sh_size = s->sz + s->pad_sz; 888260684Skaiw if (!gelf_update_shdr(s->os, &osh)) 889260684Skaiw errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 890260684Skaiw elf_errmsg(-1)); 891260684Skaiw} 892260684Skaiw 893367466Sdimstatic int 894367466Sdimsection_type_alignment(int sht, int class) 895367466Sdim{ 896367466Sdim switch (sht) 897367466Sdim { 898367466Sdim case SHT_DYNAMIC: 899367466Sdim case SHT_DYNSYM: 900367466Sdim case SHT_FINI_ARRAY: 901367466Sdim case SHT_GNU_HASH: 902367466Sdim case SHT_INIT_ARRAY: 903367466Sdim case SHT_PREINIT_ARRAY: 904367466Sdim case SHT_REL: 905367466Sdim case SHT_RELA: 906367466Sdim case SHT_SYMTAB: 907367466Sdim return (class == ELFCLASS64 ? 8 : 4); 908367466Sdim case SHT_SUNW_move: 909367466Sdim return (8); 910367466Sdim case SHT_GNU_LIBLIST: 911367466Sdim case SHT_GROUP: 912367466Sdim case SHT_HASH: 913367466Sdim case SHT_NOTE: 914367466Sdim case SHT_SUNW_verdef: /* == SHT_GNU_verdef */ 915367466Sdim case SHT_SUNW_verneed: /* == SHT_GNU_verneed */ 916367466Sdim case SHT_SYMTAB_SHNDX: 917367466Sdim return (4); 918367466Sdim case SHT_SUNW_syminfo: 919367466Sdim case SHT_SUNW_versym: /* == SHT_GNU_versym */ 920367466Sdim return (2); 921367466Sdim case SHT_NOBITS: 922367466Sdim case SHT_PROGBITS: 923367466Sdim case SHT_STRTAB: 924367466Sdim case SHT_SUNW_dof: 925367466Sdim return (1); 926367466Sdim } 927367466Sdim return (1); 928367466Sdim} 929367466Sdim 930260684Skaiwvoid 931260684Skaiwresync_sections(struct elfcopy *ecp) 932260684Skaiw{ 933260684Skaiw struct section *s, *ps; 934260684Skaiw GElf_Shdr osh; 935260684Skaiw uint64_t off; 936260684Skaiw int first; 937367466Sdim int min_alignment; 938260684Skaiw 939260684Skaiw ps = NULL; 940260684Skaiw first = 1; 941260684Skaiw off = 0; 942260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 943260684Skaiw if (first) { 944260684Skaiw off = s->off; 945260684Skaiw first = 0; 946260684Skaiw } 947260684Skaiw 948276398Semaste /* 949276398Semaste * Ignore TLS sections with load address 0 and without 950276398Semaste * content. We don't need to adjust their file offset or 951276398Semaste * VMA, only the size matters. 952276398Semaste */ 953276398Semaste if (s->seg_tls != NULL && s->type == SHT_NOBITS && 954276398Semaste s->off == 0) 955276398Semaste continue; 956276398Semaste 957260684Skaiw /* Align section offset. */ 958277181Semaste if (s->align == 0) 959277181Semaste s->align = 1; 960367466Sdim min_alignment = section_type_alignment(s->type, ecp->oec); 961367466Sdim if (s->align < INT_MAX && (int)s->align < min_alignment) { 962367466Sdim warnx("section %s alignment %d increased to %d", 963367466Sdim s->name, (int)s->align, min_alignment); 964367466Sdim s->align = min_alignment; 965367466Sdim } 966260684Skaiw if (off <= s->off) { 967295577Semaste if (!s->loadable || (ecp->flags & RELOCATABLE)) 968260684Skaiw s->off = roundup(off, s->align); 969260684Skaiw } else { 970295577Semaste if (s->loadable && (ecp->flags & RELOCATABLE) == 0) 971275916Semaste warnx("moving loadable section %s, " 972275916Semaste "is this intentional?", s->name); 973260684Skaiw s->off = roundup(off, s->align); 974260684Skaiw } 975260684Skaiw 976260684Skaiw /* Calculate next section offset. */ 977260684Skaiw off = s->off; 978260684Skaiw if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 979260684Skaiw off += s->sz; 980260684Skaiw 981260684Skaiw if (s->pseudo) { 982260684Skaiw ps = NULL; 983260684Skaiw continue; 984260684Skaiw } 985260684Skaiw 986260684Skaiw /* Count padding bytes added through --pad-to. */ 987260684Skaiw if (s->pad_sz > 0) 988260684Skaiw off += s->pad_sz; 989260684Skaiw 990260684Skaiw /* Update section header accordingly. */ 991260684Skaiw if (gelf_getshdr(s->os, &osh) == NULL) 992260684Skaiw errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 993260684Skaiw elf_errmsg(-1)); 994260684Skaiw osh.sh_addr = s->vma; 995367466Sdim osh.sh_addralign = s->align; 996260684Skaiw osh.sh_offset = s->off; 997260684Skaiw osh.sh_size = s->sz; 998260684Skaiw if (!gelf_update_shdr(s->os, &osh)) 999260684Skaiw errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1000260684Skaiw elf_errmsg(-1)); 1001260684Skaiw 1002260684Skaiw /* Add padding for previous section, if need. */ 1003260684Skaiw if (ps != NULL) { 1004260684Skaiw if (ps->pad_sz > 0) { 1005260684Skaiw /* Apply padding added by --pad-to. */ 1006260684Skaiw pad_section(ecp, ps); 1007260684Skaiw } else if ((ecp->flags & GAP_FILL) && 1008260684Skaiw (ps->off + ps->sz < s->off)) { 1009260684Skaiw /* 1010260684Skaiw * Fill the gap between sections by padding 1011260684Skaiw * the section with lower address. 1012260684Skaiw */ 1013260684Skaiw ps->pad_sz = s->off - (ps->off + ps->sz); 1014260684Skaiw pad_section(ecp, ps); 1015260684Skaiw } 1016260684Skaiw } 1017260684Skaiw 1018260684Skaiw ps = s; 1019260684Skaiw } 1020260684Skaiw 1021260684Skaiw /* Pad the last section, if need. */ 1022260684Skaiw if (ps != NULL && ps->pad_sz > 0) 1023260684Skaiw pad_section(ecp, ps); 1024260684Skaiw} 1025260684Skaiw 1026260684Skaiwstatic void 1027260684Skaiwmodify_section(struct elfcopy *ecp, struct section *s) 1028260684Skaiw{ 1029260684Skaiw struct sec_action *sac; 1030260684Skaiw size_t srcsz, dstsz, p, len; 1031260684Skaiw char *b, *c, *d, *src, *end; 1032260684Skaiw int dupe; 1033260684Skaiw 1034260684Skaiw src = read_section(s, &srcsz); 1035260684Skaiw if (src == NULL || srcsz == 0) { 1036260684Skaiw /* For empty section, we proceed if we need to append. */ 1037260684Skaiw if (!is_append_section(ecp, s->name)) 1038260684Skaiw return; 1039260684Skaiw } 1040260684Skaiw 1041260684Skaiw /* Allocate buffer needed for new section data. */ 1042260684Skaiw dstsz = srcsz; 1043260684Skaiw if (is_append_section(ecp, s->name)) { 1044260684Skaiw sac = lookup_sec_act(ecp, s->name, 0); 1045260684Skaiw dstsz += strlen(sac->string) + 1; 1046260684Skaiw } 1047260684Skaiw if ((b = malloc(dstsz)) == NULL) 1048260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1049260684Skaiw s->buf = b; 1050260684Skaiw 1051260684Skaiw /* Compress section. */ 1052260684Skaiw p = 0; 1053260684Skaiw if (is_compress_section(ecp, s->name)) { 1054260684Skaiw end = src + srcsz; 1055260684Skaiw for(c = src; c < end;) { 1056260684Skaiw len = 0; 1057260684Skaiw while(c + len < end && c[len] != '\0') 1058260684Skaiw len++; 1059260684Skaiw if (c + len == end) { 1060260684Skaiw /* XXX should we warn here? */ 1061260684Skaiw strncpy(&b[p], c, len); 1062260684Skaiw p += len; 1063260684Skaiw break; 1064260684Skaiw } 1065260684Skaiw dupe = 0; 1066260684Skaiw for (d = b; d < b + p; ) { 1067260684Skaiw if (strcmp(d, c) == 0) { 1068260684Skaiw dupe = 1; 1069260684Skaiw break; 1070260684Skaiw } 1071260684Skaiw d += strlen(d) + 1; 1072260684Skaiw } 1073260684Skaiw if (!dupe) { 1074260684Skaiw strncpy(&b[p], c, len); 1075260684Skaiw b[p + len] = '\0'; 1076260684Skaiw p += len + 1; 1077260684Skaiw } 1078260684Skaiw c += len + 1; 1079260684Skaiw } 1080260684Skaiw } else { 1081260684Skaiw memcpy(b, src, srcsz); 1082260684Skaiw p += srcsz; 1083260684Skaiw } 1084260684Skaiw 1085260684Skaiw /* Append section. */ 1086260684Skaiw if (is_append_section(ecp, s->name)) { 1087260684Skaiw sac = lookup_sec_act(ecp, s->name, 0); 1088260684Skaiw len = strlen(sac->string); 1089260684Skaiw strncpy(&b[p], sac->string, len); 1090260684Skaiw b[p + len] = '\0'; 1091260684Skaiw p += len + 1; 1092260684Skaiw } 1093260684Skaiw 1094260684Skaiw s->sz = p; 1095260684Skaiw s->nocopy = 1; 1096260684Skaiw} 1097260684Skaiw 1098260684Skaiwstatic void 1099260684Skaiwprint_data(const char *d, size_t sz) 1100260684Skaiw{ 1101260684Skaiw const char *c; 1102260684Skaiw 1103260684Skaiw for (c = d; c < d + sz; c++) { 1104260684Skaiw if (*c == '\0') 1105260684Skaiw putchar('\n'); 1106260684Skaiw else 1107260684Skaiw putchar(*c); 1108260684Skaiw } 1109260684Skaiw} 1110260684Skaiw 1111260684Skaiwstatic void 1112260684Skaiwprint_section(struct section *s) 1113260684Skaiw{ 1114260684Skaiw Elf_Data *id; 1115260684Skaiw int elferr; 1116260684Skaiw 1117260684Skaiw if (s->buf != NULL && s->sz > 0) { 1118260684Skaiw print_data(s->buf, s->sz); 1119260684Skaiw } else { 1120260684Skaiw id = NULL; 1121295577Semaste while ((id = elf_getdata(s->is, id)) != NULL || 1122295577Semaste (id = elf_rawdata(s->is, id)) != NULL) { 1123295577Semaste (void) elf_errno(); 1124260684Skaiw print_data(id->d_buf, id->d_size); 1125295577Semaste } 1126260684Skaiw elferr = elf_errno(); 1127260684Skaiw if (elferr != 0) 1128260684Skaiw errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1129260684Skaiw elf_errmsg(elferr)); 1130260684Skaiw } 1131260684Skaiw putchar('\n'); 1132260684Skaiw} 1133260684Skaiw 1134260684Skaiwstatic void * 1135260684Skaiwread_section(struct section *s, size_t *size) 1136260684Skaiw{ 1137260684Skaiw Elf_Data *id; 1138260684Skaiw char *b; 1139260684Skaiw size_t sz; 1140260684Skaiw int elferr; 1141260684Skaiw 1142260684Skaiw sz = 0; 1143260684Skaiw b = NULL; 1144260684Skaiw id = NULL; 1145295577Semaste while ((id = elf_getdata(s->is, id)) != NULL || 1146295577Semaste (id = elf_rawdata(s->is, id)) != NULL) { 1147295577Semaste (void) elf_errno(); 1148260684Skaiw if (b == NULL) 1149260684Skaiw b = malloc(id->d_size); 1150260684Skaiw else 1151367466Sdim b = realloc(b, sz + id->d_size); 1152260684Skaiw if (b == NULL) 1153260684Skaiw err(EXIT_FAILURE, "malloc or realloc failed"); 1154260684Skaiw 1155260684Skaiw memcpy(&b[sz], id->d_buf, id->d_size); 1156260684Skaiw sz += id->d_size; 1157260684Skaiw } 1158260684Skaiw elferr = elf_errno(); 1159260684Skaiw if (elferr != 0) 1160260684Skaiw errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1161260684Skaiw elf_errmsg(elferr)); 1162260684Skaiw 1163260684Skaiw *size = sz; 1164260684Skaiw 1165260684Skaiw return (b); 1166260684Skaiw} 1167260684Skaiw 1168260684Skaiwvoid 1169260684Skaiwcopy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 1170260684Skaiw int sec_flags) 1171260684Skaiw{ 1172260684Skaiw GElf_Shdr ish, osh; 1173260684Skaiw 1174260684Skaiw if (gelf_getshdr(s->is, &ish) == NULL) 1175295577Semaste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1176260684Skaiw elf_errmsg(-1)); 1177260684Skaiw if (gelf_getshdr(s->os, &osh) == NULL) 1178295577Semaste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1179260684Skaiw elf_errmsg(-1)); 1180260684Skaiw 1181260684Skaiw if (copy) 1182260684Skaiw (void) memcpy(&osh, &ish, sizeof(ish)); 1183260684Skaiw else { 1184260684Skaiw osh.sh_type = s->type; 1185260684Skaiw osh.sh_addr = s->vma; 1186260684Skaiw osh.sh_offset = s->off; 1187260684Skaiw osh.sh_size = s->sz; 1188260684Skaiw osh.sh_link = ish.sh_link; 1189260684Skaiw osh.sh_info = ish.sh_info; 1190260684Skaiw osh.sh_addralign = s->align; 1191260684Skaiw osh.sh_entsize = ish.sh_entsize; 1192260684Skaiw 1193260684Skaiw if (sec_flags) { 1194260684Skaiw osh.sh_flags = 0; 1195295577Semaste if (sec_flags & SF_ALLOC) 1196260684Skaiw osh.sh_flags |= SHF_ALLOC; 1197260684Skaiw if ((sec_flags & SF_READONLY) == 0) 1198260684Skaiw osh.sh_flags |= SHF_WRITE; 1199260684Skaiw if (sec_flags & SF_CODE) 1200260684Skaiw osh.sh_flags |= SHF_EXECINSTR; 1201295577Semaste if ((sec_flags & SF_CONTENTS) && 1202295577Semaste s->type == SHT_NOBITS && s->sz > 0) { 1203295577Semaste /* 1204295577Semaste * Convert SHT_NOBITS section to section with 1205295577Semaste * (zero'ed) content on file. 1206295577Semaste */ 1207295577Semaste osh.sh_type = s->type = SHT_PROGBITS; 1208295577Semaste if ((s->buf = calloc(1, s->sz)) == NULL) 1209295577Semaste err(EXIT_FAILURE, "malloc failed"); 1210295577Semaste s->nocopy = 1; 1211295577Semaste } 1212283616Semaste } else { 1213260684Skaiw osh.sh_flags = ish.sh_flags; 1214295577Semaste /* 1215295577Semaste * Newer binutils as(1) emits the section flag 1216295577Semaste * SHF_INFO_LINK for relocation sections. elfcopy 1217295577Semaste * emits this flag in the output section if it's 1218295577Semaste * missing in the input section, to remain compatible 1219295577Semaste * with binutils. 1220295577Semaste */ 1221283616Semaste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 1222283616Semaste osh.sh_flags |= SHF_INFO_LINK; 1223283616Semaste } 1224260684Skaiw } 1225260684Skaiw 1226260684Skaiw if (name == NULL) 1227260684Skaiw add_to_shstrtab(ecp, s->name); 1228260684Skaiw else 1229260684Skaiw add_to_shstrtab(ecp, name); 1230260684Skaiw 1231260684Skaiw if (!gelf_update_shdr(s->os, &osh)) 1232260684Skaiw errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1233260684Skaiw elf_errmsg(-1)); 1234260684Skaiw} 1235260684Skaiw 1236260684Skaiwvoid 1237260684Skaiwcopy_data(struct section *s) 1238260684Skaiw{ 1239260684Skaiw Elf_Data *id, *od; 1240260684Skaiw int elferr; 1241260684Skaiw 1242260684Skaiw if (s->nocopy && s->buf == NULL) 1243260684Skaiw return; 1244260684Skaiw 1245260684Skaiw if ((id = elf_getdata(s->is, NULL)) == NULL) { 1246295577Semaste (void) elf_errno(); 1247295577Semaste if ((id = elf_rawdata(s->is, NULL)) == NULL) { 1248295577Semaste elferr = elf_errno(); 1249295577Semaste if (elferr != 0) 1250295577Semaste errx(EXIT_FAILURE, "failed to read section:" 1251295577Semaste " %s", s->name); 1252295577Semaste return; 1253295577Semaste } 1254260684Skaiw } 1255260684Skaiw 1256260684Skaiw if ((od = elf_newdata(s->os)) == NULL) 1257260684Skaiw errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1258260684Skaiw elf_errmsg(-1)); 1259260684Skaiw 1260260684Skaiw if (s->nocopy) { 1261260684Skaiw /* Use s->buf as content if s->nocopy is set. */ 1262260684Skaiw od->d_align = id->d_align; 1263260684Skaiw od->d_off = 0; 1264260684Skaiw od->d_buf = s->buf; 1265260684Skaiw od->d_type = id->d_type; 1266260684Skaiw od->d_size = s->sz; 1267260684Skaiw od->d_version = id->d_version; 1268260684Skaiw } else { 1269260684Skaiw od->d_align = id->d_align; 1270260684Skaiw od->d_off = id->d_off; 1271260684Skaiw od->d_buf = id->d_buf; 1272260684Skaiw od->d_type = id->d_type; 1273260684Skaiw od->d_size = id->d_size; 1274260684Skaiw od->d_version = id->d_version; 1275260684Skaiw } 1276276398Semaste 1277276398Semaste /* 1278276398Semaste * Alignment Fixup. libelf does not allow the alignment for 1279276398Semaste * Elf_Data descriptor to be set to 0. In this case we workaround 1280276398Semaste * it by setting the alignment to 1. 1281276398Semaste * 1282276398Semaste * According to the ELF ABI, alignment 0 and 1 has the same 1283276398Semaste * meaning: the section has no alignment constraints. 1284276398Semaste */ 1285276398Semaste if (od->d_align == 0) 1286276398Semaste od->d_align = 1; 1287260684Skaiw} 1288260684Skaiw 1289260684Skaiwstruct section * 1290260684Skaiwcreate_external_section(struct elfcopy *ecp, const char *name, char *newname, 1291260684Skaiw void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1292260684Skaiw uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1293260684Skaiw{ 1294260684Skaiw struct section *s; 1295260684Skaiw Elf_Scn *os; 1296260684Skaiw Elf_Data *od; 1297260684Skaiw GElf_Shdr osh; 1298260684Skaiw 1299260684Skaiw if ((os = elf_newscn(ecp->eout)) == NULL) 1300260684Skaiw errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1301260684Skaiw elf_errmsg(-1)); 1302260684Skaiw if ((s = calloc(1, sizeof(*s))) == NULL) 1303260684Skaiw err(EXIT_FAILURE, "calloc failed"); 1304260684Skaiw s->name = name; 1305260684Skaiw s->newname = newname; /* needs to be free()'ed */ 1306260684Skaiw s->off = off; 1307260684Skaiw s->sz = size; 1308260684Skaiw s->vma = vma; 1309260684Skaiw s->align = align; 1310260684Skaiw s->loadable = loadable; 1311260684Skaiw s->is = NULL; 1312260684Skaiw s->os = os; 1313260684Skaiw s->type = stype; 1314260684Skaiw s->nocopy = 1; 1315260684Skaiw insert_to_sec_list(ecp, s, 1); 1316260684Skaiw 1317260684Skaiw if (gelf_getshdr(os, &osh) == NULL) 1318260684Skaiw errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1319260684Skaiw elf_errmsg(-1)); 1320260684Skaiw osh.sh_flags = flags; 1321260684Skaiw osh.sh_type = s->type; 1322260684Skaiw osh.sh_addr = s->vma; 1323260684Skaiw osh.sh_addralign = s->align; 1324260684Skaiw if (!gelf_update_shdr(os, &osh)) 1325260684Skaiw errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1326260684Skaiw elf_errmsg(-1)); 1327260684Skaiw add_to_shstrtab(ecp, name); 1328260684Skaiw 1329260684Skaiw if (buf != NULL && size != 0) { 1330260684Skaiw if ((od = elf_newdata(os)) == NULL) 1331260684Skaiw errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1332260684Skaiw elf_errmsg(-1)); 1333260684Skaiw od->d_align = align; 1334260684Skaiw od->d_off = 0; 1335260684Skaiw od->d_buf = buf; 1336260684Skaiw od->d_size = size; 1337260684Skaiw od->d_type = dtype; 1338260684Skaiw od->d_version = EV_CURRENT; 1339260684Skaiw } 1340260684Skaiw 1341260684Skaiw /* 1342260684Skaiw * Clear SYMTAB_INTACT, as we probably need to update/add new 1343260684Skaiw * STT_SECTION symbols into the symbol table. 1344260684Skaiw */ 1345260684Skaiw ecp->flags &= ~SYMTAB_INTACT; 1346260684Skaiw 1347260684Skaiw return (s); 1348260684Skaiw} 1349260684Skaiw 1350260684Skaiw/* 1351260684Skaiw * Insert sections specified by --add-section to the end of section list. 1352260684Skaiw */ 1353260684Skaiwstatic void 1354260684Skaiwinsert_sections(struct elfcopy *ecp) 1355260684Skaiw{ 1356260684Skaiw struct sec_add *sa; 1357260684Skaiw struct section *s; 1358260684Skaiw size_t off; 1359295577Semaste uint64_t stype; 1360260684Skaiw 1361260684Skaiw /* Put these sections in the end of current list. */ 1362260684Skaiw off = 0; 1363260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1364260684Skaiw if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1365260684Skaiw off = s->off + s->sz; 1366260684Skaiw else 1367260684Skaiw off = s->off; 1368260684Skaiw } 1369260684Skaiw 1370260684Skaiw STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1371260684Skaiw 1372260684Skaiw /* TODO: Add section header vma/lma, flag changes here */ 1373260684Skaiw 1374295577Semaste /* 1375295577Semaste * The default section type for user added section is 1376295577Semaste * SHT_PROGBITS. If the section name match certain patterns, 1377295577Semaste * elfcopy will try to set a more appropriate section type. 1378295577Semaste * However, data type is always set to ELF_T_BYTE and no 1379295577Semaste * translation is performed by libelf. 1380295577Semaste */ 1381295577Semaste stype = SHT_PROGBITS; 1382295577Semaste if (strcmp(sa->name, ".note") == 0 || 1383295577Semaste strncmp(sa->name, ".note.", strlen(".note.")) == 0) 1384295577Semaste stype = SHT_NOTE; 1385295577Semaste 1386260684Skaiw (void) create_external_section(ecp, sa->name, NULL, sa->content, 1387295577Semaste sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0); 1388260684Skaiw } 1389260684Skaiw} 1390260684Skaiw 1391260684Skaiwvoid 1392260684Skaiwadd_to_shstrtab(struct elfcopy *ecp, const char *name) 1393260684Skaiw{ 1394260684Skaiw 1395367466Sdim if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0) 1396367466Sdim errx(EXIT_FAILURE, "elftc_string_table_insert failed"); 1397260684Skaiw} 1398260684Skaiw 1399260684Skaiwvoid 1400260684Skaiwupdate_shdr(struct elfcopy *ecp, int update_link) 1401260684Skaiw{ 1402260684Skaiw struct section *s; 1403260684Skaiw GElf_Shdr osh; 1404260684Skaiw int elferr; 1405260684Skaiw 1406367466Sdim /* Finalize the section name string table (.shstrtab). */ 1407367466Sdim set_shstrtab(ecp); 1408367466Sdim 1409260684Skaiw TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1410260684Skaiw if (s->pseudo) 1411260684Skaiw continue; 1412260684Skaiw 1413260684Skaiw if (gelf_getshdr(s->os, &osh) == NULL) 1414295577Semaste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 1415260684Skaiw elf_errmsg(-1)); 1416260684Skaiw 1417260684Skaiw /* Find section name in string table and set sh_name. */ 1418367466Sdim osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab, 1419367466Sdim s->name); 1420260684Skaiw 1421260684Skaiw /* 1422260684Skaiw * sh_link needs to be updated, since the index of the 1423260684Skaiw * linked section might have changed. 1424260684Skaiw */ 1425260684Skaiw if (update_link && osh.sh_link != 0) 1426260684Skaiw osh.sh_link = ecp->secndx[osh.sh_link]; 1427260684Skaiw 1428260684Skaiw /* 1429260684Skaiw * sh_info of relocation section links to the section to which 1430260684Skaiw * its relocation info applies. So it may need update as well. 1431260684Skaiw */ 1432260684Skaiw if ((s->type == SHT_REL || s->type == SHT_RELA) && 1433260684Skaiw osh.sh_info != 0) 1434260684Skaiw osh.sh_info = ecp->secndx[osh.sh_info]; 1435260684Skaiw 1436282918Semaste /* 1437282918Semaste * sh_info of SHT_GROUP section needs to point to the correct 1438282918Semaste * string in the symbol table. 1439282918Semaste */ 1440282918Semaste if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) && 1441282918Semaste (ecp->flags & SYMTAB_INTACT) == 0) 1442282918Semaste osh.sh_info = ecp->symndx[osh.sh_info]; 1443282918Semaste 1444260684Skaiw if (!gelf_update_shdr(s->os, &osh)) 1445260684Skaiw errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1446260684Skaiw elf_errmsg(-1)); 1447260684Skaiw } 1448260684Skaiw elferr = elf_errno(); 1449260684Skaiw if (elferr != 0) 1450260684Skaiw errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1451260684Skaiw elf_errmsg(elferr)); 1452260684Skaiw} 1453260684Skaiw 1454260684Skaiwvoid 1455260684Skaiwinit_shstrtab(struct elfcopy *ecp) 1456260684Skaiw{ 1457367466Sdim Elf_Scn *shstrtab; 1458367466Sdim GElf_Shdr shdr; 1459260684Skaiw struct section *s; 1460367466Sdim size_t indx, sizehint; 1461260684Skaiw 1462367466Sdim if (elf_getshdrstrndx(ecp->ein, &indx) == 0) { 1463367466Sdim shstrtab = elf_getscn(ecp->ein, indx); 1464367466Sdim if (shstrtab == NULL) 1465367466Sdim errx(EXIT_FAILURE, "elf_getscn failed: %s", 1466367466Sdim elf_errmsg(-1)); 1467367466Sdim if (gelf_getshdr(shstrtab, &shdr) != &shdr) 1468367466Sdim errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 1469367466Sdim elf_errmsg(-1)); 1470367466Sdim sizehint = shdr.sh_size; 1471367466Sdim } else { 1472367466Sdim /* Clear the error from elf_getshdrstrndx(3). */ 1473367466Sdim (void)elf_errno(); 1474367466Sdim sizehint = 0; 1475367466Sdim } 1476367466Sdim 1477260684Skaiw if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1478260684Skaiw err(EXIT_FAILURE, "calloc failed"); 1479260684Skaiw s = ecp->shstrtab; 1480260684Skaiw s->name = ".shstrtab"; 1481260684Skaiw s->is = NULL; 1482260684Skaiw s->sz = 0; 1483260684Skaiw s->align = 1; 1484260684Skaiw s->loadable = 0; 1485260684Skaiw s->type = SHT_STRTAB; 1486260684Skaiw s->vma = 0; 1487367466Sdim s->strtab = elftc_string_table_create(sizehint); 1488276061Semaste 1489367466Sdim add_to_shstrtab(ecp, ""); 1490367466Sdim add_to_shstrtab(ecp, ".symtab"); 1491367466Sdim add_to_shstrtab(ecp, ".strtab"); 1492367466Sdim add_to_shstrtab(ecp, ".shstrtab"); 1493260684Skaiw} 1494260684Skaiw 1495367466Sdimstatic void 1496260684Skaiwset_shstrtab(struct elfcopy *ecp) 1497260684Skaiw{ 1498260684Skaiw struct section *s; 1499260684Skaiw Elf_Data *data; 1500260684Skaiw GElf_Shdr sh; 1501367466Sdim const char *image; 1502367466Sdim size_t sz; 1503260684Skaiw 1504260684Skaiw s = ecp->shstrtab; 1505260684Skaiw 1506284339Semaste if (s->os == NULL) { 1507284339Semaste /* Input object does not contain .shstrtab section */ 1508284339Semaste if ((s->os = elf_newscn(ecp->eout)) == NULL) 1509284339Semaste errx(EXIT_FAILURE, "elf_newscn failed: %s", 1510284339Semaste elf_errmsg(-1)); 1511284339Semaste insert_to_sec_list(ecp, s, 1); 1512284339Semaste } 1513284339Semaste 1514260684Skaiw if (gelf_getshdr(s->os, &sh) == NULL) 1515295577Semaste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1516260684Skaiw elf_errmsg(-1)); 1517260684Skaiw sh.sh_addr = 0; 1518260684Skaiw sh.sh_addralign = 1; 1519260684Skaiw sh.sh_offset = s->off; 1520260684Skaiw sh.sh_type = SHT_STRTAB; 1521260684Skaiw sh.sh_flags = 0; 1522260684Skaiw sh.sh_entsize = 0; 1523260684Skaiw sh.sh_info = 0; 1524260684Skaiw sh.sh_link = 0; 1525260684Skaiw 1526260684Skaiw if ((data = elf_newdata(s->os)) == NULL) 1527260684Skaiw errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1528260684Skaiw elf_errmsg(-1)); 1529260684Skaiw 1530260684Skaiw /* 1531260684Skaiw * If we don't have a symbol table, skip those a few bytes 1532260684Skaiw * which are reserved for this in the beginning of shstrtab. 1533260684Skaiw */ 1534260684Skaiw if (!(ecp->flags & SYMTAB_EXIST)) { 1535367466Sdim elftc_string_table_remove(s->strtab, ".symtab"); 1536367466Sdim elftc_string_table_remove(s->strtab, ".strtab"); 1537260684Skaiw } 1538260684Skaiw 1539367466Sdim image = elftc_string_table_image(s->strtab, &sz); 1540367466Sdim s->sz = sz; 1541367466Sdim 1542367466Sdim sh.sh_size = sz; 1543260684Skaiw if (!gelf_update_shdr(s->os, &sh)) 1544260684Skaiw errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1545260684Skaiw elf_errmsg(-1)); 1546260684Skaiw 1547260684Skaiw data->d_align = 1; 1548367466Sdim data->d_buf = (void *)(uintptr_t)image; 1549367466Sdim data->d_size = sz; 1550260684Skaiw data->d_off = 0; 1551260684Skaiw data->d_type = ELF_T_BYTE; 1552260684Skaiw data->d_version = EV_CURRENT; 1553260684Skaiw 1554260684Skaiw if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1555260684Skaiw errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1556260684Skaiw elf_errmsg(-1)); 1557260684Skaiw} 1558260684Skaiw 1559260684Skaiwvoid 1560260684Skaiwadd_section(struct elfcopy *ecp, const char *arg) 1561260684Skaiw{ 1562260684Skaiw struct sec_add *sa; 1563260684Skaiw struct stat sb; 1564260684Skaiw const char *s, *fn; 1565260684Skaiw FILE *fp; 1566260684Skaiw int len; 1567260684Skaiw 1568260684Skaiw if ((s = strchr(arg, '=')) == NULL) 1569260684Skaiw errx(EXIT_FAILURE, 1570260684Skaiw "illegal format for --add-section option"); 1571260684Skaiw if ((sa = malloc(sizeof(*sa))) == NULL) 1572260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1573260684Skaiw 1574260684Skaiw len = s - arg; 1575260684Skaiw if ((sa->name = malloc(len + 1)) == NULL) 1576260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1577260684Skaiw strncpy(sa->name, arg, len); 1578260684Skaiw sa->name[len] = '\0'; 1579260684Skaiw 1580260684Skaiw fn = s + 1; 1581260684Skaiw if (stat(fn, &sb) == -1) 1582260684Skaiw err(EXIT_FAILURE, "stat failed"); 1583260684Skaiw sa->size = sb.st_size; 1584295577Semaste if (sa->size > 0) { 1585295577Semaste if ((sa->content = malloc(sa->size)) == NULL) 1586295577Semaste err(EXIT_FAILURE, "malloc failed"); 1587295577Semaste if ((fp = fopen(fn, "r")) == NULL) 1588295577Semaste err(EXIT_FAILURE, "can not open %s", fn); 1589295577Semaste if (fread(sa->content, 1, sa->size, fp) == 0 || 1590295577Semaste ferror(fp)) 1591295577Semaste err(EXIT_FAILURE, "fread failed"); 1592295577Semaste fclose(fp); 1593295577Semaste } else 1594295577Semaste sa->content = NULL; 1595260684Skaiw 1596260684Skaiw STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1597260684Skaiw ecp->flags |= SEC_ADD; 1598260684Skaiw} 1599260684Skaiw 1600260684Skaiwvoid 1601260684Skaiwfree_sec_add(struct elfcopy *ecp) 1602260684Skaiw{ 1603260684Skaiw struct sec_add *sa, *sa_temp; 1604260684Skaiw 1605260684Skaiw STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1606260684Skaiw STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1607260684Skaiw free(sa->name); 1608260684Skaiw free(sa->content); 1609260684Skaiw free(sa); 1610260684Skaiw } 1611260684Skaiw} 1612260684Skaiw 1613260684Skaiwstatic void 1614260684Skaiwadd_gnu_debuglink(struct elfcopy *ecp) 1615260684Skaiw{ 1616260684Skaiw struct sec_add *sa; 1617260684Skaiw struct stat sb; 1618260684Skaiw FILE *fp; 1619260684Skaiw char *fnbase, *buf; 1620260684Skaiw int crc_off; 1621260684Skaiw int crc; 1622260684Skaiw 1623260684Skaiw if (ecp->debuglink == NULL) 1624260684Skaiw return; 1625260684Skaiw 1626260684Skaiw /* Read debug file content. */ 1627260684Skaiw if ((sa = malloc(sizeof(*sa))) == NULL) 1628260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1629260684Skaiw if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1630260684Skaiw err(EXIT_FAILURE, "strdup failed"); 1631260684Skaiw if (stat(ecp->debuglink, &sb) == -1) 1632260684Skaiw err(EXIT_FAILURE, "stat failed"); 1633296391Semaste if (sb.st_size == 0) 1634296391Semaste errx(EXIT_FAILURE, "empty debug link target %s", 1635296391Semaste ecp->debuglink); 1636260684Skaiw if ((buf = malloc(sb.st_size)) == NULL) 1637260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1638260684Skaiw if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1639260684Skaiw err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1640260684Skaiw if (fread(buf, 1, sb.st_size, fp) == 0 || 1641260684Skaiw ferror(fp)) 1642260684Skaiw err(EXIT_FAILURE, "fread failed"); 1643260684Skaiw fclose(fp); 1644260684Skaiw 1645260684Skaiw /* Calculate crc checksum. */ 1646260684Skaiw crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1647260684Skaiw free(buf); 1648260684Skaiw 1649260684Skaiw /* Calculate section size and the offset to store crc checksum. */ 1650260684Skaiw if ((fnbase = basename(ecp->debuglink)) == NULL) 1651260684Skaiw err(EXIT_FAILURE, "basename failed"); 1652260684Skaiw crc_off = roundup(strlen(fnbase) + 1, 4); 1653260684Skaiw sa->size = crc_off + 4; 1654260684Skaiw 1655260684Skaiw /* Section content. */ 1656260684Skaiw if ((sa->content = calloc(1, sa->size)) == NULL) 1657260684Skaiw err(EXIT_FAILURE, "malloc failed"); 1658260684Skaiw strncpy(sa->content, fnbase, strlen(fnbase)); 1659260684Skaiw if (ecp->oed == ELFDATA2LSB) { 1660260684Skaiw sa->content[crc_off] = crc & 0xFF; 1661260684Skaiw sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1662260684Skaiw sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1663260684Skaiw sa->content[crc_off + 3] = crc >> 24; 1664260684Skaiw } else { 1665260684Skaiw sa->content[crc_off] = crc >> 24; 1666260684Skaiw sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1667260684Skaiw sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1668260684Skaiw sa->content[crc_off + 3] = crc & 0xFF; 1669260684Skaiw } 1670260684Skaiw 1671260684Skaiw STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1672260684Skaiw ecp->flags |= SEC_ADD; 1673260684Skaiw} 1674260684Skaiw 1675260684Skaiwstatic uint32_t crctable[256] = 1676260684Skaiw{ 1677260684Skaiw 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1678260684Skaiw 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1679260684Skaiw 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1680260684Skaiw 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1681260684Skaiw 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1682260684Skaiw 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1683260684Skaiw 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1684260684Skaiw 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1685260684Skaiw 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1686260684Skaiw 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1687260684Skaiw 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1688260684Skaiw 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1689260684Skaiw 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1690260684Skaiw 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1691260684Skaiw 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1692260684Skaiw 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1693260684Skaiw 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1694260684Skaiw 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1695260684Skaiw 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1696260684Skaiw 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1697260684Skaiw 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1698260684Skaiw 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1699260684Skaiw 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1700260684Skaiw 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1701260684Skaiw 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1702260684Skaiw 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1703260684Skaiw 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1704260684Skaiw 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1705260684Skaiw 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1706260684Skaiw 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1707260684Skaiw 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1708260684Skaiw 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1709260684Skaiw 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1710260684Skaiw 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1711260684Skaiw 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1712260684Skaiw 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1713260684Skaiw 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1714260684Skaiw 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1715260684Skaiw 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1716260684Skaiw 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1717260684Skaiw 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1718260684Skaiw 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1719260684Skaiw 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1720260684Skaiw 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1721260684Skaiw 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1722260684Skaiw 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1723260684Skaiw 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1724260684Skaiw 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1725260684Skaiw 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1726260684Skaiw 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1727260684Skaiw 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1728260684Skaiw 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1729260684Skaiw 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1730260684Skaiw 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1731260684Skaiw 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1732260684Skaiw 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1733260684Skaiw 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1734260684Skaiw 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1735260684Skaiw 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1736260684Skaiw 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1737260684Skaiw 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1738260684Skaiw 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1739260684Skaiw 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1740260684Skaiw 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1741260684Skaiw}; 1742260684Skaiw 1743260684Skaiwstatic uint32_t 1744260684Skaiwcalc_crc32(const char *p, size_t len, uint32_t crc) 1745260684Skaiw{ 1746260684Skaiw uint32_t i; 1747260684Skaiw 1748260684Skaiw for (i = 0; i < len; i++) { 1749260684Skaiw crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1750260684Skaiw } 1751260684Skaiw 1752260684Skaiw return (crc ^ 0xFFFFFFFF); 1753260684Skaiw} 1754