1a85fe12eSEd Maste /*- 24a85c691SEd Maste * Copyright (c) 2007-2011,2014 Kai Wang 3a85fe12eSEd Maste * All rights reserved. 4a85fe12eSEd Maste * 5a85fe12eSEd Maste * Redistribution and use in source and binary forms, with or without 6a85fe12eSEd Maste * modification, are permitted provided that the following conditions 7a85fe12eSEd Maste * are met: 8a85fe12eSEd Maste * 1. Redistributions of source code must retain the above copyright 9a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer. 10a85fe12eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright 11a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer in the 12a85fe12eSEd Maste * documentation and/or other materials provided with the distribution. 13a85fe12eSEd Maste * 14a85fe12eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15a85fe12eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16a85fe12eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17a85fe12eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18a85fe12eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19a85fe12eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20a85fe12eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21a85fe12eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22a85fe12eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23a85fe12eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24a85fe12eSEd Maste * SUCH DAMAGE. 25a85fe12eSEd Maste */ 26a85fe12eSEd Maste 27a85fe12eSEd Maste #include <sys/param.h> 28a85fe12eSEd Maste #include <sys/stat.h> 29a85fe12eSEd Maste #include <err.h> 30a85fe12eSEd Maste #include <libgen.h> 31a85fe12eSEd Maste #include <stdio.h> 32a85fe12eSEd Maste #include <stdlib.h> 33a85fe12eSEd Maste #include <string.h> 34a85fe12eSEd Maste 35a85fe12eSEd Maste #include "elfcopy.h" 36a85fe12eSEd Maste 37ae500c1fSEd Maste ELFTC_VCSID("$Id: sections.c 3646 2018-10-27 02:25:39Z emaste $"); 38a85fe12eSEd Maste 39a85fe12eSEd Maste static void add_gnu_debuglink(struct elfcopy *ecp); 40a85fe12eSEd Maste static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); 41a85fe12eSEd Maste static void check_section_rename(struct elfcopy *ecp, struct section *s); 42aee4c74cSEd Maste static void filter_reloc(struct elfcopy *ecp, struct section *s); 43a85fe12eSEd Maste static int get_section_flags(struct elfcopy *ecp, const char *name); 44a85fe12eSEd Maste static void insert_sections(struct elfcopy *ecp); 45a85fe12eSEd Maste static int is_append_section(struct elfcopy *ecp, const char *name); 46a85fe12eSEd Maste static int is_compress_section(struct elfcopy *ecp, const char *name); 47a85fe12eSEd Maste static int is_debug_section(const char *name); 4867d97fe7SEd Maste static int is_dwo_section(const char *name); 49a85fe12eSEd Maste static int is_modify_section(struct elfcopy *ecp, const char *name); 50a85fe12eSEd Maste static int is_print_section(struct elfcopy *ecp, const char *name); 51a85fe12eSEd Maste static void modify_section(struct elfcopy *ecp, struct section *s); 52a85fe12eSEd Maste static void pad_section(struct elfcopy *ecp, struct section *s); 53a85fe12eSEd Maste static void print_data(const char *d, size_t sz); 54a85fe12eSEd Maste static void print_section(struct section *s); 55a85fe12eSEd Maste static void *read_section(struct section *s, size_t *size); 56*bc589b72SMark Johnston static void set_shstrtab(struct elfcopy *ecp); 57a85fe12eSEd Maste static void update_reloc(struct elfcopy *ecp, struct section *s); 583ef90571SEd Maste static void update_section_group(struct elfcopy *ecp, struct section *s); 59a85fe12eSEd Maste 60a85fe12eSEd Maste int 61a85fe12eSEd Maste is_remove_section(struct elfcopy *ecp, const char *name) 62a85fe12eSEd Maste { 63a85fe12eSEd Maste 64a85fe12eSEd Maste /* Always keep section name table */ 65a85fe12eSEd Maste if (strcmp(name, ".shstrtab") == 0) 66a85fe12eSEd Maste return 0; 67a85fe12eSEd Maste if (strcmp(name, ".symtab") == 0 || 68a85fe12eSEd Maste strcmp(name, ".strtab") == 0) { 69a85fe12eSEd Maste if (ecp->strip == STRIP_ALL && lookup_symop_list( 70a85fe12eSEd Maste ecp, NULL, SYMOP_KEEP) == NULL) 71a85fe12eSEd Maste return (1); 72a85fe12eSEd Maste else 73a85fe12eSEd Maste return (0); 74a85fe12eSEd Maste } 75a85fe12eSEd Maste 7667d97fe7SEd Maste if (ecp->strip == STRIP_DWO && is_dwo_section(name)) 7767d97fe7SEd Maste return (1); 7867d97fe7SEd Maste if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name)) 7967d97fe7SEd Maste return (1); 8067d97fe7SEd Maste 81a85fe12eSEd Maste if (is_debug_section(name)) { 82a85fe12eSEd Maste if (ecp->strip == STRIP_ALL || 83a85fe12eSEd Maste ecp->strip == STRIP_DEBUG || 84a85fe12eSEd Maste ecp->strip == STRIP_UNNEEDED || 85a85fe12eSEd Maste (ecp->flags & DISCARD_LOCAL)) 86a85fe12eSEd Maste return (1); 87a85fe12eSEd Maste if (ecp->strip == STRIP_NONDEBUG) 88a85fe12eSEd Maste return (0); 89a85fe12eSEd Maste } 90a85fe12eSEd Maste 91a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { 92a85fe12eSEd Maste struct sec_action *sac; 93a85fe12eSEd Maste 94a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 95a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) 96a85fe12eSEd Maste return (1); 97a85fe12eSEd Maste if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) 98a85fe12eSEd Maste return (1); 99a85fe12eSEd Maste } 100a85fe12eSEd Maste 101a85fe12eSEd Maste return (0); 102a85fe12eSEd Maste } 103a85fe12eSEd Maste 104a85fe12eSEd Maste /* 105a85fe12eSEd Maste * Relocation section needs to be removed if the section it applies to 106a85fe12eSEd Maste * will be removed. 107a85fe12eSEd Maste */ 108a85fe12eSEd Maste int 109a85fe12eSEd Maste is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) 110a85fe12eSEd Maste { 111a85fe12eSEd Maste const char *name; 112a85fe12eSEd Maste GElf_Shdr ish; 113a85fe12eSEd Maste Elf_Scn *is; 114a85fe12eSEd Maste size_t indx; 115a85fe12eSEd Maste int elferr; 116a85fe12eSEd Maste 117a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 118a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 119a85fe12eSEd Maste elf_errmsg(-1)); 120a85fe12eSEd Maste 121dc2282fcSMark Johnston is = elf_getscn(ecp->ein, sh_info); 122dc2282fcSMark Johnston if (is != NULL) { 123a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 124a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 125a85fe12eSEd Maste elf_errmsg(-1)); 126a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == 127a85fe12eSEd Maste NULL) 128a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 129a85fe12eSEd Maste elf_errmsg(-1)); 130a85fe12eSEd Maste if (is_remove_section(ecp, name)) 131a85fe12eSEd Maste return (1); 132a85fe12eSEd Maste else 133a85fe12eSEd Maste return (0); 134a85fe12eSEd Maste } 135a85fe12eSEd Maste elferr = elf_errno(); 136a85fe12eSEd Maste if (elferr != 0) 137a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 138a85fe12eSEd Maste elf_errmsg(elferr)); 139a85fe12eSEd Maste 140a85fe12eSEd Maste /* Remove reloc section if we can't find the target section. */ 141a85fe12eSEd Maste return (1); 142a85fe12eSEd Maste } 143a85fe12eSEd Maste 144a85fe12eSEd Maste static int 145a85fe12eSEd Maste is_append_section(struct elfcopy *ecp, const char *name) 146a85fe12eSEd Maste { 147a85fe12eSEd Maste struct sec_action *sac; 148a85fe12eSEd Maste 149a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 150a85fe12eSEd Maste if (sac != NULL && sac->append != 0 && sac->string != NULL) 151a85fe12eSEd Maste return (1); 152a85fe12eSEd Maste 153a85fe12eSEd Maste return (0); 154a85fe12eSEd Maste } 155a85fe12eSEd Maste 156a85fe12eSEd Maste static int 157a85fe12eSEd Maste is_compress_section(struct elfcopy *ecp, const char *name) 158a85fe12eSEd Maste { 159a85fe12eSEd Maste struct sec_action *sac; 160a85fe12eSEd Maste 161a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 162a85fe12eSEd Maste if (sac != NULL && sac->compress != 0) 163a85fe12eSEd Maste return (1); 164a85fe12eSEd Maste 165a85fe12eSEd Maste return (0); 166a85fe12eSEd Maste } 167a85fe12eSEd Maste 168a85fe12eSEd Maste static void 169a85fe12eSEd Maste check_section_rename(struct elfcopy *ecp, struct section *s) 170a85fe12eSEd Maste { 171a85fe12eSEd Maste struct sec_action *sac; 172a85fe12eSEd Maste char *prefix; 173a85fe12eSEd Maste size_t namelen; 174a85fe12eSEd Maste 175a85fe12eSEd Maste if (s->pseudo) 176a85fe12eSEd Maste return; 177a85fe12eSEd Maste 178a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 179a85fe12eSEd Maste if (sac != NULL && sac->rename) 180a85fe12eSEd Maste s->name = sac->newname; 181a85fe12eSEd Maste 182a85fe12eSEd Maste if (!strcmp(s->name, ".symtab") || 183a85fe12eSEd Maste !strcmp(s->name, ".strtab") || 184a85fe12eSEd Maste !strcmp(s->name, ".shstrtab")) 185a85fe12eSEd Maste return; 186a85fe12eSEd Maste 187a85fe12eSEd Maste prefix = NULL; 188a85fe12eSEd Maste if (s->loadable && ecp->prefix_alloc != NULL) 189a85fe12eSEd Maste prefix = ecp->prefix_alloc; 190a85fe12eSEd Maste else if (ecp->prefix_sec != NULL) 191a85fe12eSEd Maste prefix = ecp->prefix_sec; 192a85fe12eSEd Maste 193a85fe12eSEd Maste if (prefix != NULL) { 194a85fe12eSEd Maste namelen = strlen(s->name) + strlen(prefix) + 1; 195a85fe12eSEd Maste if ((s->newname = malloc(namelen)) == NULL) 196a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 197a85fe12eSEd Maste snprintf(s->newname, namelen, "%s%s", prefix, s->name); 198a85fe12eSEd Maste s->name = s->newname; 199a85fe12eSEd Maste } 200a85fe12eSEd Maste } 201a85fe12eSEd Maste 202a85fe12eSEd Maste static int 203a85fe12eSEd Maste get_section_flags(struct elfcopy *ecp, const char *name) 204a85fe12eSEd Maste { 205a85fe12eSEd Maste struct sec_action *sac; 206a85fe12eSEd Maste 207a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 208a85fe12eSEd Maste if (sac != NULL && sac->flags) 209a85fe12eSEd Maste return sac->flags; 210a85fe12eSEd Maste 211a85fe12eSEd Maste return (0); 212a85fe12eSEd Maste } 213a85fe12eSEd Maste 214a85fe12eSEd Maste /* 215a85fe12eSEd Maste * Determine whether the section are debugging section. 216a85fe12eSEd Maste * According to libbfd, debugging sections are recognized 217a85fe12eSEd Maste * only by name. 218a85fe12eSEd Maste */ 219a85fe12eSEd Maste static int 220a85fe12eSEd Maste is_debug_section(const char *name) 221a85fe12eSEd Maste { 222a85fe12eSEd Maste const char *dbg_sec[] = { 223839529caSEd Maste ".apple_", 224a85fe12eSEd Maste ".debug", 225a85fe12eSEd Maste ".gnu.linkonce.wi.", 226a85fe12eSEd Maste ".line", 227a85fe12eSEd Maste ".stab", 228a85fe12eSEd Maste NULL 229a85fe12eSEd Maste }; 230a85fe12eSEd Maste const char **p; 231a85fe12eSEd Maste 232a85fe12eSEd Maste for(p = dbg_sec; *p; p++) { 233a85fe12eSEd Maste if (strncmp(name, *p, strlen(*p)) == 0) 234a85fe12eSEd Maste return (1); 235a85fe12eSEd Maste } 236a85fe12eSEd Maste 237a85fe12eSEd Maste return (0); 238a85fe12eSEd Maste } 239a85fe12eSEd Maste 240a85fe12eSEd Maste static int 24167d97fe7SEd Maste is_dwo_section(const char *name) 24267d97fe7SEd Maste { 24367d97fe7SEd Maste size_t len; 24467d97fe7SEd Maste 24567d97fe7SEd Maste if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0) 24667d97fe7SEd Maste return (1); 24767d97fe7SEd Maste return (0); 24867d97fe7SEd Maste } 24967d97fe7SEd Maste 25067d97fe7SEd Maste static int 251a85fe12eSEd Maste is_print_section(struct elfcopy *ecp, const char *name) 252a85fe12eSEd Maste { 253a85fe12eSEd Maste struct sec_action *sac; 254a85fe12eSEd Maste 255a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 256a85fe12eSEd Maste if (sac != NULL && sac->print != 0) 257a85fe12eSEd Maste return (1); 258a85fe12eSEd Maste 259a85fe12eSEd Maste return (0); 260a85fe12eSEd Maste } 261a85fe12eSEd Maste 262a85fe12eSEd Maste static int 263a85fe12eSEd Maste is_modify_section(struct elfcopy *ecp, const char *name) 264a85fe12eSEd Maste { 265a85fe12eSEd Maste 266a85fe12eSEd Maste if (is_append_section(ecp, name) || 267a85fe12eSEd Maste is_compress_section(ecp, name)) 268a85fe12eSEd Maste return (1); 269a85fe12eSEd Maste 270a85fe12eSEd Maste return (0); 271a85fe12eSEd Maste } 272a85fe12eSEd Maste 273a85fe12eSEd Maste struct sec_action* 274a85fe12eSEd Maste lookup_sec_act(struct elfcopy *ecp, const char *name, int add) 275a85fe12eSEd Maste { 276a85fe12eSEd Maste struct sec_action *sac; 277a85fe12eSEd Maste 278a85fe12eSEd Maste if (name == NULL) 279a85fe12eSEd Maste return NULL; 280a85fe12eSEd Maste 281a85fe12eSEd Maste STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 282a85fe12eSEd Maste if (strcmp(name, sac->name) == 0) 283a85fe12eSEd Maste return sac; 284a85fe12eSEd Maste } 285a85fe12eSEd Maste 286a85fe12eSEd Maste if (add == 0) 287a85fe12eSEd Maste return NULL; 288a85fe12eSEd Maste 289a85fe12eSEd Maste if ((sac = malloc(sizeof(*sac))) == NULL) 290a85fe12eSEd Maste errx(EXIT_FAILURE, "not enough memory"); 291a85fe12eSEd Maste memset(sac, 0, sizeof(*sac)); 292a85fe12eSEd Maste sac->name = name; 293a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); 294a85fe12eSEd Maste 295a85fe12eSEd Maste return (sac); 296a85fe12eSEd Maste } 297a85fe12eSEd Maste 298a85fe12eSEd Maste void 299a85fe12eSEd Maste free_sec_act(struct elfcopy *ecp) 300a85fe12eSEd Maste { 301a85fe12eSEd Maste struct sec_action *sac, *sac_temp; 302a85fe12eSEd Maste 303a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { 304a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); 305a85fe12eSEd Maste free(sac); 306a85fe12eSEd Maste } 307a85fe12eSEd Maste } 308a85fe12eSEd Maste 309a85fe12eSEd Maste void 310a85fe12eSEd Maste insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) 311a85fe12eSEd Maste { 312a85fe12eSEd Maste struct section *s; 313a85fe12eSEd Maste 31402816870SMark Johnston if (tail || TAILQ_EMPTY(&ecp->v_sec) || 31502816870SMark Johnston TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) { 31602816870SMark Johnston TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); 31702816870SMark Johnston } else { 318a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 319a85fe12eSEd Maste if (sec->off < s->off) { 320a85fe12eSEd Maste TAILQ_INSERT_BEFORE(s, sec, sec_list); 32102816870SMark Johnston break; 322a85fe12eSEd Maste } 323a85fe12eSEd Maste } 324a85fe12eSEd Maste } 325a85fe12eSEd Maste 326a85fe12eSEd Maste if (sec->pseudo == 0) 327a85fe12eSEd Maste ecp->nos++; 328a85fe12eSEd Maste } 329a85fe12eSEd Maste 330a85fe12eSEd Maste /* 331a85fe12eSEd Maste * First step of section creation: create scn and internal section 332a85fe12eSEd Maste * structure, discard sections to be removed. 333a85fe12eSEd Maste */ 334a85fe12eSEd Maste void 335a85fe12eSEd Maste create_scn(struct elfcopy *ecp) 336a85fe12eSEd Maste { 337a85fe12eSEd Maste struct section *s; 338a85fe12eSEd Maste const char *name; 339a85fe12eSEd Maste Elf_Scn *is; 340a85fe12eSEd Maste GElf_Shdr ish; 341a85fe12eSEd Maste size_t indx; 342a85fe12eSEd Maste uint64_t oldndx, newndx; 343d938d64eSEd Maste int elferr, sec_flags, reorder; 344a85fe12eSEd Maste 345a85fe12eSEd Maste /* 346a85fe12eSEd Maste * Insert a pseudo section that contains the ELF header 347a85fe12eSEd Maste * and program header. Used as reference for section offset 348a85fe12eSEd Maste * or load address adjustment. 349a85fe12eSEd Maste */ 350a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 351a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 352a85fe12eSEd Maste s->off = 0; 353a85fe12eSEd Maste s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + 354a85fe12eSEd Maste gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); 355a85fe12eSEd Maste s->align = 1; 356a85fe12eSEd Maste s->pseudo = 1; 357a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 358a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 359a85fe12eSEd Maste 360a85fe12eSEd Maste /* Create internal .shstrtab section. */ 361a85fe12eSEd Maste init_shstrtab(ecp); 362a85fe12eSEd Maste 363a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 364a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 365a85fe12eSEd Maste elf_errmsg(-1)); 366a85fe12eSEd Maste 367d938d64eSEd Maste reorder = 0; 368a85fe12eSEd Maste is = NULL; 369a85fe12eSEd Maste while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 370a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 371839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 372a85fe12eSEd Maste elf_errmsg(-1)); 373a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) 374a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 375a85fe12eSEd Maste elf_errmsg(-1)); 376a85fe12eSEd Maste 377a85fe12eSEd Maste /* Skip sections to be removed. */ 378a85fe12eSEd Maste if (is_remove_section(ecp, name)) 379a85fe12eSEd Maste continue; 380a85fe12eSEd Maste 381a85fe12eSEd Maste /* 382a85fe12eSEd Maste * Relocation section need to be remove if the section 383a85fe12eSEd Maste * it applies will be removed. 384a85fe12eSEd Maste */ 385a85fe12eSEd Maste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 386a85fe12eSEd Maste if (ish.sh_info != 0 && 387a85fe12eSEd Maste is_remove_reloc_sec(ecp, ish.sh_info)) 388a85fe12eSEd Maste continue; 389a85fe12eSEd Maste 390cf781b2eSEd Maste /* 391cf781b2eSEd Maste * Section groups should be removed if symbol table will 392cf781b2eSEd Maste * be removed. (section group's signature stored in symbol 393cf781b2eSEd Maste * table) 394cf781b2eSEd Maste */ 395cf781b2eSEd Maste if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL) 396cf781b2eSEd Maste continue; 397cf781b2eSEd Maste 398a85fe12eSEd Maste /* Get section flags set by user. */ 399a85fe12eSEd Maste sec_flags = get_section_flags(ecp, name); 400a85fe12eSEd Maste 401a85fe12eSEd Maste /* Create internal section object. */ 402a85fe12eSEd Maste if (strcmp(name, ".shstrtab") != 0) { 403a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 404a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 405a85fe12eSEd Maste s->name = name; 406a85fe12eSEd Maste s->is = is; 407a85fe12eSEd Maste s->off = ish.sh_offset; 408a85fe12eSEd Maste s->sz = ish.sh_size; 409a85fe12eSEd Maste s->align = ish.sh_addralign; 410a85fe12eSEd Maste s->type = ish.sh_type; 41148d41ef0SPhil Shafer s->flags = ish.sh_flags; 412a85fe12eSEd Maste s->vma = ish.sh_addr; 413a85fe12eSEd Maste 414a85fe12eSEd Maste /* 415a85fe12eSEd Maste * Search program headers to determine whether section 416a85fe12eSEd Maste * is loadable, but if user explicitly set section flags 417a85fe12eSEd Maste * while neither "load" nor "alloc" is set, we make the 418a85fe12eSEd Maste * section unloadable. 419839529caSEd Maste * 420839529caSEd Maste * Sections in relocatable object is loadable if 421839529caSEd Maste * section flag SHF_ALLOC is set. 422a85fe12eSEd Maste */ 423a85fe12eSEd Maste if (sec_flags && 424a85fe12eSEd Maste (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 425a85fe12eSEd Maste s->loadable = 0; 426839529caSEd Maste else { 427a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 428839529caSEd Maste if ((ecp->flags & RELOCATABLE) && 429839529caSEd Maste (ish.sh_flags & SHF_ALLOC)) 430839529caSEd Maste s->loadable = 1; 431839529caSEd Maste } 432a85fe12eSEd Maste } else { 433a85fe12eSEd Maste /* Assuming .shstrtab is "unloadable". */ 434a85fe12eSEd Maste s = ecp->shstrtab; 435a85fe12eSEd Maste s->off = ish.sh_offset; 436a85fe12eSEd Maste } 437a85fe12eSEd Maste 438a85fe12eSEd Maste oldndx = newndx = SHN_UNDEF; 439a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 440a85fe12eSEd Maste strcmp(name, ".strtab") != 0) { 441a85fe12eSEd Maste if (!strcmp(name, ".shstrtab")) { 442a85fe12eSEd Maste /* 443a85fe12eSEd Maste * Add sections specified by --add-section and 444a85fe12eSEd Maste * gnu debuglink. we want these sections have 445a85fe12eSEd Maste * smaller index than .shstrtab section. 446a85fe12eSEd Maste */ 447a85fe12eSEd Maste if (ecp->debuglink != NULL) 448a85fe12eSEd Maste add_gnu_debuglink(ecp); 449a85fe12eSEd Maste if (ecp->flags & SEC_ADD) 450a85fe12eSEd Maste insert_sections(ecp); 451a85fe12eSEd Maste } 452a85fe12eSEd Maste if ((s->os = elf_newscn(ecp->eout)) == NULL) 453a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn failed: %s", 454a85fe12eSEd Maste elf_errmsg(-1)); 455a85fe12eSEd Maste if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 456a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 457a85fe12eSEd Maste elf_errmsg(-1)); 458a85fe12eSEd Maste } 459a85fe12eSEd Maste if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 460a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 461a85fe12eSEd Maste elf_errmsg(-1)); 462a85fe12eSEd Maste if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 463a85fe12eSEd Maste ecp->secndx[oldndx] = newndx; 464a85fe12eSEd Maste 465a85fe12eSEd Maste /* 466a85fe12eSEd Maste * If strip action is STRIP_NONDEBUG(only keep debug), 46795fd7f26SEd Maste * change sections type of loadable sections and section 46895fd7f26SEd Maste * groups to SHT_NOBITS, and the content of those sections 46995fd7f26SEd Maste * will be discarded. However, SHT_NOTE sections should 47095fd7f26SEd Maste * be kept. 471a85fe12eSEd Maste */ 47295fd7f26SEd Maste if (ecp->strip == STRIP_NONDEBUG) { 47395fd7f26SEd Maste if (((ish.sh_flags & SHF_ALLOC) || 47495fd7f26SEd Maste (ish.sh_flags & SHF_GROUP)) && 47595fd7f26SEd Maste ish.sh_type != SHT_NOTE) 476a85fe12eSEd Maste s->type = SHT_NOBITS; 47795fd7f26SEd Maste } 478a85fe12eSEd Maste 479a85fe12eSEd Maste check_section_rename(ecp, s); 480a85fe12eSEd Maste 481a85fe12eSEd Maste /* create section header based on input object. */ 482a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 483a85fe12eSEd Maste strcmp(name, ".strtab") != 0 && 484d938d64eSEd Maste strcmp(name, ".shstrtab") != 0) { 485a85fe12eSEd Maste copy_shdr(ecp, s, NULL, 0, sec_flags); 486d938d64eSEd Maste /* 487d938d64eSEd Maste * elfcopy puts .symtab, .strtab and .shstrtab 488d938d64eSEd Maste * sections in the end of the output object. 489d938d64eSEd Maste * If the input objects have more sections 490d938d64eSEd Maste * after any of these 3 sections, the section 491d938d64eSEd Maste * table will be reordered. section symbols 492d938d64eSEd Maste * should be regenerated for relocations. 493d938d64eSEd Maste */ 494d938d64eSEd Maste if (reorder) 495d938d64eSEd Maste ecp->flags &= ~SYMTAB_INTACT; 496d938d64eSEd Maste } else 497d938d64eSEd Maste reorder = 1; 498a85fe12eSEd Maste 499a85fe12eSEd Maste if (strcmp(name, ".symtab") == 0) { 500a85fe12eSEd Maste ecp->flags |= SYMTAB_EXIST; 501a85fe12eSEd Maste ecp->symtab = s; 502a85fe12eSEd Maste } 503a85fe12eSEd Maste if (strcmp(name, ".strtab") == 0) 504a85fe12eSEd Maste ecp->strtab = s; 505a85fe12eSEd Maste 506a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 507a85fe12eSEd Maste } 508a85fe12eSEd Maste elferr = elf_errno(); 509a85fe12eSEd Maste if (elferr != 0) 510a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 511a85fe12eSEd Maste elf_errmsg(elferr)); 512a85fe12eSEd Maste } 513a85fe12eSEd Maste 514a85fe12eSEd Maste struct section * 515a85fe12eSEd Maste insert_shtab(struct elfcopy *ecp, int tail) 516a85fe12eSEd Maste { 517a85fe12eSEd Maste struct section *s, *shtab; 518a85fe12eSEd Maste GElf_Ehdr ieh; 519a85fe12eSEd Maste int nsecs; 520a85fe12eSEd Maste 521a85fe12eSEd Maste /* 522a85fe12eSEd Maste * Treat section header table as a "pseudo" section, insert it 523a85fe12eSEd Maste * into section list, so later it will get sorted and resynced 524a85fe12eSEd Maste * just as normal sections. 525a85fe12eSEd Maste */ 526a85fe12eSEd Maste if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 527a85fe12eSEd Maste errx(EXIT_FAILURE, "calloc failed"); 528a85fe12eSEd Maste if (!tail) { 5294a85c691SEd Maste /* 5304a85c691SEd Maste * "shoff" of input object is used as a hint for section 5314a85c691SEd Maste * resync later. 5324a85c691SEd Maste */ 533a85fe12eSEd Maste if (gelf_getehdr(ecp->ein, &ieh) == NULL) 534a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 535a85fe12eSEd Maste elf_errmsg(-1)); 536a85fe12eSEd Maste shtab->off = ieh.e_shoff; 537a85fe12eSEd Maste } else 538a85fe12eSEd Maste shtab->off = 0; 539a85fe12eSEd Maste /* Calculate number of sections in the output object. */ 540a85fe12eSEd Maste nsecs = 0; 541a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 542a85fe12eSEd Maste if (!s->pseudo) 543a85fe12eSEd Maste nsecs++; 544a85fe12eSEd Maste } 545a85fe12eSEd Maste /* Remember there is always a null section, so we +1 here. */ 546a85fe12eSEd Maste shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 547a85fe12eSEd Maste if (shtab->sz == 0) 548a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 549a85fe12eSEd Maste shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 550a85fe12eSEd Maste shtab->loadable = 0; 551a85fe12eSEd Maste shtab->pseudo = 1; 552a85fe12eSEd Maste insert_to_sec_list(ecp, shtab, tail); 553a85fe12eSEd Maste 554a85fe12eSEd Maste return (shtab); 555a85fe12eSEd Maste } 556a85fe12eSEd Maste 557a85fe12eSEd Maste void 558a85fe12eSEd Maste copy_content(struct elfcopy *ecp) 559a85fe12eSEd Maste { 560a85fe12eSEd Maste struct section *s; 561a85fe12eSEd Maste 562a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 563a85fe12eSEd Maste /* Skip pseudo section. */ 564a85fe12eSEd Maste if (s->pseudo) 565a85fe12eSEd Maste continue; 566a85fe12eSEd Maste 567a85fe12eSEd Maste /* Skip special sections. */ 568a85fe12eSEd Maste if (strcmp(s->name, ".symtab") == 0 || 569a85fe12eSEd Maste strcmp(s->name, ".strtab") == 0 || 570a85fe12eSEd Maste strcmp(s->name, ".shstrtab") == 0) 571a85fe12eSEd Maste continue; 572a85fe12eSEd Maste 573a85fe12eSEd Maste /* 574aee4c74cSEd Maste * If strip action is STRIP_ALL, relocation info need 575aee4c74cSEd Maste * to be stripped. Skip filtering otherwisw. 576aee4c74cSEd Maste */ 577aee4c74cSEd Maste if (ecp->strip == STRIP_ALL && 578aee4c74cSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 579aee4c74cSEd Maste filter_reloc(ecp, s); 580aee4c74cSEd Maste 581aee4c74cSEd Maste /* 5823ef90571SEd Maste * The section indices in the SHT_GROUP section needs 5833ef90571SEd Maste * to be updated since we might have stripped some 5843ef90571SEd Maste * sections and changed section numbering. 5853ef90571SEd Maste */ 5863ef90571SEd Maste if (s->type == SHT_GROUP) 5873ef90571SEd Maste update_section_group(ecp, s); 5883ef90571SEd Maste 589a85fe12eSEd Maste if (is_modify_section(ecp, s->name)) 590a85fe12eSEd Maste modify_section(ecp, s); 591a85fe12eSEd Maste 592a85fe12eSEd Maste copy_data(s); 593a85fe12eSEd Maste 594a85fe12eSEd Maste /* 595a85fe12eSEd Maste * If symbol table is modified, relocation info might 596a85fe12eSEd Maste * need update, as symbol index may have changed. 597a85fe12eSEd Maste */ 598a85fe12eSEd Maste if ((ecp->flags & SYMTAB_INTACT) == 0 && 599a85fe12eSEd Maste (ecp->flags & SYMTAB_EXIST) && 600a85fe12eSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 601a85fe12eSEd Maste update_reloc(ecp, s); 602a85fe12eSEd Maste 603a85fe12eSEd Maste if (is_print_section(ecp, s->name)) 604a85fe12eSEd Maste print_section(s); 605a85fe12eSEd Maste } 606a85fe12eSEd Maste } 607a85fe12eSEd Maste 6083ef90571SEd Maste 6093ef90571SEd Maste /* 6103ef90571SEd Maste * Update section group section. The section indices in the SHT_GROUP 6113ef90571SEd Maste * section need update after section numbering changed. 6123ef90571SEd Maste */ 6133ef90571SEd Maste static void 6143ef90571SEd Maste update_section_group(struct elfcopy *ecp, struct section *s) 6153ef90571SEd Maste { 6163ef90571SEd Maste GElf_Shdr ish; 6173ef90571SEd Maste Elf_Data *id; 6183ef90571SEd Maste uint32_t *ws, *wd; 6193ef90571SEd Maste uint64_t n; 6203ef90571SEd Maste size_t ishnum; 6213ef90571SEd Maste int i, j; 6223ef90571SEd Maste 6233ef90571SEd Maste if (!elf_getshnum(ecp->ein, &ishnum)) 6243ef90571SEd Maste errx(EXIT_FAILURE, "elf_getshnum failed: %s", 6253ef90571SEd Maste elf_errmsg(-1)); 6263ef90571SEd Maste 6273ef90571SEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 6283ef90571SEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 6293ef90571SEd Maste elf_errmsg(-1)); 6303ef90571SEd Maste 6313ef90571SEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) 6323ef90571SEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 6333ef90571SEd Maste elf_errmsg(-1)); 6343ef90571SEd Maste 6353ef90571SEd Maste if (ish.sh_size == 0) 6363ef90571SEd Maste return; 6373ef90571SEd Maste 6383ef90571SEd Maste if (ish.sh_entsize == 0) 6393ef90571SEd Maste ish.sh_entsize = 4; 6403ef90571SEd Maste 6413ef90571SEd Maste ws = id->d_buf; 6423ef90571SEd Maste 6433ef90571SEd Maste /* We only support COMDAT section. */ 6443ef90571SEd Maste #ifndef GRP_COMDAT 6453ef90571SEd Maste #define GRP_COMDAT 0x1 6463ef90571SEd Maste #endif 6473ef90571SEd Maste if ((*ws & GRP_COMDAT) == 0) 6483ef90571SEd Maste return; 6493ef90571SEd Maste 6503ef90571SEd Maste if ((s->buf = malloc(ish.sh_size)) == NULL) 6513ef90571SEd Maste err(EXIT_FAILURE, "malloc failed"); 6523ef90571SEd Maste 6533ef90571SEd Maste s->sz = ish.sh_size; 6543ef90571SEd Maste 6553ef90571SEd Maste wd = s->buf; 6563ef90571SEd Maste 6573ef90571SEd Maste /* Copy the flag word as-is. */ 6583ef90571SEd Maste *wd = *ws; 6593ef90571SEd Maste 6603ef90571SEd Maste /* Update the section indices. */ 6613ef90571SEd Maste n = ish.sh_size / ish.sh_entsize; 6623ef90571SEd Maste for(i = 1, j = 1; (uint64_t)i < n; i++) { 6633ef90571SEd Maste if (ws[i] != SHN_UNDEF && ws[i] < ishnum && 6643ef90571SEd Maste ecp->secndx[ws[i]] != 0) 6653ef90571SEd Maste wd[j++] = ecp->secndx[ws[i]]; 6663ef90571SEd Maste else 6673ef90571SEd Maste s->sz -= 4; 6683ef90571SEd Maste } 6693ef90571SEd Maste 6703ef90571SEd Maste s->nocopy = 1; 6713ef90571SEd Maste } 6723ef90571SEd Maste 673aee4c74cSEd Maste /* 674aee4c74cSEd Maste * Filter relocation entries, only keep those entries whose 675aee4c74cSEd Maste * symbol is in the keep list. 676aee4c74cSEd Maste */ 677aee4c74cSEd Maste static void 678aee4c74cSEd Maste filter_reloc(struct elfcopy *ecp, struct section *s) 679aee4c74cSEd Maste { 680aee4c74cSEd Maste const char *name; 681aee4c74cSEd Maste GElf_Shdr ish; 682aee4c74cSEd Maste GElf_Rel rel; 683aee4c74cSEd Maste GElf_Rela rela; 684aee4c74cSEd Maste Elf32_Rel *rel32; 685aee4c74cSEd Maste Elf64_Rel *rel64; 686aee4c74cSEd Maste Elf32_Rela *rela32; 687aee4c74cSEd Maste Elf64_Rela *rela64; 688aee4c74cSEd Maste Elf_Data *id; 689aee4c74cSEd Maste uint64_t cap, n, nrels, sym; 690aee4c74cSEd Maste int elferr, i; 691aee4c74cSEd Maste 692aee4c74cSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 693aee4c74cSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 694aee4c74cSEd Maste elf_errmsg(-1)); 695aee4c74cSEd Maste 696aee4c74cSEd Maste /* We don't want to touch relocation info for dynamic symbols. */ 697aee4c74cSEd Maste if ((ecp->flags & SYMTAB_EXIST) == 0) { 698aee4c74cSEd Maste /* 699aee4c74cSEd Maste * No symbol table in output. If sh_link points to a section 700aee4c74cSEd Maste * that exists in the output object, this relocation section 701aee4c74cSEd Maste * is for dynamic symbols. Don't touch it. 702aee4c74cSEd Maste */ 703aee4c74cSEd Maste if (ish.sh_link != 0 && ecp->secndx[ish.sh_link] != 0) 704aee4c74cSEd Maste return; 705aee4c74cSEd Maste } else { 706aee4c74cSEd Maste /* Symbol table exist, check if index equals. */ 707aee4c74cSEd Maste if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 708aee4c74cSEd Maste return; 709aee4c74cSEd Maste } 710aee4c74cSEd Maste 711aee4c74cSEd Maste #define COPYREL(REL, SZ) do { \ 712aee4c74cSEd Maste if (nrels == 0) { \ 713aee4c74cSEd Maste if ((REL##SZ = malloc(cap * \ 714aee4c74cSEd Maste sizeof(*REL##SZ))) == NULL) \ 715aee4c74cSEd Maste err(EXIT_FAILURE, "malloc failed"); \ 716aee4c74cSEd Maste } \ 717aee4c74cSEd Maste if (nrels >= cap) { \ 718aee4c74cSEd Maste cap *= 2; \ 719aee4c74cSEd Maste if ((REL##SZ = realloc(REL##SZ, cap * \ 720aee4c74cSEd Maste sizeof(*REL##SZ))) == NULL) \ 721aee4c74cSEd Maste err(EXIT_FAILURE, "realloc failed"); \ 722aee4c74cSEd Maste } \ 723aee4c74cSEd Maste REL##SZ[nrels].r_offset = REL.r_offset; \ 724aee4c74cSEd Maste REL##SZ[nrels].r_info = REL.r_info; \ 725aee4c74cSEd Maste if (s->type == SHT_RELA) \ 726aee4c74cSEd Maste rela##SZ[nrels].r_addend = rela.r_addend; \ 727aee4c74cSEd Maste nrels++; \ 728aee4c74cSEd Maste } while (0) 729aee4c74cSEd Maste 730aee4c74cSEd Maste nrels = 0; 731aee4c74cSEd Maste cap = 4; /* keep list is usually small. */ 732aee4c74cSEd Maste rel32 = NULL; 733aee4c74cSEd Maste rel64 = NULL; 734aee4c74cSEd Maste rela32 = NULL; 735aee4c74cSEd Maste rela64 = NULL; 736aee4c74cSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) 737aee4c74cSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 738aee4c74cSEd Maste elf_errmsg(-1)); 739aee4c74cSEd Maste n = ish.sh_size / ish.sh_entsize; 740aee4c74cSEd Maste for(i = 0; (uint64_t)i < n; i++) { 741aee4c74cSEd Maste if (s->type == SHT_REL) { 742aee4c74cSEd Maste if (gelf_getrel(id, i, &rel) != &rel) 743aee4c74cSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 744aee4c74cSEd Maste elf_errmsg(-1)); 745aee4c74cSEd Maste sym = GELF_R_SYM(rel.r_info); 746aee4c74cSEd Maste } else { 747aee4c74cSEd Maste if (gelf_getrela(id, i, &rela) != &rela) 748aee4c74cSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 749aee4c74cSEd Maste elf_errmsg(-1)); 750aee4c74cSEd Maste sym = GELF_R_SYM(rela.r_info); 751aee4c74cSEd Maste } 752aee4c74cSEd Maste /* 753aee4c74cSEd Maste * If a relocation references a symbol and we are omitting 754aee4c74cSEd Maste * either that symbol or the entire symbol table we cannot 755aee4c74cSEd Maste * produce valid output, and so just omit the relocation. 756aee4c74cSEd Maste * Broken output like this is generally not useful, but some 757aee4c74cSEd Maste * uses of elfcopy/strip rely on it - for example, GCC's build 758aee4c74cSEd Maste * process uses it to check for build reproducibility by 759aee4c74cSEd Maste * stripping objects and comparing them. 760aee4c74cSEd Maste * 761aee4c74cSEd Maste * Relocations that do not reference a symbol are retained. 762aee4c74cSEd Maste */ 763aee4c74cSEd Maste if (sym != 0) { 764aee4c74cSEd Maste if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) 765aee4c74cSEd Maste continue; 766aee4c74cSEd Maste name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 767aee4c74cSEd Maste sym); 768aee4c74cSEd Maste if (name == NULL) 769aee4c74cSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 770aee4c74cSEd Maste elf_errmsg(-1)); 771aee4c74cSEd Maste if (lookup_symop_list(ecp, name, SYMOP_KEEP) == NULL) 772aee4c74cSEd Maste continue; 773aee4c74cSEd Maste } 774aee4c74cSEd Maste if (ecp->oec == ELFCLASS32) { 775aee4c74cSEd Maste if (s->type == SHT_REL) 776aee4c74cSEd Maste COPYREL(rel, 32); 777aee4c74cSEd Maste else 778aee4c74cSEd Maste COPYREL(rela, 32); 779aee4c74cSEd Maste } else { 780aee4c74cSEd Maste if (s->type == SHT_REL) 781aee4c74cSEd Maste COPYREL(rel, 64); 782aee4c74cSEd Maste else 783aee4c74cSEd Maste COPYREL(rela, 64); 784aee4c74cSEd Maste } 785aee4c74cSEd Maste } 786aee4c74cSEd Maste elferr = elf_errno(); 787aee4c74cSEd Maste if (elferr != 0) 788aee4c74cSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 789aee4c74cSEd Maste elf_errmsg(elferr)); 790aee4c74cSEd Maste 791aee4c74cSEd Maste if (ecp->oec == ELFCLASS32) { 792aee4c74cSEd Maste if (s->type == SHT_REL) 793aee4c74cSEd Maste s->buf = rel32; 794aee4c74cSEd Maste else 795aee4c74cSEd Maste s->buf = rela32; 796aee4c74cSEd Maste } else { 797aee4c74cSEd Maste if (s->type == SHT_REL) 798aee4c74cSEd Maste s->buf = rel64; 799aee4c74cSEd Maste else 800aee4c74cSEd Maste s->buf = rela64; 801aee4c74cSEd Maste } 802aee4c74cSEd Maste s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 803aee4c74cSEd Maste ELF_T_RELA), nrels, EV_CURRENT); 804aee4c74cSEd Maste s->nocopy = 1; 805aee4c74cSEd Maste } 806aee4c74cSEd Maste 807a85fe12eSEd Maste static void 808a85fe12eSEd Maste update_reloc(struct elfcopy *ecp, struct section *s) 809a85fe12eSEd Maste { 810a85fe12eSEd Maste GElf_Shdr osh; 811a85fe12eSEd Maste GElf_Rel rel; 812a85fe12eSEd Maste GElf_Rela rela; 813a85fe12eSEd Maste Elf_Data *od; 814a85fe12eSEd Maste uint64_t n; 815a85fe12eSEd Maste int i; 816a85fe12eSEd Maste 817a85fe12eSEd Maste #define UPDATEREL(REL) do { \ 818a85fe12eSEd Maste if (gelf_get##REL(od, i, &REL) != &REL) \ 819a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 820a85fe12eSEd Maste elf_errmsg(-1)); \ 821a85fe12eSEd Maste REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 822a85fe12eSEd Maste GELF_R_TYPE(REL.r_info)); \ 823a85fe12eSEd Maste if (!gelf_update_##REL(od, i, &REL)) \ 824a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 825a85fe12eSEd Maste elf_errmsg(-1)); \ 826a85fe12eSEd Maste } while(0) 827a85fe12eSEd Maste 828a85fe12eSEd Maste if (s->sz == 0) 829a85fe12eSEd Maste return; 830a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 831a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 832a85fe12eSEd Maste elf_errmsg(-1)); 833a85fe12eSEd Maste /* Only process .symtab reloc info. */ 834a85fe12eSEd Maste if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 835a85fe12eSEd Maste return; 836a85fe12eSEd Maste if ((od = elf_getdata(s->os, NULL)) == NULL) 837a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 838a85fe12eSEd Maste elf_errmsg(-1)); 839a85fe12eSEd Maste n = osh.sh_size / osh.sh_entsize; 840a85fe12eSEd Maste for(i = 0; (uint64_t)i < n; i++) { 841a85fe12eSEd Maste if (s->type == SHT_REL) 842a85fe12eSEd Maste UPDATEREL(rel); 843a85fe12eSEd Maste else 844a85fe12eSEd Maste UPDATEREL(rela); 845a85fe12eSEd Maste } 846a85fe12eSEd Maste } 847a85fe12eSEd Maste 848a85fe12eSEd Maste static void 849a85fe12eSEd Maste pad_section(struct elfcopy *ecp, struct section *s) 850a85fe12eSEd Maste { 851a85fe12eSEd Maste GElf_Shdr osh; 852a85fe12eSEd Maste Elf_Data *od; 853a85fe12eSEd Maste 854a85fe12eSEd Maste if (s == NULL || s->pad_sz == 0) 855a85fe12eSEd Maste return; 856a85fe12eSEd Maste 857a85fe12eSEd Maste if ((s->pad = malloc(s->pad_sz)) == NULL) 858a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 859a85fe12eSEd Maste memset(s->pad, ecp->fill, s->pad_sz); 860a85fe12eSEd Maste 861a85fe12eSEd Maste /* Create a new Elf_Data to contain the padding bytes. */ 862a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 863a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 864a85fe12eSEd Maste elf_errmsg(-1)); 865a85fe12eSEd Maste od->d_align = 1; 866a85fe12eSEd Maste od->d_off = s->sz; 867a85fe12eSEd Maste od->d_buf = s->pad; 868a85fe12eSEd Maste od->d_type = ELF_T_BYTE; 869a85fe12eSEd Maste od->d_size = s->pad_sz; 870a85fe12eSEd Maste od->d_version = EV_CURRENT; 871a85fe12eSEd Maste 872a85fe12eSEd Maste /* Update section header. */ 873a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 874a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 875a85fe12eSEd Maste elf_errmsg(-1)); 876a85fe12eSEd Maste osh.sh_size = s->sz + s->pad_sz; 877a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 878a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 879a85fe12eSEd Maste elf_errmsg(-1)); 880a85fe12eSEd Maste } 881a85fe12eSEd Maste 882a85fe12eSEd Maste void 883a85fe12eSEd Maste resync_sections(struct elfcopy *ecp) 884a85fe12eSEd Maste { 885a85fe12eSEd Maste struct section *s, *ps; 886a85fe12eSEd Maste GElf_Shdr osh; 887a85fe12eSEd Maste uint64_t off; 888a85fe12eSEd Maste int first; 889a85fe12eSEd Maste 890a85fe12eSEd Maste ps = NULL; 891a85fe12eSEd Maste first = 1; 892a85fe12eSEd Maste off = 0; 893a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 894a85fe12eSEd Maste if (first) { 895a85fe12eSEd Maste off = s->off; 896a85fe12eSEd Maste first = 0; 897a85fe12eSEd Maste } 898a85fe12eSEd Maste 8994a85c691SEd Maste /* 9004a85c691SEd Maste * Ignore TLS sections with load address 0 and without 9014a85c691SEd Maste * content. We don't need to adjust their file offset or 9024a85c691SEd Maste * VMA, only the size matters. 9034a85c691SEd Maste */ 9044a85c691SEd Maste if (s->seg_tls != NULL && s->type == SHT_NOBITS && 9054a85c691SEd Maste s->off == 0) 9064a85c691SEd Maste continue; 9074a85c691SEd Maste 908a85fe12eSEd Maste /* Align section offset. */ 9092b39d4f6SEd Maste if (s->align == 0) 9102b39d4f6SEd Maste s->align = 1; 911a85fe12eSEd Maste if (off <= s->off) { 912839529caSEd Maste if (!s->loadable || (ecp->flags & RELOCATABLE)) 913a85fe12eSEd Maste s->off = roundup(off, s->align); 914a85fe12eSEd Maste } else { 915839529caSEd Maste if (s->loadable && (ecp->flags & RELOCATABLE) == 0) 91617eee522SEd Maste warnx("moving loadable section %s, " 91717eee522SEd Maste "is this intentional?", s->name); 918a85fe12eSEd Maste s->off = roundup(off, s->align); 919a85fe12eSEd Maste } 920a85fe12eSEd Maste 921a85fe12eSEd Maste /* Calculate next section offset. */ 922a85fe12eSEd Maste off = s->off; 923a85fe12eSEd Maste if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 924a85fe12eSEd Maste off += s->sz; 925a85fe12eSEd Maste 926a85fe12eSEd Maste if (s->pseudo) { 927a85fe12eSEd Maste ps = NULL; 928a85fe12eSEd Maste continue; 929a85fe12eSEd Maste } 930a85fe12eSEd Maste 931a85fe12eSEd Maste /* Count padding bytes added through --pad-to. */ 932a85fe12eSEd Maste if (s->pad_sz > 0) 933a85fe12eSEd Maste off += s->pad_sz; 934a85fe12eSEd Maste 935a85fe12eSEd Maste /* Update section header accordingly. */ 936a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 937a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 938a85fe12eSEd Maste elf_errmsg(-1)); 939a85fe12eSEd Maste osh.sh_addr = s->vma; 940a85fe12eSEd Maste osh.sh_offset = s->off; 941a85fe12eSEd Maste osh.sh_size = s->sz; 942a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 943a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 944a85fe12eSEd Maste elf_errmsg(-1)); 945a85fe12eSEd Maste 946a85fe12eSEd Maste /* Add padding for previous section, if need. */ 947a85fe12eSEd Maste if (ps != NULL) { 948a85fe12eSEd Maste if (ps->pad_sz > 0) { 949a85fe12eSEd Maste /* Apply padding added by --pad-to. */ 950a85fe12eSEd Maste pad_section(ecp, ps); 951a85fe12eSEd Maste } else if ((ecp->flags & GAP_FILL) && 952a85fe12eSEd Maste (ps->off + ps->sz < s->off)) { 953a85fe12eSEd Maste /* 954a85fe12eSEd Maste * Fill the gap between sections by padding 955a85fe12eSEd Maste * the section with lower address. 956a85fe12eSEd Maste */ 957a85fe12eSEd Maste ps->pad_sz = s->off - (ps->off + ps->sz); 958a85fe12eSEd Maste pad_section(ecp, ps); 959a85fe12eSEd Maste } 960a85fe12eSEd Maste } 961a85fe12eSEd Maste 962a85fe12eSEd Maste ps = s; 963a85fe12eSEd Maste } 964a85fe12eSEd Maste 965a85fe12eSEd Maste /* Pad the last section, if need. */ 966a85fe12eSEd Maste if (ps != NULL && ps->pad_sz > 0) 967a85fe12eSEd Maste pad_section(ecp, ps); 968a85fe12eSEd Maste } 969a85fe12eSEd Maste 970a85fe12eSEd Maste static void 971a85fe12eSEd Maste modify_section(struct elfcopy *ecp, struct section *s) 972a85fe12eSEd Maste { 973a85fe12eSEd Maste struct sec_action *sac; 974a85fe12eSEd Maste size_t srcsz, dstsz, p, len; 975a85fe12eSEd Maste char *b, *c, *d, *src, *end; 976a85fe12eSEd Maste int dupe; 977a85fe12eSEd Maste 978a85fe12eSEd Maste src = read_section(s, &srcsz); 979a85fe12eSEd Maste if (src == NULL || srcsz == 0) { 980a85fe12eSEd Maste /* For empty section, we proceed if we need to append. */ 981a85fe12eSEd Maste if (!is_append_section(ecp, s->name)) 982a85fe12eSEd Maste return; 983a85fe12eSEd Maste } 984a85fe12eSEd Maste 985a85fe12eSEd Maste /* Allocate buffer needed for new section data. */ 986a85fe12eSEd Maste dstsz = srcsz; 987a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 988a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 989a85fe12eSEd Maste dstsz += strlen(sac->string) + 1; 990a85fe12eSEd Maste } 991a85fe12eSEd Maste if ((b = malloc(dstsz)) == NULL) 992a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 993a85fe12eSEd Maste s->buf = b; 994a85fe12eSEd Maste 995a85fe12eSEd Maste /* Compress section. */ 996a85fe12eSEd Maste p = 0; 997a85fe12eSEd Maste if (is_compress_section(ecp, s->name)) { 998a85fe12eSEd Maste end = src + srcsz; 999a85fe12eSEd Maste for(c = src; c < end;) { 1000a85fe12eSEd Maste len = 0; 1001a85fe12eSEd Maste while(c + len < end && c[len] != '\0') 1002a85fe12eSEd Maste len++; 1003a85fe12eSEd Maste if (c + len == end) { 1004a85fe12eSEd Maste /* XXX should we warn here? */ 1005a85fe12eSEd Maste strncpy(&b[p], c, len); 1006a85fe12eSEd Maste p += len; 1007a85fe12eSEd Maste break; 1008a85fe12eSEd Maste } 1009a85fe12eSEd Maste dupe = 0; 1010a85fe12eSEd Maste for (d = b; d < b + p; ) { 1011a85fe12eSEd Maste if (strcmp(d, c) == 0) { 1012a85fe12eSEd Maste dupe = 1; 1013a85fe12eSEd Maste break; 1014a85fe12eSEd Maste } 1015a85fe12eSEd Maste d += strlen(d) + 1; 1016a85fe12eSEd Maste } 1017a85fe12eSEd Maste if (!dupe) { 1018a85fe12eSEd Maste strncpy(&b[p], c, len); 1019a85fe12eSEd Maste b[p + len] = '\0'; 1020a85fe12eSEd Maste p += len + 1; 1021a85fe12eSEd Maste } 1022a85fe12eSEd Maste c += len + 1; 1023a85fe12eSEd Maste } 1024a85fe12eSEd Maste } else { 1025a85fe12eSEd Maste memcpy(b, src, srcsz); 1026a85fe12eSEd Maste p += srcsz; 1027a85fe12eSEd Maste } 1028a85fe12eSEd Maste 1029a85fe12eSEd Maste /* Append section. */ 1030a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 1031a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 1032a85fe12eSEd Maste len = strlen(sac->string); 1033a85fe12eSEd Maste strncpy(&b[p], sac->string, len); 1034a85fe12eSEd Maste b[p + len] = '\0'; 1035a85fe12eSEd Maste p += len + 1; 1036a85fe12eSEd Maste } 1037a85fe12eSEd Maste 1038a85fe12eSEd Maste s->sz = p; 1039a85fe12eSEd Maste s->nocopy = 1; 1040a85fe12eSEd Maste } 1041a85fe12eSEd Maste 1042a85fe12eSEd Maste static void 1043a85fe12eSEd Maste print_data(const char *d, size_t sz) 1044a85fe12eSEd Maste { 1045a85fe12eSEd Maste const char *c; 1046a85fe12eSEd Maste 1047a85fe12eSEd Maste for (c = d; c < d + sz; c++) { 1048a85fe12eSEd Maste if (*c == '\0') 1049a85fe12eSEd Maste putchar('\n'); 1050a85fe12eSEd Maste else 1051a85fe12eSEd Maste putchar(*c); 1052a85fe12eSEd Maste } 1053a85fe12eSEd Maste } 1054a85fe12eSEd Maste 1055a85fe12eSEd Maste static void 1056a85fe12eSEd Maste print_section(struct section *s) 1057a85fe12eSEd Maste { 1058a85fe12eSEd Maste Elf_Data *id; 1059a85fe12eSEd Maste int elferr; 1060a85fe12eSEd Maste 1061a85fe12eSEd Maste if (s->buf != NULL && s->sz > 0) { 1062a85fe12eSEd Maste print_data(s->buf, s->sz); 1063a85fe12eSEd Maste } else { 1064a85fe12eSEd Maste id = NULL; 1065839529caSEd Maste while ((id = elf_getdata(s->is, id)) != NULL || 1066839529caSEd Maste (id = elf_rawdata(s->is, id)) != NULL) { 1067839529caSEd Maste (void) elf_errno(); 1068a85fe12eSEd Maste print_data(id->d_buf, id->d_size); 1069839529caSEd Maste } 1070a85fe12eSEd Maste elferr = elf_errno(); 1071a85fe12eSEd Maste if (elferr != 0) 1072a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1073a85fe12eSEd Maste elf_errmsg(elferr)); 1074a85fe12eSEd Maste } 1075a85fe12eSEd Maste putchar('\n'); 1076a85fe12eSEd Maste } 1077a85fe12eSEd Maste 1078a85fe12eSEd Maste static void * 1079a85fe12eSEd Maste read_section(struct section *s, size_t *size) 1080a85fe12eSEd Maste { 1081a85fe12eSEd Maste Elf_Data *id; 1082a85fe12eSEd Maste char *b; 1083a85fe12eSEd Maste size_t sz; 1084a85fe12eSEd Maste int elferr; 1085a85fe12eSEd Maste 1086a85fe12eSEd Maste sz = 0; 1087a85fe12eSEd Maste b = NULL; 1088a85fe12eSEd Maste id = NULL; 1089839529caSEd Maste while ((id = elf_getdata(s->is, id)) != NULL || 1090839529caSEd Maste (id = elf_rawdata(s->is, id)) != NULL) { 1091839529caSEd Maste (void) elf_errno(); 1092a85fe12eSEd Maste if (b == NULL) 1093a85fe12eSEd Maste b = malloc(id->d_size); 1094a85fe12eSEd Maste else 1095a85fe12eSEd Maste b = malloc(sz + id->d_size); 1096a85fe12eSEd Maste if (b == NULL) 1097a85fe12eSEd Maste err(EXIT_FAILURE, "malloc or realloc failed"); 1098a85fe12eSEd Maste 1099a85fe12eSEd Maste memcpy(&b[sz], id->d_buf, id->d_size); 1100a85fe12eSEd Maste sz += id->d_size; 1101a85fe12eSEd Maste } 1102a85fe12eSEd Maste elferr = elf_errno(); 1103a85fe12eSEd Maste if (elferr != 0) 1104a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1105a85fe12eSEd Maste elf_errmsg(elferr)); 1106a85fe12eSEd Maste 1107a85fe12eSEd Maste *size = sz; 1108a85fe12eSEd Maste 1109a85fe12eSEd Maste return (b); 1110a85fe12eSEd Maste } 1111a85fe12eSEd Maste 1112a85fe12eSEd Maste void 1113a85fe12eSEd Maste copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 1114a85fe12eSEd Maste int sec_flags) 1115a85fe12eSEd Maste { 1116a85fe12eSEd Maste GElf_Shdr ish, osh; 1117a85fe12eSEd Maste 1118a85fe12eSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 1119839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1120a85fe12eSEd Maste elf_errmsg(-1)); 1121a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 1122839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1123a85fe12eSEd Maste elf_errmsg(-1)); 1124a85fe12eSEd Maste 1125a85fe12eSEd Maste if (copy) 1126a85fe12eSEd Maste (void) memcpy(&osh, &ish, sizeof(ish)); 1127a85fe12eSEd Maste else { 1128a85fe12eSEd Maste osh.sh_type = s->type; 1129a85fe12eSEd Maste osh.sh_addr = s->vma; 1130a85fe12eSEd Maste osh.sh_offset = s->off; 1131a85fe12eSEd Maste osh.sh_size = s->sz; 1132a85fe12eSEd Maste osh.sh_link = ish.sh_link; 1133a85fe12eSEd Maste osh.sh_info = ish.sh_info; 1134a85fe12eSEd Maste osh.sh_addralign = s->align; 1135a85fe12eSEd Maste osh.sh_entsize = ish.sh_entsize; 1136a85fe12eSEd Maste 1137a85fe12eSEd Maste if (sec_flags) { 1138a85fe12eSEd Maste osh.sh_flags = 0; 1139839529caSEd Maste if (sec_flags & SF_ALLOC) 1140a85fe12eSEd Maste osh.sh_flags |= SHF_ALLOC; 1141a85fe12eSEd Maste if ((sec_flags & SF_READONLY) == 0) 1142a85fe12eSEd Maste osh.sh_flags |= SHF_WRITE; 1143a85fe12eSEd Maste if (sec_flags & SF_CODE) 1144a85fe12eSEd Maste osh.sh_flags |= SHF_EXECINSTR; 1145839529caSEd Maste if ((sec_flags & SF_CONTENTS) && 1146839529caSEd Maste s->type == SHT_NOBITS && s->sz > 0) { 1147839529caSEd Maste /* 1148839529caSEd Maste * Convert SHT_NOBITS section to section with 1149839529caSEd Maste * (zero'ed) content on file. 1150839529caSEd Maste */ 1151839529caSEd Maste osh.sh_type = s->type = SHT_PROGBITS; 1152839529caSEd Maste if ((s->buf = calloc(1, s->sz)) == NULL) 1153839529caSEd Maste err(EXIT_FAILURE, "malloc failed"); 1154839529caSEd Maste s->nocopy = 1; 1155839529caSEd Maste } 11563ef90571SEd Maste } else { 1157a85fe12eSEd Maste osh.sh_flags = ish.sh_flags; 1158839529caSEd Maste /* 1159839529caSEd Maste * Newer binutils as(1) emits the section flag 1160839529caSEd Maste * SHF_INFO_LINK for relocation sections. elfcopy 1161839529caSEd Maste * emits this flag in the output section if it's 1162839529caSEd Maste * missing in the input section, to remain compatible 1163839529caSEd Maste * with binutils. 1164839529caSEd Maste */ 11653ef90571SEd Maste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 11663ef90571SEd Maste osh.sh_flags |= SHF_INFO_LINK; 11673ef90571SEd Maste } 1168a85fe12eSEd Maste } 1169a85fe12eSEd Maste 1170a85fe12eSEd Maste if (name == NULL) 1171a85fe12eSEd Maste add_to_shstrtab(ecp, s->name); 1172a85fe12eSEd Maste else 1173a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1174a85fe12eSEd Maste 1175a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1176a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1177a85fe12eSEd Maste elf_errmsg(-1)); 1178a85fe12eSEd Maste } 1179a85fe12eSEd Maste 1180a85fe12eSEd Maste void 1181a85fe12eSEd Maste copy_data(struct section *s) 1182a85fe12eSEd Maste { 1183a85fe12eSEd Maste Elf_Data *id, *od; 1184a85fe12eSEd Maste int elferr; 1185a85fe12eSEd Maste 1186a85fe12eSEd Maste if (s->nocopy && s->buf == NULL) 1187a85fe12eSEd Maste return; 1188a85fe12eSEd Maste 1189a85fe12eSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) { 1190839529caSEd Maste (void) elf_errno(); 1191839529caSEd Maste if ((id = elf_rawdata(s->is, NULL)) == NULL) { 1192a85fe12eSEd Maste elferr = elf_errno(); 1193a85fe12eSEd Maste if (elferr != 0) 1194839529caSEd Maste errx(EXIT_FAILURE, "failed to read section:" 1195839529caSEd Maste " %s", s->name); 1196a85fe12eSEd Maste return; 1197a85fe12eSEd Maste } 1198839529caSEd Maste } 1199a85fe12eSEd Maste 1200a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 1201a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1202a85fe12eSEd Maste elf_errmsg(-1)); 1203a85fe12eSEd Maste 1204a85fe12eSEd Maste if (s->nocopy) { 1205a85fe12eSEd Maste /* Use s->buf as content if s->nocopy is set. */ 1206a85fe12eSEd Maste od->d_align = id->d_align; 1207a85fe12eSEd Maste od->d_off = 0; 1208a85fe12eSEd Maste od->d_buf = s->buf; 1209a85fe12eSEd Maste od->d_type = id->d_type; 1210a85fe12eSEd Maste od->d_size = s->sz; 1211a85fe12eSEd Maste od->d_version = id->d_version; 1212a85fe12eSEd Maste } else { 1213a85fe12eSEd Maste od->d_align = id->d_align; 1214a85fe12eSEd Maste od->d_off = id->d_off; 1215a85fe12eSEd Maste od->d_buf = id->d_buf; 1216a85fe12eSEd Maste od->d_type = id->d_type; 1217a85fe12eSEd Maste od->d_size = id->d_size; 1218a85fe12eSEd Maste od->d_version = id->d_version; 1219a85fe12eSEd Maste } 12204a85c691SEd Maste 12214a85c691SEd Maste /* 12224a85c691SEd Maste * Alignment Fixup. libelf does not allow the alignment for 12234a85c691SEd Maste * Elf_Data descriptor to be set to 0. In this case we workaround 12244a85c691SEd Maste * it by setting the alignment to 1. 12254a85c691SEd Maste * 12264a85c691SEd Maste * According to the ELF ABI, alignment 0 and 1 has the same 12274a85c691SEd Maste * meaning: the section has no alignment constraints. 12284a85c691SEd Maste */ 12294a85c691SEd Maste if (od->d_align == 0) 12304a85c691SEd Maste od->d_align = 1; 1231a85fe12eSEd Maste } 1232a85fe12eSEd Maste 1233a85fe12eSEd Maste struct section * 1234a85fe12eSEd Maste create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1235a85fe12eSEd Maste void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1236a85fe12eSEd Maste uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1237a85fe12eSEd Maste { 1238a85fe12eSEd Maste struct section *s; 1239a85fe12eSEd Maste Elf_Scn *os; 1240a85fe12eSEd Maste Elf_Data *od; 1241a85fe12eSEd Maste GElf_Shdr osh; 1242a85fe12eSEd Maste 1243a85fe12eSEd Maste if ((os = elf_newscn(ecp->eout)) == NULL) 1244a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1245a85fe12eSEd Maste elf_errmsg(-1)); 1246a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 1247a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1248a85fe12eSEd Maste s->name = name; 1249a85fe12eSEd Maste s->newname = newname; /* needs to be free()'ed */ 1250a85fe12eSEd Maste s->off = off; 1251a85fe12eSEd Maste s->sz = size; 1252a85fe12eSEd Maste s->vma = vma; 1253a85fe12eSEd Maste s->align = align; 1254a85fe12eSEd Maste s->loadable = loadable; 1255a85fe12eSEd Maste s->is = NULL; 1256a85fe12eSEd Maste s->os = os; 1257a85fe12eSEd Maste s->type = stype; 1258a85fe12eSEd Maste s->nocopy = 1; 1259a85fe12eSEd Maste insert_to_sec_list(ecp, s, 1); 1260a85fe12eSEd Maste 1261a85fe12eSEd Maste if (gelf_getshdr(os, &osh) == NULL) 1262a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1263a85fe12eSEd Maste elf_errmsg(-1)); 1264a85fe12eSEd Maste osh.sh_flags = flags; 1265a85fe12eSEd Maste osh.sh_type = s->type; 1266a85fe12eSEd Maste osh.sh_addr = s->vma; 1267a85fe12eSEd Maste osh.sh_addralign = s->align; 1268a85fe12eSEd Maste if (!gelf_update_shdr(os, &osh)) 1269a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1270a85fe12eSEd Maste elf_errmsg(-1)); 1271a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1272a85fe12eSEd Maste 1273a85fe12eSEd Maste if (buf != NULL && size != 0) { 1274a85fe12eSEd Maste if ((od = elf_newdata(os)) == NULL) 1275a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1276a85fe12eSEd Maste elf_errmsg(-1)); 1277a85fe12eSEd Maste od->d_align = align; 1278a85fe12eSEd Maste od->d_off = 0; 1279a85fe12eSEd Maste od->d_buf = buf; 1280a85fe12eSEd Maste od->d_size = size; 1281a85fe12eSEd Maste od->d_type = dtype; 1282a85fe12eSEd Maste od->d_version = EV_CURRENT; 1283a85fe12eSEd Maste } 1284a85fe12eSEd Maste 1285a85fe12eSEd Maste /* 1286a85fe12eSEd Maste * Clear SYMTAB_INTACT, as we probably need to update/add new 1287a85fe12eSEd Maste * STT_SECTION symbols into the symbol table. 1288a85fe12eSEd Maste */ 1289a85fe12eSEd Maste ecp->flags &= ~SYMTAB_INTACT; 1290a85fe12eSEd Maste 1291a85fe12eSEd Maste return (s); 1292a85fe12eSEd Maste } 1293a85fe12eSEd Maste 1294a85fe12eSEd Maste /* 1295a85fe12eSEd Maste * Insert sections specified by --add-section to the end of section list. 1296a85fe12eSEd Maste */ 1297a85fe12eSEd Maste static void 1298a85fe12eSEd Maste insert_sections(struct elfcopy *ecp) 1299a85fe12eSEd Maste { 1300a85fe12eSEd Maste struct sec_add *sa; 1301a85fe12eSEd Maste struct section *s; 1302a85fe12eSEd Maste size_t off; 1303839529caSEd Maste uint64_t stype; 1304a85fe12eSEd Maste 1305a85fe12eSEd Maste /* Put these sections in the end of current list. */ 1306a85fe12eSEd Maste off = 0; 1307a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1308a85fe12eSEd Maste if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1309a85fe12eSEd Maste off = s->off + s->sz; 1310a85fe12eSEd Maste else 1311a85fe12eSEd Maste off = s->off; 1312a85fe12eSEd Maste } 1313a85fe12eSEd Maste 1314a85fe12eSEd Maste STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1315a85fe12eSEd Maste 1316a85fe12eSEd Maste /* TODO: Add section header vma/lma, flag changes here */ 1317a85fe12eSEd Maste 1318839529caSEd Maste /* 1319839529caSEd Maste * The default section type for user added section is 1320839529caSEd Maste * SHT_PROGBITS. If the section name match certain patterns, 1321839529caSEd Maste * elfcopy will try to set a more appropriate section type. 1322839529caSEd Maste * However, data type is always set to ELF_T_BYTE and no 1323839529caSEd Maste * translation is performed by libelf. 1324839529caSEd Maste */ 1325839529caSEd Maste stype = SHT_PROGBITS; 1326839529caSEd Maste if (strcmp(sa->name, ".note") == 0 || 1327839529caSEd Maste strncmp(sa->name, ".note.", strlen(".note.")) == 0) 1328839529caSEd Maste stype = SHT_NOTE; 1329839529caSEd Maste 1330a85fe12eSEd Maste (void) create_external_section(ecp, sa->name, NULL, sa->content, 1331839529caSEd Maste sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0); 1332a85fe12eSEd Maste } 1333a85fe12eSEd Maste } 1334a85fe12eSEd Maste 1335a85fe12eSEd Maste void 1336a85fe12eSEd Maste add_to_shstrtab(struct elfcopy *ecp, const char *name) 1337a85fe12eSEd Maste { 1338a85fe12eSEd Maste 1339*bc589b72SMark Johnston if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0) 1340*bc589b72SMark Johnston errx(EXIT_FAILURE, "elftc_string_table_insert failed"); 1341a85fe12eSEd Maste } 1342a85fe12eSEd Maste 1343a85fe12eSEd Maste void 1344a85fe12eSEd Maste update_shdr(struct elfcopy *ecp, int update_link) 1345a85fe12eSEd Maste { 1346a85fe12eSEd Maste struct section *s; 1347a85fe12eSEd Maste GElf_Shdr osh; 1348a85fe12eSEd Maste int elferr; 1349a85fe12eSEd Maste 1350*bc589b72SMark Johnston /* Finalize the section name string table (.shstrtab). */ 1351*bc589b72SMark Johnston set_shstrtab(ecp); 1352*bc589b72SMark Johnston 1353a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1354a85fe12eSEd Maste if (s->pseudo) 1355a85fe12eSEd Maste continue; 1356a85fe12eSEd Maste 1357a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 1358839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 1359a85fe12eSEd Maste elf_errmsg(-1)); 1360a85fe12eSEd Maste 1361a85fe12eSEd Maste /* Find section name in string table and set sh_name. */ 1362*bc589b72SMark Johnston osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab, 1363*bc589b72SMark Johnston s->name); 1364a85fe12eSEd Maste 1365a85fe12eSEd Maste /* 1366a85fe12eSEd Maste * sh_link needs to be updated, since the index of the 1367a85fe12eSEd Maste * linked section might have changed. 1368a85fe12eSEd Maste */ 1369a85fe12eSEd Maste if (update_link && osh.sh_link != 0) 1370a85fe12eSEd Maste osh.sh_link = ecp->secndx[osh.sh_link]; 1371a85fe12eSEd Maste 1372a85fe12eSEd Maste /* 1373a85fe12eSEd Maste * sh_info of relocation section links to the section to which 1374a85fe12eSEd Maste * its relocation info applies. So it may need update as well. 1375a85fe12eSEd Maste */ 1376a85fe12eSEd Maste if ((s->type == SHT_REL || s->type == SHT_RELA) && 1377a85fe12eSEd Maste osh.sh_info != 0) 1378a85fe12eSEd Maste osh.sh_info = ecp->secndx[osh.sh_info]; 1379a85fe12eSEd Maste 1380b00fe64fSEd Maste /* 1381b00fe64fSEd Maste * sh_info of SHT_GROUP section needs to point to the correct 1382b00fe64fSEd Maste * string in the symbol table. 1383b00fe64fSEd Maste */ 1384b00fe64fSEd Maste if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) && 1385b00fe64fSEd Maste (ecp->flags & SYMTAB_INTACT) == 0) 1386b00fe64fSEd Maste osh.sh_info = ecp->symndx[osh.sh_info]; 1387b00fe64fSEd Maste 1388a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1389a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1390a85fe12eSEd Maste elf_errmsg(-1)); 1391a85fe12eSEd Maste } 1392a85fe12eSEd Maste elferr = elf_errno(); 1393a85fe12eSEd Maste if (elferr != 0) 1394a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1395a85fe12eSEd Maste elf_errmsg(elferr)); 1396a85fe12eSEd Maste } 1397a85fe12eSEd Maste 1398a85fe12eSEd Maste void 1399a85fe12eSEd Maste init_shstrtab(struct elfcopy *ecp) 1400a85fe12eSEd Maste { 1401a85fe12eSEd Maste struct section *s; 1402a85fe12eSEd Maste 1403a85fe12eSEd Maste if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1404a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1405a85fe12eSEd Maste s = ecp->shstrtab; 1406a85fe12eSEd Maste s->name = ".shstrtab"; 1407a85fe12eSEd Maste s->is = NULL; 1408a85fe12eSEd Maste s->sz = 0; 1409a85fe12eSEd Maste s->align = 1; 1410a85fe12eSEd Maste s->loadable = 0; 1411a85fe12eSEd Maste s->type = SHT_STRTAB; 1412a85fe12eSEd Maste s->vma = 0; 1413*bc589b72SMark Johnston s->strtab = elftc_string_table_create(0); 14149ef62fdbSEd Maste 1415*bc589b72SMark Johnston add_to_shstrtab(ecp, ""); 1416*bc589b72SMark Johnston add_to_shstrtab(ecp, ".symtab"); 1417*bc589b72SMark Johnston add_to_shstrtab(ecp, ".strtab"); 1418*bc589b72SMark Johnston add_to_shstrtab(ecp, ".shstrtab"); 1419a85fe12eSEd Maste } 1420a85fe12eSEd Maste 1421*bc589b72SMark Johnston static void 1422a85fe12eSEd Maste set_shstrtab(struct elfcopy *ecp) 1423a85fe12eSEd Maste { 1424a85fe12eSEd Maste struct section *s; 1425a85fe12eSEd Maste Elf_Data *data; 1426a85fe12eSEd Maste GElf_Shdr sh; 1427*bc589b72SMark Johnston const char *image; 1428*bc589b72SMark Johnston size_t sz; 1429a85fe12eSEd Maste 1430a85fe12eSEd Maste s = ecp->shstrtab; 1431a85fe12eSEd Maste 1432619ba3b4SEd Maste if (s->os == NULL) { 1433619ba3b4SEd Maste /* Input object does not contain .shstrtab section */ 1434619ba3b4SEd Maste if ((s->os = elf_newscn(ecp->eout)) == NULL) 1435619ba3b4SEd Maste errx(EXIT_FAILURE, "elf_newscn failed: %s", 1436619ba3b4SEd Maste elf_errmsg(-1)); 1437619ba3b4SEd Maste insert_to_sec_list(ecp, s, 1); 1438619ba3b4SEd Maste } 1439619ba3b4SEd Maste 1440a85fe12eSEd Maste if (gelf_getshdr(s->os, &sh) == NULL) 1441839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1442a85fe12eSEd Maste elf_errmsg(-1)); 1443a85fe12eSEd Maste sh.sh_addr = 0; 1444a85fe12eSEd Maste sh.sh_addralign = 1; 1445a85fe12eSEd Maste sh.sh_offset = s->off; 1446a85fe12eSEd Maste sh.sh_type = SHT_STRTAB; 1447a85fe12eSEd Maste sh.sh_flags = 0; 1448a85fe12eSEd Maste sh.sh_entsize = 0; 1449a85fe12eSEd Maste sh.sh_info = 0; 1450a85fe12eSEd Maste sh.sh_link = 0; 1451a85fe12eSEd Maste 1452a85fe12eSEd Maste if ((data = elf_newdata(s->os)) == NULL) 1453a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1454a85fe12eSEd Maste elf_errmsg(-1)); 1455a85fe12eSEd Maste 1456a85fe12eSEd Maste /* 1457a85fe12eSEd Maste * If we don't have a symbol table, skip those a few bytes 1458a85fe12eSEd Maste * which are reserved for this in the beginning of shstrtab. 1459a85fe12eSEd Maste */ 1460a85fe12eSEd Maste if (!(ecp->flags & SYMTAB_EXIST)) { 1461*bc589b72SMark Johnston elftc_string_table_remove(s->strtab, ".symtab"); 1462*bc589b72SMark Johnston elftc_string_table_remove(s->strtab, ".strtab"); 1463a85fe12eSEd Maste } 1464a85fe12eSEd Maste 1465*bc589b72SMark Johnston image = elftc_string_table_image(s->strtab, &sz); 1466*bc589b72SMark Johnston s->sz = sz; 1467*bc589b72SMark Johnston 1468*bc589b72SMark Johnston sh.sh_size = sz; 1469a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &sh)) 1470a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1471a85fe12eSEd Maste elf_errmsg(-1)); 1472a85fe12eSEd Maste 1473a85fe12eSEd Maste data->d_align = 1; 1474*bc589b72SMark Johnston data->d_buf = (void *)(uintptr_t)image; 1475*bc589b72SMark Johnston data->d_size = sz; 1476a85fe12eSEd Maste data->d_off = 0; 1477a85fe12eSEd Maste data->d_type = ELF_T_BYTE; 1478a85fe12eSEd Maste data->d_version = EV_CURRENT; 1479a85fe12eSEd Maste 1480a85fe12eSEd Maste if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1481a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1482a85fe12eSEd Maste elf_errmsg(-1)); 1483a85fe12eSEd Maste } 1484a85fe12eSEd Maste 1485a85fe12eSEd Maste void 1486a85fe12eSEd Maste add_section(struct elfcopy *ecp, const char *arg) 1487a85fe12eSEd Maste { 1488a85fe12eSEd Maste struct sec_add *sa; 1489a85fe12eSEd Maste struct stat sb; 1490a85fe12eSEd Maste const char *s, *fn; 1491a85fe12eSEd Maste FILE *fp; 1492a85fe12eSEd Maste int len; 1493a85fe12eSEd Maste 1494a85fe12eSEd Maste if ((s = strchr(arg, '=')) == NULL) 1495a85fe12eSEd Maste errx(EXIT_FAILURE, 1496a85fe12eSEd Maste "illegal format for --add-section option"); 1497a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1498a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1499a85fe12eSEd Maste 1500a85fe12eSEd Maste len = s - arg; 1501a85fe12eSEd Maste if ((sa->name = malloc(len + 1)) == NULL) 1502a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1503a85fe12eSEd Maste strncpy(sa->name, arg, len); 1504a85fe12eSEd Maste sa->name[len] = '\0'; 1505a85fe12eSEd Maste 1506a85fe12eSEd Maste fn = s + 1; 1507a85fe12eSEd Maste if (stat(fn, &sb) == -1) 1508a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1509a85fe12eSEd Maste sa->size = sb.st_size; 1510839529caSEd Maste if (sa->size > 0) { 1511a85fe12eSEd Maste if ((sa->content = malloc(sa->size)) == NULL) 1512a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1513a85fe12eSEd Maste if ((fp = fopen(fn, "r")) == NULL) 1514a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", fn); 1515a85fe12eSEd Maste if (fread(sa->content, 1, sa->size, fp) == 0 || 1516a85fe12eSEd Maste ferror(fp)) 1517a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1518a85fe12eSEd Maste fclose(fp); 1519839529caSEd Maste } else 1520839529caSEd Maste sa->content = NULL; 1521a85fe12eSEd Maste 1522a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1523a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1524a85fe12eSEd Maste } 1525a85fe12eSEd Maste 1526a85fe12eSEd Maste void 1527a85fe12eSEd Maste free_sec_add(struct elfcopy *ecp) 1528a85fe12eSEd Maste { 1529a85fe12eSEd Maste struct sec_add *sa, *sa_temp; 1530a85fe12eSEd Maste 1531a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1532a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1533a85fe12eSEd Maste free(sa->name); 1534a85fe12eSEd Maste free(sa->content); 1535a85fe12eSEd Maste free(sa); 1536a85fe12eSEd Maste } 1537a85fe12eSEd Maste } 1538a85fe12eSEd Maste 1539a85fe12eSEd Maste static void 1540a85fe12eSEd Maste add_gnu_debuglink(struct elfcopy *ecp) 1541a85fe12eSEd Maste { 1542a85fe12eSEd Maste struct sec_add *sa; 1543a85fe12eSEd Maste struct stat sb; 1544a85fe12eSEd Maste FILE *fp; 1545a85fe12eSEd Maste char *fnbase, *buf; 1546a85fe12eSEd Maste int crc_off; 1547a85fe12eSEd Maste int crc; 1548a85fe12eSEd Maste 1549a85fe12eSEd Maste if (ecp->debuglink == NULL) 1550a85fe12eSEd Maste return; 1551a85fe12eSEd Maste 1552a85fe12eSEd Maste /* Read debug file content. */ 1553a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1554a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1555a85fe12eSEd Maste if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1556a85fe12eSEd Maste err(EXIT_FAILURE, "strdup failed"); 1557a85fe12eSEd Maste if (stat(ecp->debuglink, &sb) == -1) 1558a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1559f5e9c916SEd Maste if (sb.st_size == 0) 1560f5e9c916SEd Maste errx(EXIT_FAILURE, "empty debug link target %s", 1561f5e9c916SEd Maste ecp->debuglink); 1562a85fe12eSEd Maste if ((buf = malloc(sb.st_size)) == NULL) 1563a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1564a85fe12eSEd Maste if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1565a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1566a85fe12eSEd Maste if (fread(buf, 1, sb.st_size, fp) == 0 || 1567a85fe12eSEd Maste ferror(fp)) 1568a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1569a85fe12eSEd Maste fclose(fp); 1570a85fe12eSEd Maste 1571a85fe12eSEd Maste /* Calculate crc checksum. */ 1572a85fe12eSEd Maste crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1573a85fe12eSEd Maste free(buf); 1574a85fe12eSEd Maste 1575a85fe12eSEd Maste /* Calculate section size and the offset to store crc checksum. */ 1576a85fe12eSEd Maste if ((fnbase = basename(ecp->debuglink)) == NULL) 1577a85fe12eSEd Maste err(EXIT_FAILURE, "basename failed"); 1578a85fe12eSEd Maste crc_off = roundup(strlen(fnbase) + 1, 4); 1579a85fe12eSEd Maste sa->size = crc_off + 4; 1580a85fe12eSEd Maste 1581a85fe12eSEd Maste /* Section content. */ 1582a85fe12eSEd Maste if ((sa->content = calloc(1, sa->size)) == NULL) 1583a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1584a85fe12eSEd Maste strncpy(sa->content, fnbase, strlen(fnbase)); 1585a85fe12eSEd Maste if (ecp->oed == ELFDATA2LSB) { 1586a85fe12eSEd Maste sa->content[crc_off] = crc & 0xFF; 1587a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1588a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1589a85fe12eSEd Maste sa->content[crc_off + 3] = crc >> 24; 1590a85fe12eSEd Maste } else { 1591a85fe12eSEd Maste sa->content[crc_off] = crc >> 24; 1592a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1593a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1594a85fe12eSEd Maste sa->content[crc_off + 3] = crc & 0xFF; 1595a85fe12eSEd Maste } 1596a85fe12eSEd Maste 1597a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1598a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1599a85fe12eSEd Maste } 1600a85fe12eSEd Maste 1601a85fe12eSEd Maste static uint32_t crctable[256] = 1602a85fe12eSEd Maste { 1603a85fe12eSEd Maste 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1604a85fe12eSEd Maste 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1605a85fe12eSEd Maste 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1606a85fe12eSEd Maste 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1607a85fe12eSEd Maste 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1608a85fe12eSEd Maste 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1609a85fe12eSEd Maste 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1610a85fe12eSEd Maste 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1611a85fe12eSEd Maste 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1612a85fe12eSEd Maste 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1613a85fe12eSEd Maste 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1614a85fe12eSEd Maste 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1615a85fe12eSEd Maste 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1616a85fe12eSEd Maste 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1617a85fe12eSEd Maste 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1618a85fe12eSEd Maste 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1619a85fe12eSEd Maste 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1620a85fe12eSEd Maste 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1621a85fe12eSEd Maste 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1622a85fe12eSEd Maste 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1623a85fe12eSEd Maste 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1624a85fe12eSEd Maste 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1625a85fe12eSEd Maste 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1626a85fe12eSEd Maste 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1627a85fe12eSEd Maste 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1628a85fe12eSEd Maste 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1629a85fe12eSEd Maste 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1630a85fe12eSEd Maste 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1631a85fe12eSEd Maste 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1632a85fe12eSEd Maste 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1633a85fe12eSEd Maste 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1634a85fe12eSEd Maste 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1635a85fe12eSEd Maste 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1636a85fe12eSEd Maste 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1637a85fe12eSEd Maste 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1638a85fe12eSEd Maste 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1639a85fe12eSEd Maste 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1640a85fe12eSEd Maste 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1641a85fe12eSEd Maste 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1642a85fe12eSEd Maste 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1643a85fe12eSEd Maste 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1644a85fe12eSEd Maste 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1645a85fe12eSEd Maste 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1646a85fe12eSEd Maste 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1647a85fe12eSEd Maste 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1648a85fe12eSEd Maste 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1649a85fe12eSEd Maste 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1650a85fe12eSEd Maste 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1651a85fe12eSEd Maste 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1652a85fe12eSEd Maste 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1653a85fe12eSEd Maste 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1654a85fe12eSEd Maste 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1655a85fe12eSEd Maste 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1656a85fe12eSEd Maste 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1657a85fe12eSEd Maste 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1658a85fe12eSEd Maste 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1659a85fe12eSEd Maste 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1660a85fe12eSEd Maste 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1661a85fe12eSEd Maste 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1662a85fe12eSEd Maste 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1663a85fe12eSEd Maste 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1664a85fe12eSEd Maste 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1665a85fe12eSEd Maste 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1666a85fe12eSEd Maste 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1667a85fe12eSEd Maste }; 1668a85fe12eSEd Maste 1669a85fe12eSEd Maste static uint32_t 1670a85fe12eSEd Maste calc_crc32(const char *p, size_t len, uint32_t crc) 1671a85fe12eSEd Maste { 1672a85fe12eSEd Maste uint32_t i; 1673a85fe12eSEd Maste 1674a85fe12eSEd Maste for (i = 0; i < len; i++) { 1675a85fe12eSEd Maste crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1676a85fe12eSEd Maste } 1677a85fe12eSEd Maste 1678a85fe12eSEd Maste return (crc ^ 0xFFFFFFFF); 1679a85fe12eSEd Maste } 1680