1a85fe12eSEd Maste /*- 2a85fe12eSEd Maste * Copyright (c) 2007-2011 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/cdefs.h> 28a85fe12eSEd Maste #include <sys/param.h> 29a85fe12eSEd Maste #include <sys/stat.h> 30a85fe12eSEd Maste #include <err.h> 31a85fe12eSEd Maste #include <libgen.h> 32a85fe12eSEd Maste #include <stdio.h> 33a85fe12eSEd Maste #include <stdlib.h> 34a85fe12eSEd Maste #include <string.h> 35a85fe12eSEd Maste 36a85fe12eSEd Maste #include "elfcopy.h" 37a85fe12eSEd Maste 38a85fe12eSEd Maste ELFTC_VCSID("$Id: sections.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); 39a85fe12eSEd Maste 40a85fe12eSEd Maste static void add_gnu_debuglink(struct elfcopy *ecp); 41a85fe12eSEd Maste static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); 42a85fe12eSEd Maste static void check_section_rename(struct elfcopy *ecp, struct section *s); 43a85fe12eSEd Maste static void filter_reloc(struct elfcopy *ecp, struct section *s); 44a85fe12eSEd Maste static int get_section_flags(struct elfcopy *ecp, const char *name); 45a85fe12eSEd Maste static void insert_sections(struct elfcopy *ecp); 46a85fe12eSEd Maste static void insert_to_strtab(struct section *t, const char *s); 47a85fe12eSEd Maste static int is_append_section(struct elfcopy *ecp, const char *name); 48a85fe12eSEd Maste static int is_compress_section(struct elfcopy *ecp, const char *name); 49a85fe12eSEd Maste static int is_debug_section(const char *name); 50a85fe12eSEd Maste static int is_modify_section(struct elfcopy *ecp, const char *name); 51a85fe12eSEd Maste static int is_print_section(struct elfcopy *ecp, const char *name); 52a85fe12eSEd Maste static int lookup_string(struct section *t, const char *s); 53a85fe12eSEd Maste static void modify_section(struct elfcopy *ecp, struct section *s); 54a85fe12eSEd Maste static void pad_section(struct elfcopy *ecp, struct section *s); 55a85fe12eSEd Maste static void print_data(const char *d, size_t sz); 56a85fe12eSEd Maste static void print_section(struct section *s); 57a85fe12eSEd Maste static void *read_section(struct section *s, size_t *size); 58a85fe12eSEd Maste static void update_reloc(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 76a85fe12eSEd Maste if (is_debug_section(name)) { 77a85fe12eSEd Maste if (ecp->strip == STRIP_ALL || 78a85fe12eSEd Maste ecp->strip == STRIP_DEBUG || 79a85fe12eSEd Maste ecp->strip == STRIP_UNNEEDED || 80a85fe12eSEd Maste (ecp->flags & DISCARD_LOCAL)) 81a85fe12eSEd Maste return (1); 82a85fe12eSEd Maste if (ecp->strip == STRIP_NONDEBUG) 83a85fe12eSEd Maste return (0); 84a85fe12eSEd Maste } 85a85fe12eSEd Maste 86a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { 87a85fe12eSEd Maste struct sec_action *sac; 88a85fe12eSEd Maste 89a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 90a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) 91a85fe12eSEd Maste return (1); 92a85fe12eSEd Maste if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) 93a85fe12eSEd Maste return (1); 94a85fe12eSEd Maste } 95a85fe12eSEd Maste 96a85fe12eSEd Maste return (0); 97a85fe12eSEd Maste } 98a85fe12eSEd Maste 99a85fe12eSEd Maste /* 100a85fe12eSEd Maste * Relocation section needs to be removed if the section it applies to 101a85fe12eSEd Maste * will be removed. 102a85fe12eSEd Maste */ 103a85fe12eSEd Maste int 104a85fe12eSEd Maste is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) 105a85fe12eSEd Maste { 106a85fe12eSEd Maste const char *name; 107a85fe12eSEd Maste GElf_Shdr ish; 108a85fe12eSEd Maste Elf_Scn *is; 109a85fe12eSEd Maste size_t indx; 110a85fe12eSEd Maste int elferr; 111a85fe12eSEd Maste 112a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 113a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 114a85fe12eSEd Maste elf_errmsg(-1)); 115a85fe12eSEd Maste 116a85fe12eSEd Maste is = NULL; 117a85fe12eSEd Maste while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 118a85fe12eSEd Maste if (sh_info == elf_ndxscn(is)) { 119a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 120a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 121a85fe12eSEd Maste elf_errmsg(-1)); 122a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == 123a85fe12eSEd Maste NULL) 124a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 125a85fe12eSEd Maste elf_errmsg(-1)); 126a85fe12eSEd Maste if (is_remove_section(ecp, name)) 127a85fe12eSEd Maste return (1); 128a85fe12eSEd Maste else 129a85fe12eSEd Maste return (0); 130a85fe12eSEd Maste } 131a85fe12eSEd Maste } 132a85fe12eSEd Maste elferr = elf_errno(); 133a85fe12eSEd Maste if (elferr != 0) 134a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 135a85fe12eSEd Maste elf_errmsg(elferr)); 136a85fe12eSEd Maste 137a85fe12eSEd Maste /* Remove reloc section if we can't find the target section. */ 138a85fe12eSEd Maste return (1); 139a85fe12eSEd Maste } 140a85fe12eSEd Maste 141a85fe12eSEd Maste static int 142a85fe12eSEd Maste is_append_section(struct elfcopy *ecp, const char *name) 143a85fe12eSEd Maste { 144a85fe12eSEd Maste struct sec_action *sac; 145a85fe12eSEd Maste 146a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 147a85fe12eSEd Maste if (sac != NULL && sac->append != 0 && sac->string != NULL) 148a85fe12eSEd Maste return (1); 149a85fe12eSEd Maste 150a85fe12eSEd Maste return (0); 151a85fe12eSEd Maste } 152a85fe12eSEd Maste 153a85fe12eSEd Maste static int 154a85fe12eSEd Maste is_compress_section(struct elfcopy *ecp, const char *name) 155a85fe12eSEd Maste { 156a85fe12eSEd Maste struct sec_action *sac; 157a85fe12eSEd Maste 158a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 159a85fe12eSEd Maste if (sac != NULL && sac->compress != 0) 160a85fe12eSEd Maste return (1); 161a85fe12eSEd Maste 162a85fe12eSEd Maste return (0); 163a85fe12eSEd Maste } 164a85fe12eSEd Maste 165a85fe12eSEd Maste static void 166a85fe12eSEd Maste check_section_rename(struct elfcopy *ecp, struct section *s) 167a85fe12eSEd Maste { 168a85fe12eSEd Maste struct sec_action *sac; 169a85fe12eSEd Maste char *prefix; 170a85fe12eSEd Maste size_t namelen; 171a85fe12eSEd Maste 172a85fe12eSEd Maste if (s->pseudo) 173a85fe12eSEd Maste return; 174a85fe12eSEd Maste 175a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 176a85fe12eSEd Maste if (sac != NULL && sac->rename) 177a85fe12eSEd Maste s->name = sac->newname; 178a85fe12eSEd Maste 179a85fe12eSEd Maste if (!strcmp(s->name, ".symtab") || 180a85fe12eSEd Maste !strcmp(s->name, ".strtab") || 181a85fe12eSEd Maste !strcmp(s->name, ".shstrtab")) 182a85fe12eSEd Maste return; 183a85fe12eSEd Maste 184a85fe12eSEd Maste prefix = NULL; 185a85fe12eSEd Maste if (s->loadable && ecp->prefix_alloc != NULL) 186a85fe12eSEd Maste prefix = ecp->prefix_alloc; 187a85fe12eSEd Maste else if (ecp->prefix_sec != NULL) 188a85fe12eSEd Maste prefix = ecp->prefix_sec; 189a85fe12eSEd Maste 190a85fe12eSEd Maste if (prefix != NULL) { 191a85fe12eSEd Maste namelen = strlen(s->name) + strlen(prefix) + 1; 192a85fe12eSEd Maste if ((s->newname = malloc(namelen)) == NULL) 193a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 194a85fe12eSEd Maste snprintf(s->newname, namelen, "%s%s", prefix, s->name); 195a85fe12eSEd Maste s->name = s->newname; 196a85fe12eSEd Maste } 197a85fe12eSEd Maste } 198a85fe12eSEd Maste 199a85fe12eSEd Maste static int 200a85fe12eSEd Maste get_section_flags(struct elfcopy *ecp, const char *name) 201a85fe12eSEd Maste { 202a85fe12eSEd Maste struct sec_action *sac; 203a85fe12eSEd Maste 204a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 205a85fe12eSEd Maste if (sac != NULL && sac->flags) 206a85fe12eSEd Maste return sac->flags; 207a85fe12eSEd Maste 208a85fe12eSEd Maste return (0); 209a85fe12eSEd Maste } 210a85fe12eSEd Maste 211a85fe12eSEd Maste /* 212a85fe12eSEd Maste * Determine whether the section are debugging section. 213a85fe12eSEd Maste * According to libbfd, debugging sections are recognized 214a85fe12eSEd Maste * only by name. 215a85fe12eSEd Maste */ 216a85fe12eSEd Maste static int 217a85fe12eSEd Maste is_debug_section(const char *name) 218a85fe12eSEd Maste { 219a85fe12eSEd Maste const char *dbg_sec[] = { 220a85fe12eSEd Maste ".debug", 221a85fe12eSEd Maste ".gnu.linkonce.wi.", 222a85fe12eSEd Maste ".line", 223a85fe12eSEd Maste ".stab", 224a85fe12eSEd Maste NULL 225a85fe12eSEd Maste }; 226a85fe12eSEd Maste const char **p; 227a85fe12eSEd Maste 228a85fe12eSEd Maste for(p = dbg_sec; *p; p++) { 229a85fe12eSEd Maste if (strncmp(name, *p, strlen(*p)) == 0) 230a85fe12eSEd Maste return (1); 231a85fe12eSEd Maste } 232a85fe12eSEd Maste 233a85fe12eSEd Maste return (0); 234a85fe12eSEd Maste } 235a85fe12eSEd Maste 236a85fe12eSEd Maste static int 237a85fe12eSEd Maste is_print_section(struct elfcopy *ecp, const char *name) 238a85fe12eSEd Maste { 239a85fe12eSEd Maste struct sec_action *sac; 240a85fe12eSEd Maste 241a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 242a85fe12eSEd Maste if (sac != NULL && sac->print != 0) 243a85fe12eSEd Maste return (1); 244a85fe12eSEd Maste 245a85fe12eSEd Maste return (0); 246a85fe12eSEd Maste } 247a85fe12eSEd Maste 248a85fe12eSEd Maste static int 249a85fe12eSEd Maste is_modify_section(struct elfcopy *ecp, const char *name) 250a85fe12eSEd Maste { 251a85fe12eSEd Maste 252a85fe12eSEd Maste if (is_append_section(ecp, name) || 253a85fe12eSEd Maste is_compress_section(ecp, name)) 254a85fe12eSEd Maste return (1); 255a85fe12eSEd Maste 256a85fe12eSEd Maste return (0); 257a85fe12eSEd Maste } 258a85fe12eSEd Maste 259a85fe12eSEd Maste struct sec_action* 260a85fe12eSEd Maste lookup_sec_act(struct elfcopy *ecp, const char *name, int add) 261a85fe12eSEd Maste { 262a85fe12eSEd Maste struct sec_action *sac; 263a85fe12eSEd Maste 264a85fe12eSEd Maste if (name == NULL) 265a85fe12eSEd Maste return NULL; 266a85fe12eSEd Maste 267a85fe12eSEd Maste STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 268a85fe12eSEd Maste if (strcmp(name, sac->name) == 0) 269a85fe12eSEd Maste return sac; 270a85fe12eSEd Maste } 271a85fe12eSEd Maste 272a85fe12eSEd Maste if (add == 0) 273a85fe12eSEd Maste return NULL; 274a85fe12eSEd Maste 275a85fe12eSEd Maste if ((sac = malloc(sizeof(*sac))) == NULL) 276a85fe12eSEd Maste errx(EXIT_FAILURE, "not enough memory"); 277a85fe12eSEd Maste memset(sac, 0, sizeof(*sac)); 278a85fe12eSEd Maste sac->name = name; 279a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); 280a85fe12eSEd Maste 281a85fe12eSEd Maste return (sac); 282a85fe12eSEd Maste } 283a85fe12eSEd Maste 284a85fe12eSEd Maste void 285a85fe12eSEd Maste free_sec_act(struct elfcopy *ecp) 286a85fe12eSEd Maste { 287a85fe12eSEd Maste struct sec_action *sac, *sac_temp; 288a85fe12eSEd Maste 289a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { 290a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); 291a85fe12eSEd Maste free(sac); 292a85fe12eSEd Maste } 293a85fe12eSEd Maste } 294a85fe12eSEd Maste 295a85fe12eSEd Maste void 296a85fe12eSEd Maste insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) 297a85fe12eSEd Maste { 298a85fe12eSEd Maste struct section *s; 299a85fe12eSEd Maste 300a85fe12eSEd Maste if (!tail) { 301a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 302a85fe12eSEd Maste if (sec->off < s->off) { 303a85fe12eSEd Maste TAILQ_INSERT_BEFORE(s, sec, sec_list); 304a85fe12eSEd Maste goto inc_nos; 305a85fe12eSEd Maste } 306a85fe12eSEd Maste } 307a85fe12eSEd Maste } 308a85fe12eSEd Maste 309a85fe12eSEd Maste TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); 310a85fe12eSEd Maste 311a85fe12eSEd Maste inc_nos: 312a85fe12eSEd Maste if (sec->pseudo == 0) 313a85fe12eSEd Maste ecp->nos++; 314a85fe12eSEd Maste } 315a85fe12eSEd Maste 316a85fe12eSEd Maste /* 317a85fe12eSEd Maste * First step of section creation: create scn and internal section 318a85fe12eSEd Maste * structure, discard sections to be removed. 319a85fe12eSEd Maste */ 320a85fe12eSEd Maste void 321a85fe12eSEd Maste create_scn(struct elfcopy *ecp) 322a85fe12eSEd Maste { 323a85fe12eSEd Maste struct section *s; 324a85fe12eSEd Maste const char *name; 325a85fe12eSEd Maste Elf_Scn *is; 326a85fe12eSEd Maste GElf_Shdr ish; 327a85fe12eSEd Maste size_t indx; 328a85fe12eSEd Maste uint64_t oldndx, newndx; 329a85fe12eSEd Maste int elferr, sec_flags; 330a85fe12eSEd Maste 331a85fe12eSEd Maste /* 332a85fe12eSEd Maste * Insert a pseudo section that contains the ELF header 333a85fe12eSEd Maste * and program header. Used as reference for section offset 334a85fe12eSEd Maste * or load address adjustment. 335a85fe12eSEd Maste */ 336a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 337a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 338a85fe12eSEd Maste s->off = 0; 339a85fe12eSEd Maste s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + 340a85fe12eSEd Maste gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); 341a85fe12eSEd Maste s->align = 1; 342a85fe12eSEd Maste s->pseudo = 1; 343a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 344a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 345a85fe12eSEd Maste 346a85fe12eSEd Maste /* Create internal .shstrtab section. */ 347a85fe12eSEd Maste init_shstrtab(ecp); 348a85fe12eSEd Maste 349a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 350a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 351a85fe12eSEd Maste elf_errmsg(-1)); 352a85fe12eSEd Maste 353a85fe12eSEd Maste is = NULL; 354a85fe12eSEd Maste while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 355a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 356a85fe12eSEd Maste errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s", 357a85fe12eSEd Maste elf_errmsg(-1)); 358a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) 359a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 360a85fe12eSEd Maste elf_errmsg(-1)); 361a85fe12eSEd Maste 362a85fe12eSEd Maste /* Skip sections to be removed. */ 363a85fe12eSEd Maste if (is_remove_section(ecp, name)) 364a85fe12eSEd Maste continue; 365a85fe12eSEd Maste 366a85fe12eSEd Maste /* 367a85fe12eSEd Maste * Relocation section need to be remove if the section 368a85fe12eSEd Maste * it applies will be removed. 369a85fe12eSEd Maste */ 370a85fe12eSEd Maste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 371a85fe12eSEd Maste if (ish.sh_info != 0 && 372a85fe12eSEd Maste is_remove_reloc_sec(ecp, ish.sh_info)) 373a85fe12eSEd Maste continue; 374a85fe12eSEd Maste 375a85fe12eSEd Maste /* Get section flags set by user. */ 376a85fe12eSEd Maste sec_flags = get_section_flags(ecp, name); 377a85fe12eSEd Maste 378a85fe12eSEd Maste /* Create internal section object. */ 379a85fe12eSEd Maste if (strcmp(name, ".shstrtab") != 0) { 380a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 381a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 382a85fe12eSEd Maste s->name = name; 383a85fe12eSEd Maste s->is = is; 384a85fe12eSEd Maste s->off = ish.sh_offset; 385a85fe12eSEd Maste s->sz = ish.sh_size; 386a85fe12eSEd Maste s->align = ish.sh_addralign; 387a85fe12eSEd Maste s->type = ish.sh_type; 388a85fe12eSEd Maste s->vma = ish.sh_addr; 389a85fe12eSEd Maste 390a85fe12eSEd Maste /* 391a85fe12eSEd Maste * Search program headers to determine whether section 392a85fe12eSEd Maste * is loadable, but if user explicitly set section flags 393a85fe12eSEd Maste * while neither "load" nor "alloc" is set, we make the 394a85fe12eSEd Maste * section unloadable. 395a85fe12eSEd Maste */ 396a85fe12eSEd Maste if (sec_flags && 397a85fe12eSEd Maste (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 398a85fe12eSEd Maste s->loadable = 0; 399a85fe12eSEd Maste else 400a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 401a85fe12eSEd Maste } else { 402a85fe12eSEd Maste /* Assuming .shstrtab is "unloadable". */ 403a85fe12eSEd Maste s = ecp->shstrtab; 404a85fe12eSEd Maste s->off = ish.sh_offset; 405a85fe12eSEd Maste } 406a85fe12eSEd Maste 407a85fe12eSEd Maste oldndx = newndx = SHN_UNDEF; 408a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 409a85fe12eSEd Maste strcmp(name, ".strtab") != 0) { 410a85fe12eSEd Maste if (!strcmp(name, ".shstrtab")) { 411a85fe12eSEd Maste /* 412a85fe12eSEd Maste * Add sections specified by --add-section and 413a85fe12eSEd Maste * gnu debuglink. we want these sections have 414a85fe12eSEd Maste * smaller index than .shstrtab section. 415a85fe12eSEd Maste */ 416a85fe12eSEd Maste if (ecp->debuglink != NULL) 417a85fe12eSEd Maste add_gnu_debuglink(ecp); 418a85fe12eSEd Maste if (ecp->flags & SEC_ADD) 419a85fe12eSEd Maste insert_sections(ecp); 420a85fe12eSEd Maste } 421a85fe12eSEd Maste if ((s->os = elf_newscn(ecp->eout)) == NULL) 422a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn failed: %s", 423a85fe12eSEd Maste elf_errmsg(-1)); 424a85fe12eSEd Maste if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 425a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 426a85fe12eSEd Maste elf_errmsg(-1)); 427a85fe12eSEd Maste } 428a85fe12eSEd Maste if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 429a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 430a85fe12eSEd Maste elf_errmsg(-1)); 431a85fe12eSEd Maste if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 432a85fe12eSEd Maste ecp->secndx[oldndx] = newndx; 433a85fe12eSEd Maste 434a85fe12eSEd Maste /* 435a85fe12eSEd Maste * If strip action is STRIP_NONDEBUG(only keep debug), 436a85fe12eSEd Maste * change sections flags of loadable sections to SHF_NOBITS, 437a85fe12eSEd Maste * and the content of those sections will be ignored. 438a85fe12eSEd Maste */ 439a85fe12eSEd Maste if (ecp->strip == STRIP_NONDEBUG && (ish.sh_flags & SHF_ALLOC)) 440a85fe12eSEd Maste s->type = SHT_NOBITS; 441a85fe12eSEd Maste 442a85fe12eSEd Maste check_section_rename(ecp, s); 443a85fe12eSEd Maste 444a85fe12eSEd Maste /* create section header based on input object. */ 445a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 446a85fe12eSEd Maste strcmp(name, ".strtab") != 0 && 447a85fe12eSEd Maste strcmp(name, ".shstrtab") != 0) 448a85fe12eSEd Maste copy_shdr(ecp, s, NULL, 0, sec_flags); 449a85fe12eSEd Maste 450a85fe12eSEd Maste if (strcmp(name, ".symtab") == 0) { 451a85fe12eSEd Maste ecp->flags |= SYMTAB_EXIST; 452a85fe12eSEd Maste ecp->symtab = s; 453a85fe12eSEd Maste } 454a85fe12eSEd Maste if (strcmp(name, ".strtab") == 0) 455a85fe12eSEd Maste ecp->strtab = s; 456a85fe12eSEd Maste 457a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 458a85fe12eSEd Maste } 459a85fe12eSEd Maste elferr = elf_errno(); 460a85fe12eSEd Maste if (elferr != 0) 461a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 462a85fe12eSEd Maste elf_errmsg(elferr)); 463a85fe12eSEd Maste } 464a85fe12eSEd Maste 465a85fe12eSEd Maste struct section * 466a85fe12eSEd Maste insert_shtab(struct elfcopy *ecp, int tail) 467a85fe12eSEd Maste { 468a85fe12eSEd Maste struct section *s, *shtab; 469a85fe12eSEd Maste GElf_Ehdr ieh; 470a85fe12eSEd Maste int nsecs; 471a85fe12eSEd Maste 472a85fe12eSEd Maste /* 473a85fe12eSEd Maste * Treat section header table as a "pseudo" section, insert it 474a85fe12eSEd Maste * into section list, so later it will get sorted and resynced 475a85fe12eSEd Maste * just as normal sections. 476a85fe12eSEd Maste */ 477a85fe12eSEd Maste if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 478a85fe12eSEd Maste errx(EXIT_FAILURE, "calloc failed"); 479a85fe12eSEd Maste if (!tail) { 480a85fe12eSEd Maste /* shoff of input object is used as a hint. */ 481a85fe12eSEd Maste if (gelf_getehdr(ecp->ein, &ieh) == NULL) 482a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 483a85fe12eSEd Maste elf_errmsg(-1)); 484a85fe12eSEd Maste shtab->off = ieh.e_shoff; 485a85fe12eSEd Maste } else 486a85fe12eSEd Maste shtab->off = 0; 487a85fe12eSEd Maste /* Calculate number of sections in the output object. */ 488a85fe12eSEd Maste nsecs = 0; 489a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 490a85fe12eSEd Maste if (!s->pseudo) 491a85fe12eSEd Maste nsecs++; 492a85fe12eSEd Maste } 493a85fe12eSEd Maste /* Remember there is always a null section, so we +1 here. */ 494a85fe12eSEd Maste shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 495a85fe12eSEd Maste if (shtab->sz == 0) 496a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 497a85fe12eSEd Maste shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 498a85fe12eSEd Maste shtab->loadable = 0; 499a85fe12eSEd Maste shtab->pseudo = 1; 500a85fe12eSEd Maste insert_to_sec_list(ecp, shtab, tail); 501a85fe12eSEd Maste 502a85fe12eSEd Maste return (shtab); 503a85fe12eSEd Maste } 504a85fe12eSEd Maste 505a85fe12eSEd Maste void 506a85fe12eSEd Maste copy_content(struct elfcopy *ecp) 507a85fe12eSEd Maste { 508a85fe12eSEd Maste struct section *s; 509a85fe12eSEd Maste 510a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 511a85fe12eSEd Maste /* Skip pseudo section. */ 512a85fe12eSEd Maste if (s->pseudo) 513a85fe12eSEd Maste continue; 514a85fe12eSEd Maste 515a85fe12eSEd Maste /* Skip special sections. */ 516a85fe12eSEd Maste if (strcmp(s->name, ".symtab") == 0 || 517a85fe12eSEd Maste strcmp(s->name, ".strtab") == 0 || 518a85fe12eSEd Maste strcmp(s->name, ".shstrtab") == 0) 519a85fe12eSEd Maste continue; 520a85fe12eSEd Maste 521a85fe12eSEd Maste /* 522a85fe12eSEd Maste * If strip action is STRIP_ALL, relocation info need 523a85fe12eSEd Maste * to be stripped. Skip filtering otherwisw. 524a85fe12eSEd Maste */ 525a85fe12eSEd Maste if (ecp->strip == STRIP_ALL && 526a85fe12eSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 527a85fe12eSEd Maste filter_reloc(ecp, s); 528a85fe12eSEd Maste 529a85fe12eSEd Maste if (is_modify_section(ecp, s->name)) 530a85fe12eSEd Maste modify_section(ecp, s); 531a85fe12eSEd Maste 532a85fe12eSEd Maste copy_data(s); 533a85fe12eSEd Maste 534a85fe12eSEd Maste /* 535a85fe12eSEd Maste * If symbol table is modified, relocation info might 536a85fe12eSEd Maste * need update, as symbol index may have changed. 537a85fe12eSEd Maste */ 538a85fe12eSEd Maste if ((ecp->flags & SYMTAB_INTACT) == 0 && 539a85fe12eSEd Maste (ecp->flags & SYMTAB_EXIST) && 540a85fe12eSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 541a85fe12eSEd Maste update_reloc(ecp, s); 542a85fe12eSEd Maste 543a85fe12eSEd Maste if (is_print_section(ecp, s->name)) 544a85fe12eSEd Maste print_section(s); 545a85fe12eSEd Maste } 546a85fe12eSEd Maste } 547a85fe12eSEd Maste 548a85fe12eSEd Maste /* 549a85fe12eSEd Maste * Filter relocation entries, only keep those entries whose 550a85fe12eSEd Maste * symbol is in the keep list. 551a85fe12eSEd Maste */ 552a85fe12eSEd Maste static void 553a85fe12eSEd Maste filter_reloc(struct elfcopy *ecp, struct section *s) 554a85fe12eSEd Maste { 555a85fe12eSEd Maste const char *name; 556a85fe12eSEd Maste GElf_Shdr ish; 557a85fe12eSEd Maste GElf_Rel rel; 558a85fe12eSEd Maste GElf_Rela rela; 559a85fe12eSEd Maste Elf32_Rel *rel32; 560a85fe12eSEd Maste Elf64_Rel *rel64; 561a85fe12eSEd Maste Elf32_Rela *rela32; 562a85fe12eSEd Maste Elf64_Rela *rela64; 563a85fe12eSEd Maste Elf_Data *id; 564a85fe12eSEd Maste uint64_t cap, n, nrels; 565a85fe12eSEd Maste int elferr, i; 566a85fe12eSEd Maste 567a85fe12eSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 568a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 569a85fe12eSEd Maste elf_errmsg(-1)); 570a85fe12eSEd Maste 571a85fe12eSEd Maste /* We don't want to touch relocation info for dynamic symbols. */ 572a85fe12eSEd Maste if ((ecp->flags & SYMTAB_EXIST) == 0) { 573a85fe12eSEd Maste if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { 574a85fe12eSEd Maste /* 575a85fe12eSEd Maste * This reloc section applies to the symbol table 576a85fe12eSEd Maste * that was stripped, so discard whole section. 577a85fe12eSEd Maste */ 578a85fe12eSEd Maste s->nocopy = 1; 579a85fe12eSEd Maste s->sz = 0; 580a85fe12eSEd Maste } 581a85fe12eSEd Maste return; 582a85fe12eSEd Maste } else { 583a85fe12eSEd Maste /* Symbol table exist, check if index equals. */ 584a85fe12eSEd Maste if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 585a85fe12eSEd Maste return; 586a85fe12eSEd Maste } 587a85fe12eSEd Maste 588a85fe12eSEd Maste #define COPYREL(REL, SZ) do { \ 589a85fe12eSEd Maste if (nrels == 0) { \ 590a85fe12eSEd Maste if ((REL##SZ = malloc(cap * \ 591a85fe12eSEd Maste sizeof(Elf##SZ##_Rel))) == NULL) \ 592a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); \ 593a85fe12eSEd Maste } \ 594a85fe12eSEd Maste if (nrels >= cap) { \ 595a85fe12eSEd Maste cap *= 2; \ 596a85fe12eSEd Maste if ((REL##SZ = realloc(REL##SZ, cap * \ 597a85fe12eSEd Maste sizeof(Elf##SZ##_Rel))) == NULL) \ 598a85fe12eSEd Maste err(EXIT_FAILURE, "realloc failed"); \ 599a85fe12eSEd Maste } \ 600a85fe12eSEd Maste REL##SZ[nrels].r_offset = REL.r_offset; \ 601a85fe12eSEd Maste REL##SZ[nrels].r_info = REL.r_info; \ 602a85fe12eSEd Maste if (s->type == SHT_RELA) \ 603a85fe12eSEd Maste rela##SZ[nrels].r_addend = rela.r_addend; \ 604a85fe12eSEd Maste nrels++; \ 605a85fe12eSEd Maste } while (0) 606a85fe12eSEd Maste 607a85fe12eSEd Maste nrels = 0; 608a85fe12eSEd Maste cap = 4; /* keep list is usually small. */ 609a85fe12eSEd Maste rel32 = NULL; 610a85fe12eSEd Maste rel64 = NULL; 611a85fe12eSEd Maste rela32 = NULL; 612a85fe12eSEd Maste rela64 = NULL; 613a85fe12eSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) 614a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 615a85fe12eSEd Maste elf_errmsg(-1)); 616a85fe12eSEd Maste n = ish.sh_size / ish.sh_entsize; 617a85fe12eSEd Maste for(i = 0; (uint64_t)i < n; i++) { 618a85fe12eSEd Maste if (s->type == SHT_REL) { 619a85fe12eSEd Maste if (gelf_getrel(id, i, &rel) != &rel) 620a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 621a85fe12eSEd Maste elf_errmsg(-1)); 622a85fe12eSEd Maste } else { 623a85fe12eSEd Maste if (gelf_getrela(id, i, &rela) != &rela) 624a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 625a85fe12eSEd Maste elf_errmsg(-1)); 626a85fe12eSEd Maste } 627a85fe12eSEd Maste name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 628a85fe12eSEd Maste GELF_R_SYM(rel.r_info)); 629a85fe12eSEd Maste if (name == NULL) 630a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 631a85fe12eSEd Maste elf_errmsg(-1)); 632a85fe12eSEd Maste if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { 633a85fe12eSEd Maste if (ecp->oec == ELFCLASS32) { 634a85fe12eSEd Maste if (s->type == SHT_REL) 635a85fe12eSEd Maste COPYREL(rel, 32); 636a85fe12eSEd Maste else 637a85fe12eSEd Maste COPYREL(rela, 32); 638a85fe12eSEd Maste } else { 639a85fe12eSEd Maste if (s->type == SHT_REL) 640a85fe12eSEd Maste COPYREL(rel, 64); 641a85fe12eSEd Maste else 642a85fe12eSEd Maste COPYREL(rela, 64); 643a85fe12eSEd Maste } 644a85fe12eSEd Maste } 645a85fe12eSEd Maste } 646a85fe12eSEd Maste elferr = elf_errno(); 647a85fe12eSEd Maste if (elferr != 0) 648a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 649a85fe12eSEd Maste elf_errmsg(elferr)); 650a85fe12eSEd Maste 651a85fe12eSEd Maste if (ecp->oec == ELFCLASS32) { 652a85fe12eSEd Maste if (s->type == SHT_REL) 653a85fe12eSEd Maste s->buf = rel32; 654a85fe12eSEd Maste else 655a85fe12eSEd Maste s->buf = rela32; 656a85fe12eSEd Maste } else { 657a85fe12eSEd Maste if (s->type == SHT_REL) 658a85fe12eSEd Maste s->buf = rel64; 659a85fe12eSEd Maste else 660a85fe12eSEd Maste s->buf = rela64; 661a85fe12eSEd Maste } 662a85fe12eSEd Maste s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 663a85fe12eSEd Maste ELF_T_RELA), nrels, EV_CURRENT); 664a85fe12eSEd Maste s->nocopy = 1; 665a85fe12eSEd Maste } 666a85fe12eSEd Maste 667a85fe12eSEd Maste static void 668a85fe12eSEd Maste update_reloc(struct elfcopy *ecp, struct section *s) 669a85fe12eSEd Maste { 670a85fe12eSEd Maste GElf_Shdr osh; 671a85fe12eSEd Maste GElf_Rel rel; 672a85fe12eSEd Maste GElf_Rela rela; 673a85fe12eSEd Maste Elf_Data *od; 674a85fe12eSEd Maste uint64_t n; 675a85fe12eSEd Maste int i; 676a85fe12eSEd Maste 677a85fe12eSEd Maste #define UPDATEREL(REL) do { \ 678a85fe12eSEd Maste if (gelf_get##REL(od, i, &REL) != &REL) \ 679a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 680a85fe12eSEd Maste elf_errmsg(-1)); \ 681a85fe12eSEd Maste REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 682a85fe12eSEd Maste GELF_R_TYPE(REL.r_info)); \ 683a85fe12eSEd Maste if (!gelf_update_##REL(od, i, &REL)) \ 684a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 685a85fe12eSEd Maste elf_errmsg(-1)); \ 686a85fe12eSEd Maste } while(0) 687a85fe12eSEd Maste 688a85fe12eSEd Maste if (s->sz == 0) 689a85fe12eSEd Maste return; 690a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 691a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 692a85fe12eSEd Maste elf_errmsg(-1)); 693a85fe12eSEd Maste /* Only process .symtab reloc info. */ 694a85fe12eSEd Maste if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 695a85fe12eSEd Maste return; 696a85fe12eSEd Maste if ((od = elf_getdata(s->os, NULL)) == NULL) 697a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 698a85fe12eSEd Maste elf_errmsg(-1)); 699a85fe12eSEd Maste n = osh.sh_size / osh.sh_entsize; 700a85fe12eSEd Maste for(i = 0; (uint64_t)i < n; i++) { 701a85fe12eSEd Maste if (s->type == SHT_REL) 702a85fe12eSEd Maste UPDATEREL(rel); 703a85fe12eSEd Maste else 704a85fe12eSEd Maste UPDATEREL(rela); 705a85fe12eSEd Maste } 706a85fe12eSEd Maste } 707a85fe12eSEd Maste 708a85fe12eSEd Maste static void 709a85fe12eSEd Maste pad_section(struct elfcopy *ecp, struct section *s) 710a85fe12eSEd Maste { 711a85fe12eSEd Maste GElf_Shdr osh; 712a85fe12eSEd Maste Elf_Data *od; 713a85fe12eSEd Maste 714a85fe12eSEd Maste if (s == NULL || s->pad_sz == 0) 715a85fe12eSEd Maste return; 716a85fe12eSEd Maste 717a85fe12eSEd Maste if ((s->pad = malloc(s->pad_sz)) == NULL) 718a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 719a85fe12eSEd Maste memset(s->pad, ecp->fill, s->pad_sz); 720a85fe12eSEd Maste 721a85fe12eSEd Maste /* Create a new Elf_Data to contain the padding bytes. */ 722a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 723a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 724a85fe12eSEd Maste elf_errmsg(-1)); 725a85fe12eSEd Maste od->d_align = 1; 726a85fe12eSEd Maste od->d_off = s->sz; 727a85fe12eSEd Maste od->d_buf = s->pad; 728a85fe12eSEd Maste od->d_type = ELF_T_BYTE; 729a85fe12eSEd Maste od->d_size = s->pad_sz; 730a85fe12eSEd Maste od->d_version = EV_CURRENT; 731a85fe12eSEd Maste 732a85fe12eSEd Maste /* Update section header. */ 733a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 734a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 735a85fe12eSEd Maste elf_errmsg(-1)); 736a85fe12eSEd Maste osh.sh_size = s->sz + s->pad_sz; 737a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 738a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 739a85fe12eSEd Maste elf_errmsg(-1)); 740a85fe12eSEd Maste } 741a85fe12eSEd Maste 742a85fe12eSEd Maste void 743a85fe12eSEd Maste resync_sections(struct elfcopy *ecp) 744a85fe12eSEd Maste { 745a85fe12eSEd Maste struct section *s, *ps; 746a85fe12eSEd Maste GElf_Shdr osh; 747a85fe12eSEd Maste uint64_t off; 748a85fe12eSEd Maste int first; 749a85fe12eSEd Maste 750a85fe12eSEd Maste ps = NULL; 751a85fe12eSEd Maste first = 1; 752a85fe12eSEd Maste off = 0; 753a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 754a85fe12eSEd Maste if (first) { 755a85fe12eSEd Maste off = s->off; 756a85fe12eSEd Maste first = 0; 757a85fe12eSEd Maste } 758a85fe12eSEd Maste 759a85fe12eSEd Maste /* Align section offset. */ 760a85fe12eSEd Maste if (off <= s->off) { 761a85fe12eSEd Maste if (!s->loadable) 762a85fe12eSEd Maste s->off = roundup(off, s->align); 763a85fe12eSEd Maste } else { 764a85fe12eSEd Maste if (s->loadable) 76517eee522SEd Maste warnx("moving loadable section %s, " 76617eee522SEd Maste "is this intentional?", s->name); 767a85fe12eSEd Maste s->off = roundup(off, s->align); 768a85fe12eSEd Maste } 769a85fe12eSEd Maste 770a85fe12eSEd Maste /* Calculate next section offset. */ 771a85fe12eSEd Maste off = s->off; 772a85fe12eSEd Maste if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 773a85fe12eSEd Maste off += s->sz; 774a85fe12eSEd Maste 775a85fe12eSEd Maste if (s->pseudo) { 776a85fe12eSEd Maste ps = NULL; 777a85fe12eSEd Maste continue; 778a85fe12eSEd Maste } 779a85fe12eSEd Maste 780a85fe12eSEd Maste /* Count padding bytes added through --pad-to. */ 781a85fe12eSEd Maste if (s->pad_sz > 0) 782a85fe12eSEd Maste off += s->pad_sz; 783a85fe12eSEd Maste 784a85fe12eSEd Maste /* Update section header accordingly. */ 785a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 786a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 787a85fe12eSEd Maste elf_errmsg(-1)); 788a85fe12eSEd Maste osh.sh_addr = s->vma; 789a85fe12eSEd Maste osh.sh_offset = s->off; 790a85fe12eSEd Maste osh.sh_size = s->sz; 791a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 792a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 793a85fe12eSEd Maste elf_errmsg(-1)); 794a85fe12eSEd Maste 795a85fe12eSEd Maste /* Add padding for previous section, if need. */ 796a85fe12eSEd Maste if (ps != NULL) { 797a85fe12eSEd Maste if (ps->pad_sz > 0) { 798a85fe12eSEd Maste /* Apply padding added by --pad-to. */ 799a85fe12eSEd Maste pad_section(ecp, ps); 800a85fe12eSEd Maste } else if ((ecp->flags & GAP_FILL) && 801a85fe12eSEd Maste (ps->off + ps->sz < s->off)) { 802a85fe12eSEd Maste /* 803a85fe12eSEd Maste * Fill the gap between sections by padding 804a85fe12eSEd Maste * the section with lower address. 805a85fe12eSEd Maste */ 806a85fe12eSEd Maste ps->pad_sz = s->off - (ps->off + ps->sz); 807a85fe12eSEd Maste pad_section(ecp, ps); 808a85fe12eSEd Maste } 809a85fe12eSEd Maste } 810a85fe12eSEd Maste 811a85fe12eSEd Maste ps = s; 812a85fe12eSEd Maste } 813a85fe12eSEd Maste 814a85fe12eSEd Maste /* Pad the last section, if need. */ 815a85fe12eSEd Maste if (ps != NULL && ps->pad_sz > 0) 816a85fe12eSEd Maste pad_section(ecp, ps); 817a85fe12eSEd Maste } 818a85fe12eSEd Maste 819a85fe12eSEd Maste static void 820a85fe12eSEd Maste modify_section(struct elfcopy *ecp, struct section *s) 821a85fe12eSEd Maste { 822a85fe12eSEd Maste struct sec_action *sac; 823a85fe12eSEd Maste size_t srcsz, dstsz, p, len; 824a85fe12eSEd Maste char *b, *c, *d, *src, *end; 825a85fe12eSEd Maste int dupe; 826a85fe12eSEd Maste 827a85fe12eSEd Maste src = read_section(s, &srcsz); 828a85fe12eSEd Maste if (src == NULL || srcsz == 0) { 829a85fe12eSEd Maste /* For empty section, we proceed if we need to append. */ 830a85fe12eSEd Maste if (!is_append_section(ecp, s->name)) 831a85fe12eSEd Maste return; 832a85fe12eSEd Maste } 833a85fe12eSEd Maste 834a85fe12eSEd Maste /* Allocate buffer needed for new section data. */ 835a85fe12eSEd Maste dstsz = srcsz; 836a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 837a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 838a85fe12eSEd Maste dstsz += strlen(sac->string) + 1; 839a85fe12eSEd Maste } 840a85fe12eSEd Maste if ((b = malloc(dstsz)) == NULL) 841a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 842a85fe12eSEd Maste s->buf = b; 843a85fe12eSEd Maste 844a85fe12eSEd Maste /* Compress section. */ 845a85fe12eSEd Maste p = 0; 846a85fe12eSEd Maste if (is_compress_section(ecp, s->name)) { 847a85fe12eSEd Maste end = src + srcsz; 848a85fe12eSEd Maste for(c = src; c < end;) { 849a85fe12eSEd Maste len = 0; 850a85fe12eSEd Maste while(c + len < end && c[len] != '\0') 851a85fe12eSEd Maste len++; 852a85fe12eSEd Maste if (c + len == end) { 853a85fe12eSEd Maste /* XXX should we warn here? */ 854a85fe12eSEd Maste strncpy(&b[p], c, len); 855a85fe12eSEd Maste p += len; 856a85fe12eSEd Maste break; 857a85fe12eSEd Maste } 858a85fe12eSEd Maste dupe = 0; 859a85fe12eSEd Maste for (d = b; d < b + p; ) { 860a85fe12eSEd Maste if (strcmp(d, c) == 0) { 861a85fe12eSEd Maste dupe = 1; 862a85fe12eSEd Maste break; 863a85fe12eSEd Maste } 864a85fe12eSEd Maste d += strlen(d) + 1; 865a85fe12eSEd Maste } 866a85fe12eSEd Maste if (!dupe) { 867a85fe12eSEd Maste strncpy(&b[p], c, len); 868a85fe12eSEd Maste b[p + len] = '\0'; 869a85fe12eSEd Maste p += len + 1; 870a85fe12eSEd Maste } 871a85fe12eSEd Maste c += len + 1; 872a85fe12eSEd Maste } 873a85fe12eSEd Maste } else { 874a85fe12eSEd Maste memcpy(b, src, srcsz); 875a85fe12eSEd Maste p += srcsz; 876a85fe12eSEd Maste } 877a85fe12eSEd Maste 878a85fe12eSEd Maste /* Append section. */ 879a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 880a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 881a85fe12eSEd Maste len = strlen(sac->string); 882a85fe12eSEd Maste strncpy(&b[p], sac->string, len); 883a85fe12eSEd Maste b[p + len] = '\0'; 884a85fe12eSEd Maste p += len + 1; 885a85fe12eSEd Maste } 886a85fe12eSEd Maste 887a85fe12eSEd Maste s->sz = p; 888a85fe12eSEd Maste s->nocopy = 1; 889a85fe12eSEd Maste } 890a85fe12eSEd Maste 891a85fe12eSEd Maste static void 892a85fe12eSEd Maste print_data(const char *d, size_t sz) 893a85fe12eSEd Maste { 894a85fe12eSEd Maste const char *c; 895a85fe12eSEd Maste 896a85fe12eSEd Maste for (c = d; c < d + sz; c++) { 897a85fe12eSEd Maste if (*c == '\0') 898a85fe12eSEd Maste putchar('\n'); 899a85fe12eSEd Maste else 900a85fe12eSEd Maste putchar(*c); 901a85fe12eSEd Maste } 902a85fe12eSEd Maste } 903a85fe12eSEd Maste 904a85fe12eSEd Maste static void 905a85fe12eSEd Maste print_section(struct section *s) 906a85fe12eSEd Maste { 907a85fe12eSEd Maste Elf_Data *id; 908a85fe12eSEd Maste int elferr; 909a85fe12eSEd Maste 910a85fe12eSEd Maste if (s->buf != NULL && s->sz > 0) { 911a85fe12eSEd Maste print_data(s->buf, s->sz); 912a85fe12eSEd Maste } else { 913a85fe12eSEd Maste id = NULL; 914a85fe12eSEd Maste while ((id = elf_getdata(s->is, id)) != NULL) 915a85fe12eSEd Maste print_data(id->d_buf, id->d_size); 916a85fe12eSEd Maste elferr = elf_errno(); 917a85fe12eSEd Maste if (elferr != 0) 918a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 919a85fe12eSEd Maste elf_errmsg(elferr)); 920a85fe12eSEd Maste } 921a85fe12eSEd Maste putchar('\n'); 922a85fe12eSEd Maste } 923a85fe12eSEd Maste 924a85fe12eSEd Maste static void * 925a85fe12eSEd Maste read_section(struct section *s, size_t *size) 926a85fe12eSEd Maste { 927a85fe12eSEd Maste Elf_Data *id; 928a85fe12eSEd Maste char *b; 929a85fe12eSEd Maste size_t sz; 930a85fe12eSEd Maste int elferr; 931a85fe12eSEd Maste 932a85fe12eSEd Maste sz = 0; 933a85fe12eSEd Maste b = NULL; 934a85fe12eSEd Maste id = NULL; 935a85fe12eSEd Maste while ((id = elf_getdata(s->is, id)) != NULL) { 936a85fe12eSEd Maste if (b == NULL) 937a85fe12eSEd Maste b = malloc(id->d_size); 938a85fe12eSEd Maste else 939a85fe12eSEd Maste b = malloc(sz + id->d_size); 940a85fe12eSEd Maste if (b == NULL) 941a85fe12eSEd Maste err(EXIT_FAILURE, "malloc or realloc failed"); 942a85fe12eSEd Maste 943a85fe12eSEd Maste memcpy(&b[sz], id->d_buf, id->d_size); 944a85fe12eSEd Maste sz += id->d_size; 945a85fe12eSEd Maste } 946a85fe12eSEd Maste elferr = elf_errno(); 947a85fe12eSEd Maste if (elferr != 0) 948a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 949a85fe12eSEd Maste elf_errmsg(elferr)); 950a85fe12eSEd Maste 951a85fe12eSEd Maste *size = sz; 952a85fe12eSEd Maste 953a85fe12eSEd Maste return (b); 954a85fe12eSEd Maste } 955a85fe12eSEd Maste 956a85fe12eSEd Maste void 957a85fe12eSEd Maste copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 958a85fe12eSEd Maste int sec_flags) 959a85fe12eSEd Maste { 960a85fe12eSEd Maste GElf_Shdr ish, osh; 961a85fe12eSEd Maste 962a85fe12eSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 963a85fe12eSEd Maste errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", 964a85fe12eSEd Maste elf_errmsg(-1)); 965a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 966a85fe12eSEd Maste errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", 967a85fe12eSEd Maste elf_errmsg(-1)); 968a85fe12eSEd Maste 969a85fe12eSEd Maste if (copy) 970a85fe12eSEd Maste (void) memcpy(&osh, &ish, sizeof(ish)); 971a85fe12eSEd Maste else { 972a85fe12eSEd Maste osh.sh_type = s->type; 973a85fe12eSEd Maste osh.sh_addr = s->vma; 974a85fe12eSEd Maste osh.sh_offset = s->off; 975a85fe12eSEd Maste osh.sh_size = s->sz; 976a85fe12eSEd Maste osh.sh_link = ish.sh_link; 977a85fe12eSEd Maste osh.sh_info = ish.sh_info; 978a85fe12eSEd Maste osh.sh_addralign = s->align; 979a85fe12eSEd Maste osh.sh_entsize = ish.sh_entsize; 980a85fe12eSEd Maste 981a85fe12eSEd Maste if (sec_flags) { 982a85fe12eSEd Maste osh.sh_flags = 0; 983a85fe12eSEd Maste if (sec_flags & SF_ALLOC) { 984a85fe12eSEd Maste osh.sh_flags |= SHF_ALLOC; 985a85fe12eSEd Maste if (!s->loadable) 986a85fe12eSEd Maste warnx("set SHF_ALLOC flag for " 987a85fe12eSEd Maste "unloadable section %s", 988a85fe12eSEd Maste s->name); 989a85fe12eSEd Maste } 990a85fe12eSEd Maste if ((sec_flags & SF_READONLY) == 0) 991a85fe12eSEd Maste osh.sh_flags |= SHF_WRITE; 992a85fe12eSEd Maste if (sec_flags & SF_CODE) 993a85fe12eSEd Maste osh.sh_flags |= SHF_EXECINSTR; 994a85fe12eSEd Maste } else 995a85fe12eSEd Maste osh.sh_flags = ish.sh_flags; 996a85fe12eSEd Maste } 997a85fe12eSEd Maste 998a85fe12eSEd Maste if (name == NULL) 999a85fe12eSEd Maste add_to_shstrtab(ecp, s->name); 1000a85fe12eSEd Maste else 1001a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1002a85fe12eSEd Maste 1003a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1004a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1005a85fe12eSEd Maste elf_errmsg(-1)); 1006a85fe12eSEd Maste } 1007a85fe12eSEd Maste 1008a85fe12eSEd Maste void 1009a85fe12eSEd Maste copy_data(struct section *s) 1010a85fe12eSEd Maste { 1011a85fe12eSEd Maste Elf_Data *id, *od; 1012a85fe12eSEd Maste int elferr; 1013a85fe12eSEd Maste 1014a85fe12eSEd Maste if (s->nocopy && s->buf == NULL) 1015a85fe12eSEd Maste return; 1016a85fe12eSEd Maste 1017a85fe12eSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) { 1018a85fe12eSEd Maste elferr = elf_errno(); 1019a85fe12eSEd Maste if (elferr != 0) 1020a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1021a85fe12eSEd Maste elf_errmsg(elferr)); 1022a85fe12eSEd Maste return; 1023a85fe12eSEd Maste } 1024a85fe12eSEd Maste 1025a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 1026a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1027a85fe12eSEd Maste elf_errmsg(-1)); 1028a85fe12eSEd Maste 1029a85fe12eSEd Maste if (s->nocopy) { 1030a85fe12eSEd Maste /* Use s->buf as content if s->nocopy is set. */ 1031a85fe12eSEd Maste od->d_align = id->d_align; 1032a85fe12eSEd Maste od->d_off = 0; 1033a85fe12eSEd Maste od->d_buf = s->buf; 1034a85fe12eSEd Maste od->d_type = id->d_type; 1035a85fe12eSEd Maste od->d_size = s->sz; 1036a85fe12eSEd Maste od->d_version = id->d_version; 1037a85fe12eSEd Maste } else { 1038a85fe12eSEd Maste od->d_align = id->d_align; 1039a85fe12eSEd Maste od->d_off = id->d_off; 1040a85fe12eSEd Maste od->d_buf = id->d_buf; 1041a85fe12eSEd Maste od->d_type = id->d_type; 1042a85fe12eSEd Maste od->d_size = id->d_size; 1043a85fe12eSEd Maste od->d_version = id->d_version; 1044a85fe12eSEd Maste } 1045a85fe12eSEd Maste } 1046a85fe12eSEd Maste 1047a85fe12eSEd Maste struct section * 1048a85fe12eSEd Maste create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1049a85fe12eSEd Maste void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1050a85fe12eSEd Maste uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1051a85fe12eSEd Maste { 1052a85fe12eSEd Maste struct section *s; 1053a85fe12eSEd Maste Elf_Scn *os; 1054a85fe12eSEd Maste Elf_Data *od; 1055a85fe12eSEd Maste GElf_Shdr osh; 1056a85fe12eSEd Maste 1057a85fe12eSEd Maste if ((os = elf_newscn(ecp->eout)) == NULL) 1058a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1059a85fe12eSEd Maste elf_errmsg(-1)); 1060a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 1061a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1062a85fe12eSEd Maste s->name = name; 1063a85fe12eSEd Maste s->newname = newname; /* needs to be free()'ed */ 1064a85fe12eSEd Maste s->off = off; 1065a85fe12eSEd Maste s->sz = size; 1066a85fe12eSEd Maste s->vma = vma; 1067a85fe12eSEd Maste s->align = align; 1068a85fe12eSEd Maste s->loadable = loadable; 1069a85fe12eSEd Maste s->is = NULL; 1070a85fe12eSEd Maste s->os = os; 1071a85fe12eSEd Maste s->type = stype; 1072a85fe12eSEd Maste s->nocopy = 1; 1073a85fe12eSEd Maste insert_to_sec_list(ecp, s, 1); 1074a85fe12eSEd Maste 1075a85fe12eSEd Maste if (gelf_getshdr(os, &osh) == NULL) 1076a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1077a85fe12eSEd Maste elf_errmsg(-1)); 1078a85fe12eSEd Maste osh.sh_flags = flags; 1079a85fe12eSEd Maste osh.sh_type = s->type; 1080a85fe12eSEd Maste osh.sh_addr = s->vma; 1081a85fe12eSEd Maste osh.sh_addralign = s->align; 1082a85fe12eSEd Maste if (!gelf_update_shdr(os, &osh)) 1083a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1084a85fe12eSEd Maste elf_errmsg(-1)); 1085a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1086a85fe12eSEd Maste 1087a85fe12eSEd Maste if (buf != NULL && size != 0) { 1088a85fe12eSEd Maste if ((od = elf_newdata(os)) == NULL) 1089a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1090a85fe12eSEd Maste elf_errmsg(-1)); 1091a85fe12eSEd Maste od->d_align = align; 1092a85fe12eSEd Maste od->d_off = 0; 1093a85fe12eSEd Maste od->d_buf = buf; 1094a85fe12eSEd Maste od->d_size = size; 1095a85fe12eSEd Maste od->d_type = dtype; 1096a85fe12eSEd Maste od->d_version = EV_CURRENT; 1097a85fe12eSEd Maste } 1098a85fe12eSEd Maste 1099a85fe12eSEd Maste /* 1100a85fe12eSEd Maste * Clear SYMTAB_INTACT, as we probably need to update/add new 1101a85fe12eSEd Maste * STT_SECTION symbols into the symbol table. 1102a85fe12eSEd Maste */ 1103a85fe12eSEd Maste ecp->flags &= ~SYMTAB_INTACT; 1104a85fe12eSEd Maste 1105a85fe12eSEd Maste return (s); 1106a85fe12eSEd Maste } 1107a85fe12eSEd Maste 1108a85fe12eSEd Maste /* 1109a85fe12eSEd Maste * Insert sections specified by --add-section to the end of section list. 1110a85fe12eSEd Maste */ 1111a85fe12eSEd Maste static void 1112a85fe12eSEd Maste insert_sections(struct elfcopy *ecp) 1113a85fe12eSEd Maste { 1114a85fe12eSEd Maste struct sec_add *sa; 1115a85fe12eSEd Maste struct section *s; 1116a85fe12eSEd Maste size_t off; 1117a85fe12eSEd Maste 1118a85fe12eSEd Maste /* Put these sections in the end of current list. */ 1119a85fe12eSEd Maste off = 0; 1120a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1121a85fe12eSEd Maste if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1122a85fe12eSEd Maste off = s->off + s->sz; 1123a85fe12eSEd Maste else 1124a85fe12eSEd Maste off = s->off; 1125a85fe12eSEd Maste } 1126a85fe12eSEd Maste 1127a85fe12eSEd Maste STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1128a85fe12eSEd Maste 1129a85fe12eSEd Maste /* TODO: Add section header vma/lma, flag changes here */ 1130a85fe12eSEd Maste 1131a85fe12eSEd Maste (void) create_external_section(ecp, sa->name, NULL, sa->content, 1132a85fe12eSEd Maste sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); 1133a85fe12eSEd Maste } 1134a85fe12eSEd Maste } 1135a85fe12eSEd Maste 1136a85fe12eSEd Maste void 1137a85fe12eSEd Maste add_to_shstrtab(struct elfcopy *ecp, const char *name) 1138a85fe12eSEd Maste { 1139a85fe12eSEd Maste struct section *s; 1140a85fe12eSEd Maste 1141a85fe12eSEd Maste s = ecp->shstrtab; 1142a85fe12eSEd Maste insert_to_strtab(s, name); 1143a85fe12eSEd Maste } 1144a85fe12eSEd Maste 1145a85fe12eSEd Maste void 1146a85fe12eSEd Maste update_shdr(struct elfcopy *ecp, int update_link) 1147a85fe12eSEd Maste { 1148a85fe12eSEd Maste struct section *s; 1149a85fe12eSEd Maste GElf_Shdr osh; 1150a85fe12eSEd Maste int elferr; 1151a85fe12eSEd Maste 1152a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1153a85fe12eSEd Maste if (s->pseudo) 1154a85fe12eSEd Maste continue; 1155a85fe12eSEd Maste 1156a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 1157a85fe12eSEd Maste errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", 1158a85fe12eSEd Maste elf_errmsg(-1)); 1159a85fe12eSEd Maste 1160a85fe12eSEd Maste /* Find section name in string table and set sh_name. */ 1161a85fe12eSEd Maste osh.sh_name = lookup_string(ecp->shstrtab, s->name); 1162a85fe12eSEd Maste 1163a85fe12eSEd Maste /* 1164a85fe12eSEd Maste * sh_link needs to be updated, since the index of the 1165a85fe12eSEd Maste * linked section might have changed. 1166a85fe12eSEd Maste */ 1167a85fe12eSEd Maste if (update_link && osh.sh_link != 0) 1168a85fe12eSEd Maste osh.sh_link = ecp->secndx[osh.sh_link]; 1169a85fe12eSEd Maste 1170a85fe12eSEd Maste /* 1171a85fe12eSEd Maste * sh_info of relocation section links to the section to which 1172a85fe12eSEd Maste * its relocation info applies. So it may need update as well. 1173a85fe12eSEd Maste */ 1174a85fe12eSEd Maste if ((s->type == SHT_REL || s->type == SHT_RELA) && 1175a85fe12eSEd Maste osh.sh_info != 0) 1176a85fe12eSEd Maste osh.sh_info = ecp->secndx[osh.sh_info]; 1177a85fe12eSEd Maste 1178a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1179a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1180a85fe12eSEd Maste elf_errmsg(-1)); 1181a85fe12eSEd Maste } 1182a85fe12eSEd Maste elferr = elf_errno(); 1183a85fe12eSEd Maste if (elferr != 0) 1184a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1185a85fe12eSEd Maste elf_errmsg(elferr)); 1186a85fe12eSEd Maste } 1187a85fe12eSEd Maste 1188a85fe12eSEd Maste void 1189a85fe12eSEd Maste init_shstrtab(struct elfcopy *ecp) 1190a85fe12eSEd Maste { 1191a85fe12eSEd Maste struct section *s; 1192a85fe12eSEd Maste 1193a85fe12eSEd Maste if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1194a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1195a85fe12eSEd Maste s = ecp->shstrtab; 1196a85fe12eSEd Maste s->name = ".shstrtab"; 1197a85fe12eSEd Maste s->is = NULL; 1198a85fe12eSEd Maste s->sz = 0; 1199a85fe12eSEd Maste s->align = 1; 1200a85fe12eSEd Maste s->loadable = 0; 1201a85fe12eSEd Maste s->type = SHT_STRTAB; 1202a85fe12eSEd Maste s->vma = 0; 1203*9ef62fdbSEd Maste 1204*9ef62fdbSEd Maste insert_to_strtab(s, ""); 1205*9ef62fdbSEd Maste insert_to_strtab(s, ".symtab"); 1206*9ef62fdbSEd Maste insert_to_strtab(s, ".strtab"); 1207*9ef62fdbSEd Maste insert_to_strtab(s, ".shstrtab"); 1208a85fe12eSEd Maste } 1209a85fe12eSEd Maste 1210a85fe12eSEd Maste void 1211a85fe12eSEd Maste set_shstrtab(struct elfcopy *ecp) 1212a85fe12eSEd Maste { 1213a85fe12eSEd Maste struct section *s; 1214a85fe12eSEd Maste Elf_Data *data; 1215a85fe12eSEd Maste GElf_Shdr sh; 1216a85fe12eSEd Maste 1217a85fe12eSEd Maste s = ecp->shstrtab; 1218a85fe12eSEd Maste 1219a85fe12eSEd Maste if (gelf_getshdr(s->os, &sh) == NULL) 1220a85fe12eSEd Maste errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", 1221a85fe12eSEd Maste elf_errmsg(-1)); 1222a85fe12eSEd Maste sh.sh_addr = 0; 1223a85fe12eSEd Maste sh.sh_addralign = 1; 1224a85fe12eSEd Maste sh.sh_offset = s->off; 1225a85fe12eSEd Maste sh.sh_type = SHT_STRTAB; 1226a85fe12eSEd Maste sh.sh_flags = 0; 1227a85fe12eSEd Maste sh.sh_entsize = 0; 1228a85fe12eSEd Maste sh.sh_info = 0; 1229a85fe12eSEd Maste sh.sh_link = 0; 1230a85fe12eSEd Maste 1231a85fe12eSEd Maste if ((data = elf_newdata(s->os)) == NULL) 1232a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1233a85fe12eSEd Maste elf_errmsg(-1)); 1234a85fe12eSEd Maste 1235a85fe12eSEd Maste /* 1236a85fe12eSEd Maste * If we don't have a symbol table, skip those a few bytes 1237a85fe12eSEd Maste * which are reserved for this in the beginning of shstrtab. 1238a85fe12eSEd Maste */ 1239a85fe12eSEd Maste if (!(ecp->flags & SYMTAB_EXIST)) { 1240a85fe12eSEd Maste s->sz -= sizeof(".symtab\0.strtab"); 1241a85fe12eSEd Maste memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), 1242a85fe12eSEd Maste s->sz); 1243a85fe12eSEd Maste } 1244a85fe12eSEd Maste 1245a85fe12eSEd Maste sh.sh_size = s->sz; 1246a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &sh)) 1247a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1248a85fe12eSEd Maste elf_errmsg(-1)); 1249a85fe12eSEd Maste 1250a85fe12eSEd Maste data->d_align = 1; 1251a85fe12eSEd Maste data->d_buf = s->buf; 1252a85fe12eSEd Maste data->d_size = s->sz; 1253a85fe12eSEd Maste data->d_off = 0; 1254a85fe12eSEd Maste data->d_type = ELF_T_BYTE; 1255a85fe12eSEd Maste data->d_version = EV_CURRENT; 1256a85fe12eSEd Maste 1257a85fe12eSEd Maste if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1258a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1259a85fe12eSEd Maste elf_errmsg(-1)); 1260a85fe12eSEd Maste } 1261a85fe12eSEd Maste 1262a85fe12eSEd Maste void 1263a85fe12eSEd Maste add_section(struct elfcopy *ecp, const char *arg) 1264a85fe12eSEd Maste { 1265a85fe12eSEd Maste struct sec_add *sa; 1266a85fe12eSEd Maste struct stat sb; 1267a85fe12eSEd Maste const char *s, *fn; 1268a85fe12eSEd Maste FILE *fp; 1269a85fe12eSEd Maste int len; 1270a85fe12eSEd Maste 1271a85fe12eSEd Maste if ((s = strchr(arg, '=')) == NULL) 1272a85fe12eSEd Maste errx(EXIT_FAILURE, 1273a85fe12eSEd Maste "illegal format for --add-section option"); 1274a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1275a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1276a85fe12eSEd Maste 1277a85fe12eSEd Maste len = s - arg; 1278a85fe12eSEd Maste if ((sa->name = malloc(len + 1)) == NULL) 1279a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1280a85fe12eSEd Maste strncpy(sa->name, arg, len); 1281a85fe12eSEd Maste sa->name[len] = '\0'; 1282a85fe12eSEd Maste 1283a85fe12eSEd Maste fn = s + 1; 1284a85fe12eSEd Maste if (stat(fn, &sb) == -1) 1285a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1286a85fe12eSEd Maste sa->size = sb.st_size; 1287a85fe12eSEd Maste if ((sa->content = malloc(sa->size)) == NULL) 1288a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1289a85fe12eSEd Maste if ((fp = fopen(fn, "r")) == NULL) 1290a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", fn); 1291a85fe12eSEd Maste if (fread(sa->content, 1, sa->size, fp) == 0 || 1292a85fe12eSEd Maste ferror(fp)) 1293a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1294a85fe12eSEd Maste fclose(fp); 1295a85fe12eSEd Maste 1296a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1297a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1298a85fe12eSEd Maste } 1299a85fe12eSEd Maste 1300a85fe12eSEd Maste void 1301a85fe12eSEd Maste free_sec_add(struct elfcopy *ecp) 1302a85fe12eSEd Maste { 1303a85fe12eSEd Maste struct sec_add *sa, *sa_temp; 1304a85fe12eSEd Maste 1305a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1306a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1307a85fe12eSEd Maste free(sa->name); 1308a85fe12eSEd Maste free(sa->content); 1309a85fe12eSEd Maste free(sa); 1310a85fe12eSEd Maste } 1311a85fe12eSEd Maste } 1312a85fe12eSEd Maste 1313a85fe12eSEd Maste static void 1314a85fe12eSEd Maste add_gnu_debuglink(struct elfcopy *ecp) 1315a85fe12eSEd Maste { 1316a85fe12eSEd Maste struct sec_add *sa; 1317a85fe12eSEd Maste struct stat sb; 1318a85fe12eSEd Maste FILE *fp; 1319a85fe12eSEd Maste char *fnbase, *buf; 1320a85fe12eSEd Maste int crc_off; 1321a85fe12eSEd Maste int crc; 1322a85fe12eSEd Maste 1323a85fe12eSEd Maste if (ecp->debuglink == NULL) 1324a85fe12eSEd Maste return; 1325a85fe12eSEd Maste 1326a85fe12eSEd Maste /* Read debug file content. */ 1327a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1328a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1329a85fe12eSEd Maste if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1330a85fe12eSEd Maste err(EXIT_FAILURE, "strdup failed"); 1331a85fe12eSEd Maste if (stat(ecp->debuglink, &sb) == -1) 1332a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1333a85fe12eSEd Maste if ((buf = malloc(sb.st_size)) == NULL) 1334a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1335a85fe12eSEd Maste if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1336a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1337a85fe12eSEd Maste if (fread(buf, 1, sb.st_size, fp) == 0 || 1338a85fe12eSEd Maste ferror(fp)) 1339a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1340a85fe12eSEd Maste fclose(fp); 1341a85fe12eSEd Maste 1342a85fe12eSEd Maste /* Calculate crc checksum. */ 1343a85fe12eSEd Maste crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1344a85fe12eSEd Maste free(buf); 1345a85fe12eSEd Maste 1346a85fe12eSEd Maste /* Calculate section size and the offset to store crc checksum. */ 1347a85fe12eSEd Maste if ((fnbase = basename(ecp->debuglink)) == NULL) 1348a85fe12eSEd Maste err(EXIT_FAILURE, "basename failed"); 1349a85fe12eSEd Maste crc_off = roundup(strlen(fnbase) + 1, 4); 1350a85fe12eSEd Maste sa->size = crc_off + 4; 1351a85fe12eSEd Maste 1352a85fe12eSEd Maste /* Section content. */ 1353a85fe12eSEd Maste if ((sa->content = calloc(1, sa->size)) == NULL) 1354a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1355a85fe12eSEd Maste strncpy(sa->content, fnbase, strlen(fnbase)); 1356a85fe12eSEd Maste if (ecp->oed == ELFDATA2LSB) { 1357a85fe12eSEd Maste sa->content[crc_off] = crc & 0xFF; 1358a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1359a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1360a85fe12eSEd Maste sa->content[crc_off + 3] = crc >> 24; 1361a85fe12eSEd Maste } else { 1362a85fe12eSEd Maste sa->content[crc_off] = crc >> 24; 1363a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1364a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1365a85fe12eSEd Maste sa->content[crc_off + 3] = crc & 0xFF; 1366a85fe12eSEd Maste } 1367a85fe12eSEd Maste 1368a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1369a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1370a85fe12eSEd Maste } 1371a85fe12eSEd Maste 1372a85fe12eSEd Maste static void 1373a85fe12eSEd Maste insert_to_strtab(struct section *t, const char *s) 1374a85fe12eSEd Maste { 1375a85fe12eSEd Maste const char *r; 1376a85fe12eSEd Maste char *b, *c; 1377a85fe12eSEd Maste size_t len, slen; 1378a85fe12eSEd Maste int append; 1379a85fe12eSEd Maste 1380a85fe12eSEd Maste if (t->sz == 0) { 1381a85fe12eSEd Maste t->cap = 512; 1382a85fe12eSEd Maste if ((t->buf = malloc(t->cap)) == NULL) 1383a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1384a85fe12eSEd Maste } 1385a85fe12eSEd Maste 1386a85fe12eSEd Maste slen = strlen(s); 1387a85fe12eSEd Maste append = 0; 1388a85fe12eSEd Maste b = t->buf; 1389a85fe12eSEd Maste for (c = b; c < b + t->sz;) { 1390a85fe12eSEd Maste len = strlen(c); 1391a85fe12eSEd Maste if (!append && len >= slen) { 1392a85fe12eSEd Maste r = c + (len - slen); 1393a85fe12eSEd Maste if (strcmp(r, s) == 0) 1394a85fe12eSEd Maste return; 1395a85fe12eSEd Maste } else if (len < slen && len != 0) { 1396a85fe12eSEd Maste r = s + (slen - len); 1397a85fe12eSEd Maste if (strcmp(c, r) == 0) { 1398a85fe12eSEd Maste t->sz -= len + 1; 1399a85fe12eSEd Maste memmove(c, c + len + 1, t->sz - (c - b)); 1400a85fe12eSEd Maste append = 1; 1401a85fe12eSEd Maste continue; 1402a85fe12eSEd Maste } 1403a85fe12eSEd Maste } 1404a85fe12eSEd Maste c += len + 1; 1405a85fe12eSEd Maste } 1406a85fe12eSEd Maste 1407a85fe12eSEd Maste while (t->sz + slen + 1 >= t->cap) { 1408a85fe12eSEd Maste t->cap *= 2; 1409a85fe12eSEd Maste if ((t->buf = realloc(t->buf, t->cap)) == NULL) 1410a85fe12eSEd Maste err(EXIT_FAILURE, "realloc failed"); 1411a85fe12eSEd Maste } 1412a85fe12eSEd Maste b = t->buf; 1413a85fe12eSEd Maste strncpy(&b[t->sz], s, slen); 1414a85fe12eSEd Maste b[t->sz + slen] = '\0'; 1415a85fe12eSEd Maste t->sz += slen + 1; 1416a85fe12eSEd Maste } 1417a85fe12eSEd Maste 1418a85fe12eSEd Maste static int 1419a85fe12eSEd Maste lookup_string(struct section *t, const char *s) 1420a85fe12eSEd Maste { 1421a85fe12eSEd Maste const char *b, *c, *r; 1422a85fe12eSEd Maste size_t len, slen; 1423a85fe12eSEd Maste 1424a85fe12eSEd Maste slen = strlen(s); 1425a85fe12eSEd Maste b = t->buf; 1426a85fe12eSEd Maste for (c = b; c < b + t->sz;) { 1427a85fe12eSEd Maste len = strlen(c); 1428a85fe12eSEd Maste if (len >= slen) { 1429a85fe12eSEd Maste r = c + (len - slen); 1430a85fe12eSEd Maste if (strcmp(r, s) == 0) 1431a85fe12eSEd Maste return (r - b); 1432a85fe12eSEd Maste } 1433a85fe12eSEd Maste c += len + 1; 1434a85fe12eSEd Maste } 1435a85fe12eSEd Maste 1436a85fe12eSEd Maste return (-1); 1437a85fe12eSEd Maste } 1438a85fe12eSEd Maste 1439a85fe12eSEd Maste static uint32_t crctable[256] = 1440a85fe12eSEd Maste { 1441a85fe12eSEd Maste 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1442a85fe12eSEd Maste 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1443a85fe12eSEd Maste 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1444a85fe12eSEd Maste 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1445a85fe12eSEd Maste 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1446a85fe12eSEd Maste 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1447a85fe12eSEd Maste 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1448a85fe12eSEd Maste 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1449a85fe12eSEd Maste 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1450a85fe12eSEd Maste 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1451a85fe12eSEd Maste 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1452a85fe12eSEd Maste 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1453a85fe12eSEd Maste 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1454a85fe12eSEd Maste 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1455a85fe12eSEd Maste 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1456a85fe12eSEd Maste 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1457a85fe12eSEd Maste 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1458a85fe12eSEd Maste 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1459a85fe12eSEd Maste 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1460a85fe12eSEd Maste 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1461a85fe12eSEd Maste 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1462a85fe12eSEd Maste 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1463a85fe12eSEd Maste 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1464a85fe12eSEd Maste 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1465a85fe12eSEd Maste 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1466a85fe12eSEd Maste 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1467a85fe12eSEd Maste 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1468a85fe12eSEd Maste 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1469a85fe12eSEd Maste 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1470a85fe12eSEd Maste 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1471a85fe12eSEd Maste 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1472a85fe12eSEd Maste 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1473a85fe12eSEd Maste 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1474a85fe12eSEd Maste 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1475a85fe12eSEd Maste 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1476a85fe12eSEd Maste 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1477a85fe12eSEd Maste 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1478a85fe12eSEd Maste 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1479a85fe12eSEd Maste 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1480a85fe12eSEd Maste 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1481a85fe12eSEd Maste 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1482a85fe12eSEd Maste 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1483a85fe12eSEd Maste 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1484a85fe12eSEd Maste 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1485a85fe12eSEd Maste 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1486a85fe12eSEd Maste 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1487a85fe12eSEd Maste 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1488a85fe12eSEd Maste 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1489a85fe12eSEd Maste 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1490a85fe12eSEd Maste 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1491a85fe12eSEd Maste 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1492a85fe12eSEd Maste 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1493a85fe12eSEd Maste 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1494a85fe12eSEd Maste 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1495a85fe12eSEd Maste 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1496a85fe12eSEd Maste 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1497a85fe12eSEd Maste 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1498a85fe12eSEd Maste 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1499a85fe12eSEd Maste 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1500a85fe12eSEd Maste 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1501a85fe12eSEd Maste 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1502a85fe12eSEd Maste 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1503a85fe12eSEd Maste 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1504a85fe12eSEd Maste 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1505a85fe12eSEd Maste }; 1506a85fe12eSEd Maste 1507a85fe12eSEd Maste static uint32_t 1508a85fe12eSEd Maste calc_crc32(const char *p, size_t len, uint32_t crc) 1509a85fe12eSEd Maste { 1510a85fe12eSEd Maste uint32_t i; 1511a85fe12eSEd Maste 1512a85fe12eSEd Maste for (i = 0; i < len; i++) { 1513a85fe12eSEd Maste crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1514a85fe12eSEd Maste } 1515a85fe12eSEd Maste 1516a85fe12eSEd Maste return (crc ^ 0xFFFFFFFF); 1517a85fe12eSEd Maste } 1518