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 37*839529caSEd Maste ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $"); 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); 42a85fe12eSEd 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 void insert_to_strtab(struct section *t, const char *s); 46a85fe12eSEd Maste static int is_append_section(struct elfcopy *ecp, const char *name); 47a85fe12eSEd Maste static int is_compress_section(struct elfcopy *ecp, const char *name); 48a85fe12eSEd Maste static int is_debug_section(const char *name); 4967d97fe7SEd Maste static int is_dwo_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); 593ef90571SEd Maste static void update_section_group(struct elfcopy *ecp, struct section *s); 60a85fe12eSEd Maste 61a85fe12eSEd Maste int 62a85fe12eSEd Maste is_remove_section(struct elfcopy *ecp, const char *name) 63a85fe12eSEd Maste { 64a85fe12eSEd Maste 65a85fe12eSEd Maste /* Always keep section name table */ 66a85fe12eSEd Maste if (strcmp(name, ".shstrtab") == 0) 67a85fe12eSEd Maste return 0; 68a85fe12eSEd Maste if (strcmp(name, ".symtab") == 0 || 69a85fe12eSEd Maste strcmp(name, ".strtab") == 0) { 70a85fe12eSEd Maste if (ecp->strip == STRIP_ALL && lookup_symop_list( 71a85fe12eSEd Maste ecp, NULL, SYMOP_KEEP) == NULL) 72a85fe12eSEd Maste return (1); 73a85fe12eSEd Maste else 74a85fe12eSEd Maste return (0); 75a85fe12eSEd Maste } 76a85fe12eSEd Maste 7767d97fe7SEd Maste if (ecp->strip == STRIP_DWO && is_dwo_section(name)) 7867d97fe7SEd Maste return (1); 7967d97fe7SEd Maste if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name)) 8067d97fe7SEd Maste return (1); 8167d97fe7SEd Maste 82a85fe12eSEd Maste if (is_debug_section(name)) { 83a85fe12eSEd Maste if (ecp->strip == STRIP_ALL || 84a85fe12eSEd Maste ecp->strip == STRIP_DEBUG || 85a85fe12eSEd Maste ecp->strip == STRIP_UNNEEDED || 86a85fe12eSEd Maste (ecp->flags & DISCARD_LOCAL)) 87a85fe12eSEd Maste return (1); 88a85fe12eSEd Maste if (ecp->strip == STRIP_NONDEBUG) 89a85fe12eSEd Maste return (0); 90a85fe12eSEd Maste } 91a85fe12eSEd Maste 92a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { 93a85fe12eSEd Maste struct sec_action *sac; 94a85fe12eSEd Maste 95a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 96a85fe12eSEd Maste if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) 97a85fe12eSEd Maste return (1); 98a85fe12eSEd Maste if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) 99a85fe12eSEd Maste return (1); 100a85fe12eSEd Maste } 101a85fe12eSEd Maste 102a85fe12eSEd Maste return (0); 103a85fe12eSEd Maste } 104a85fe12eSEd Maste 105a85fe12eSEd Maste /* 106a85fe12eSEd Maste * Relocation section needs to be removed if the section it applies to 107a85fe12eSEd Maste * will be removed. 108a85fe12eSEd Maste */ 109a85fe12eSEd Maste int 110a85fe12eSEd Maste is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) 111a85fe12eSEd Maste { 112a85fe12eSEd Maste const char *name; 113a85fe12eSEd Maste GElf_Shdr ish; 114a85fe12eSEd Maste Elf_Scn *is; 115a85fe12eSEd Maste size_t indx; 116a85fe12eSEd Maste int elferr; 117a85fe12eSEd Maste 118a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 119a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 120a85fe12eSEd Maste elf_errmsg(-1)); 121a85fe12eSEd Maste 122a85fe12eSEd Maste is = NULL; 123a85fe12eSEd Maste while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 124a85fe12eSEd Maste if (sh_info == elf_ndxscn(is)) { 125a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 126a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 127a85fe12eSEd Maste elf_errmsg(-1)); 128a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == 129a85fe12eSEd Maste NULL) 130a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 131a85fe12eSEd Maste elf_errmsg(-1)); 132a85fe12eSEd Maste if (is_remove_section(ecp, name)) 133a85fe12eSEd Maste return (1); 134a85fe12eSEd Maste else 135a85fe12eSEd Maste return (0); 136a85fe12eSEd Maste } 137a85fe12eSEd Maste } 138a85fe12eSEd Maste elferr = elf_errno(); 139a85fe12eSEd Maste if (elferr != 0) 140a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 141a85fe12eSEd Maste elf_errmsg(elferr)); 142a85fe12eSEd Maste 143a85fe12eSEd Maste /* Remove reloc section if we can't find the target section. */ 144a85fe12eSEd Maste return (1); 145a85fe12eSEd Maste } 146a85fe12eSEd Maste 147a85fe12eSEd Maste static int 148a85fe12eSEd Maste is_append_section(struct elfcopy *ecp, const char *name) 149a85fe12eSEd Maste { 150a85fe12eSEd Maste struct sec_action *sac; 151a85fe12eSEd Maste 152a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 153a85fe12eSEd Maste if (sac != NULL && sac->append != 0 && sac->string != NULL) 154a85fe12eSEd Maste return (1); 155a85fe12eSEd Maste 156a85fe12eSEd Maste return (0); 157a85fe12eSEd Maste } 158a85fe12eSEd Maste 159a85fe12eSEd Maste static int 160a85fe12eSEd Maste is_compress_section(struct elfcopy *ecp, const char *name) 161a85fe12eSEd Maste { 162a85fe12eSEd Maste struct sec_action *sac; 163a85fe12eSEd Maste 164a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 165a85fe12eSEd Maste if (sac != NULL && sac->compress != 0) 166a85fe12eSEd Maste return (1); 167a85fe12eSEd Maste 168a85fe12eSEd Maste return (0); 169a85fe12eSEd Maste } 170a85fe12eSEd Maste 171a85fe12eSEd Maste static void 172a85fe12eSEd Maste check_section_rename(struct elfcopy *ecp, struct section *s) 173a85fe12eSEd Maste { 174a85fe12eSEd Maste struct sec_action *sac; 175a85fe12eSEd Maste char *prefix; 176a85fe12eSEd Maste size_t namelen; 177a85fe12eSEd Maste 178a85fe12eSEd Maste if (s->pseudo) 179a85fe12eSEd Maste return; 180a85fe12eSEd Maste 181a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 182a85fe12eSEd Maste if (sac != NULL && sac->rename) 183a85fe12eSEd Maste s->name = sac->newname; 184a85fe12eSEd Maste 185a85fe12eSEd Maste if (!strcmp(s->name, ".symtab") || 186a85fe12eSEd Maste !strcmp(s->name, ".strtab") || 187a85fe12eSEd Maste !strcmp(s->name, ".shstrtab")) 188a85fe12eSEd Maste return; 189a85fe12eSEd Maste 190a85fe12eSEd Maste prefix = NULL; 191a85fe12eSEd Maste if (s->loadable && ecp->prefix_alloc != NULL) 192a85fe12eSEd Maste prefix = ecp->prefix_alloc; 193a85fe12eSEd Maste else if (ecp->prefix_sec != NULL) 194a85fe12eSEd Maste prefix = ecp->prefix_sec; 195a85fe12eSEd Maste 196a85fe12eSEd Maste if (prefix != NULL) { 197a85fe12eSEd Maste namelen = strlen(s->name) + strlen(prefix) + 1; 198a85fe12eSEd Maste if ((s->newname = malloc(namelen)) == NULL) 199a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 200a85fe12eSEd Maste snprintf(s->newname, namelen, "%s%s", prefix, s->name); 201a85fe12eSEd Maste s->name = s->newname; 202a85fe12eSEd Maste } 203a85fe12eSEd Maste } 204a85fe12eSEd Maste 205a85fe12eSEd Maste static int 206a85fe12eSEd Maste get_section_flags(struct elfcopy *ecp, const char *name) 207a85fe12eSEd Maste { 208a85fe12eSEd Maste struct sec_action *sac; 209a85fe12eSEd Maste 210a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 211a85fe12eSEd Maste if (sac != NULL && sac->flags) 212a85fe12eSEd Maste return sac->flags; 213a85fe12eSEd Maste 214a85fe12eSEd Maste return (0); 215a85fe12eSEd Maste } 216a85fe12eSEd Maste 217a85fe12eSEd Maste /* 218a85fe12eSEd Maste * Determine whether the section are debugging section. 219a85fe12eSEd Maste * According to libbfd, debugging sections are recognized 220a85fe12eSEd Maste * only by name. 221a85fe12eSEd Maste */ 222a85fe12eSEd Maste static int 223a85fe12eSEd Maste is_debug_section(const char *name) 224a85fe12eSEd Maste { 225a85fe12eSEd Maste const char *dbg_sec[] = { 226*839529caSEd Maste ".apple_", 227a85fe12eSEd Maste ".debug", 228a85fe12eSEd Maste ".gnu.linkonce.wi.", 229a85fe12eSEd Maste ".line", 230a85fe12eSEd Maste ".stab", 231a85fe12eSEd Maste NULL 232a85fe12eSEd Maste }; 233a85fe12eSEd Maste const char **p; 234a85fe12eSEd Maste 235a85fe12eSEd Maste for(p = dbg_sec; *p; p++) { 236a85fe12eSEd Maste if (strncmp(name, *p, strlen(*p)) == 0) 237a85fe12eSEd Maste return (1); 238a85fe12eSEd Maste } 239a85fe12eSEd Maste 240a85fe12eSEd Maste return (0); 241a85fe12eSEd Maste } 242a85fe12eSEd Maste 243a85fe12eSEd Maste static int 24467d97fe7SEd Maste is_dwo_section(const char *name) 24567d97fe7SEd Maste { 24667d97fe7SEd Maste size_t len; 24767d97fe7SEd Maste 24867d97fe7SEd Maste if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0) 24967d97fe7SEd Maste return (1); 25067d97fe7SEd Maste return (0); 25167d97fe7SEd Maste } 25267d97fe7SEd Maste 25367d97fe7SEd Maste static int 254a85fe12eSEd Maste is_print_section(struct elfcopy *ecp, const char *name) 255a85fe12eSEd Maste { 256a85fe12eSEd Maste struct sec_action *sac; 257a85fe12eSEd Maste 258a85fe12eSEd Maste sac = lookup_sec_act(ecp, name, 0); 259a85fe12eSEd Maste if (sac != NULL && sac->print != 0) 260a85fe12eSEd Maste return (1); 261a85fe12eSEd Maste 262a85fe12eSEd Maste return (0); 263a85fe12eSEd Maste } 264a85fe12eSEd Maste 265a85fe12eSEd Maste static int 266a85fe12eSEd Maste is_modify_section(struct elfcopy *ecp, const char *name) 267a85fe12eSEd Maste { 268a85fe12eSEd Maste 269a85fe12eSEd Maste if (is_append_section(ecp, name) || 270a85fe12eSEd Maste is_compress_section(ecp, name)) 271a85fe12eSEd Maste return (1); 272a85fe12eSEd Maste 273a85fe12eSEd Maste return (0); 274a85fe12eSEd Maste } 275a85fe12eSEd Maste 276a85fe12eSEd Maste struct sec_action* 277a85fe12eSEd Maste lookup_sec_act(struct elfcopy *ecp, const char *name, int add) 278a85fe12eSEd Maste { 279a85fe12eSEd Maste struct sec_action *sac; 280a85fe12eSEd Maste 281a85fe12eSEd Maste if (name == NULL) 282a85fe12eSEd Maste return NULL; 283a85fe12eSEd Maste 284a85fe12eSEd Maste STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 285a85fe12eSEd Maste if (strcmp(name, sac->name) == 0) 286a85fe12eSEd Maste return sac; 287a85fe12eSEd Maste } 288a85fe12eSEd Maste 289a85fe12eSEd Maste if (add == 0) 290a85fe12eSEd Maste return NULL; 291a85fe12eSEd Maste 292a85fe12eSEd Maste if ((sac = malloc(sizeof(*sac))) == NULL) 293a85fe12eSEd Maste errx(EXIT_FAILURE, "not enough memory"); 294a85fe12eSEd Maste memset(sac, 0, sizeof(*sac)); 295a85fe12eSEd Maste sac->name = name; 296a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); 297a85fe12eSEd Maste 298a85fe12eSEd Maste return (sac); 299a85fe12eSEd Maste } 300a85fe12eSEd Maste 301a85fe12eSEd Maste void 302a85fe12eSEd Maste free_sec_act(struct elfcopy *ecp) 303a85fe12eSEd Maste { 304a85fe12eSEd Maste struct sec_action *sac, *sac_temp; 305a85fe12eSEd Maste 306a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { 307a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); 308a85fe12eSEd Maste free(sac); 309a85fe12eSEd Maste } 310a85fe12eSEd Maste } 311a85fe12eSEd Maste 312a85fe12eSEd Maste void 313a85fe12eSEd Maste insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) 314a85fe12eSEd Maste { 315a85fe12eSEd Maste struct section *s; 316a85fe12eSEd Maste 317a85fe12eSEd Maste if (!tail) { 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); 321a85fe12eSEd Maste goto inc_nos; 322a85fe12eSEd Maste } 323a85fe12eSEd Maste } 324a85fe12eSEd Maste } 325a85fe12eSEd Maste 326a85fe12eSEd Maste TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); 327a85fe12eSEd Maste 328a85fe12eSEd Maste inc_nos: 329a85fe12eSEd Maste if (sec->pseudo == 0) 330a85fe12eSEd Maste ecp->nos++; 331a85fe12eSEd Maste } 332a85fe12eSEd Maste 333a85fe12eSEd Maste /* 334a85fe12eSEd Maste * First step of section creation: create scn and internal section 335a85fe12eSEd Maste * structure, discard sections to be removed. 336a85fe12eSEd Maste */ 337a85fe12eSEd Maste void 338a85fe12eSEd Maste create_scn(struct elfcopy *ecp) 339a85fe12eSEd Maste { 340a85fe12eSEd Maste struct section *s; 341a85fe12eSEd Maste const char *name; 342a85fe12eSEd Maste Elf_Scn *is; 343a85fe12eSEd Maste GElf_Shdr ish; 344a85fe12eSEd Maste size_t indx; 345a85fe12eSEd Maste uint64_t oldndx, newndx; 346a85fe12eSEd Maste int elferr, sec_flags; 347a85fe12eSEd Maste 348a85fe12eSEd Maste /* 349a85fe12eSEd Maste * Insert a pseudo section that contains the ELF header 350a85fe12eSEd Maste * and program header. Used as reference for section offset 351a85fe12eSEd Maste * or load address adjustment. 352a85fe12eSEd Maste */ 353a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 354a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 355a85fe12eSEd Maste s->off = 0; 356a85fe12eSEd Maste s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + 357a85fe12eSEd Maste gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); 358a85fe12eSEd Maste s->align = 1; 359a85fe12eSEd Maste s->pseudo = 1; 360a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 361a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 362a85fe12eSEd Maste 363a85fe12eSEd Maste /* Create internal .shstrtab section. */ 364a85fe12eSEd Maste init_shstrtab(ecp); 365a85fe12eSEd Maste 366a85fe12eSEd Maste if (elf_getshstrndx(ecp->ein, &indx) == 0) 367a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 368a85fe12eSEd Maste elf_errmsg(-1)); 369a85fe12eSEd Maste 370a85fe12eSEd Maste is = NULL; 371a85fe12eSEd Maste while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 372a85fe12eSEd Maste if (gelf_getshdr(is, &ish) == NULL) 373*839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 374a85fe12eSEd Maste elf_errmsg(-1)); 375a85fe12eSEd Maste if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) 376a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 377a85fe12eSEd Maste elf_errmsg(-1)); 378a85fe12eSEd Maste 379a85fe12eSEd Maste /* Skip sections to be removed. */ 380a85fe12eSEd Maste if (is_remove_section(ecp, name)) 381a85fe12eSEd Maste continue; 382a85fe12eSEd Maste 383a85fe12eSEd Maste /* 384a85fe12eSEd Maste * Relocation section need to be remove if the section 385a85fe12eSEd Maste * it applies will be removed. 386a85fe12eSEd Maste */ 387a85fe12eSEd Maste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 388a85fe12eSEd Maste if (ish.sh_info != 0 && 389a85fe12eSEd Maste is_remove_reloc_sec(ecp, ish.sh_info)) 390a85fe12eSEd Maste continue; 391a85fe12eSEd Maste 392cf781b2eSEd Maste /* 393cf781b2eSEd Maste * Section groups should be removed if symbol table will 394cf781b2eSEd Maste * be removed. (section group's signature stored in symbol 395cf781b2eSEd Maste * table) 396cf781b2eSEd Maste */ 397cf781b2eSEd Maste if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL) 398cf781b2eSEd Maste continue; 399cf781b2eSEd Maste 400a85fe12eSEd Maste /* Get section flags set by user. */ 401a85fe12eSEd Maste sec_flags = get_section_flags(ecp, name); 402a85fe12eSEd Maste 403a85fe12eSEd Maste /* Create internal section object. */ 404a85fe12eSEd Maste if (strcmp(name, ".shstrtab") != 0) { 405a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 406a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 407a85fe12eSEd Maste s->name = name; 408a85fe12eSEd Maste s->is = is; 409a85fe12eSEd Maste s->off = ish.sh_offset; 410a85fe12eSEd Maste s->sz = ish.sh_size; 411a85fe12eSEd Maste s->align = ish.sh_addralign; 412a85fe12eSEd Maste s->type = ish.sh_type; 413a85fe12eSEd Maste s->vma = ish.sh_addr; 414a85fe12eSEd Maste 415a85fe12eSEd Maste /* 416a85fe12eSEd Maste * Search program headers to determine whether section 417a85fe12eSEd Maste * is loadable, but if user explicitly set section flags 418a85fe12eSEd Maste * while neither "load" nor "alloc" is set, we make the 419a85fe12eSEd Maste * section unloadable. 420*839529caSEd Maste * 421*839529caSEd Maste * Sections in relocatable object is loadable if 422*839529caSEd Maste * section flag SHF_ALLOC is set. 423a85fe12eSEd Maste */ 424a85fe12eSEd Maste if (sec_flags && 425a85fe12eSEd Maste (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 426a85fe12eSEd Maste s->loadable = 0; 427*839529caSEd Maste else { 428a85fe12eSEd Maste s->loadable = add_to_inseg_list(ecp, s); 429*839529caSEd Maste if ((ecp->flags & RELOCATABLE) && 430*839529caSEd Maste (ish.sh_flags & SHF_ALLOC)) 431*839529caSEd Maste s->loadable = 1; 432*839529caSEd Maste } 433a85fe12eSEd Maste } else { 434a85fe12eSEd Maste /* Assuming .shstrtab is "unloadable". */ 435a85fe12eSEd Maste s = ecp->shstrtab; 436a85fe12eSEd Maste s->off = ish.sh_offset; 437a85fe12eSEd Maste } 438a85fe12eSEd Maste 439a85fe12eSEd Maste oldndx = newndx = SHN_UNDEF; 440a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 441a85fe12eSEd Maste strcmp(name, ".strtab") != 0) { 442a85fe12eSEd Maste if (!strcmp(name, ".shstrtab")) { 443a85fe12eSEd Maste /* 444a85fe12eSEd Maste * Add sections specified by --add-section and 445a85fe12eSEd Maste * gnu debuglink. we want these sections have 446a85fe12eSEd Maste * smaller index than .shstrtab section. 447a85fe12eSEd Maste */ 448a85fe12eSEd Maste if (ecp->debuglink != NULL) 449a85fe12eSEd Maste add_gnu_debuglink(ecp); 450a85fe12eSEd Maste if (ecp->flags & SEC_ADD) 451a85fe12eSEd Maste insert_sections(ecp); 452a85fe12eSEd Maste } 453a85fe12eSEd Maste if ((s->os = elf_newscn(ecp->eout)) == NULL) 454a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn failed: %s", 455a85fe12eSEd Maste elf_errmsg(-1)); 456a85fe12eSEd Maste if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 457a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 458a85fe12eSEd Maste elf_errmsg(-1)); 459a85fe12eSEd Maste } 460a85fe12eSEd Maste if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 461a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 462a85fe12eSEd Maste elf_errmsg(-1)); 463a85fe12eSEd Maste if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 464a85fe12eSEd Maste ecp->secndx[oldndx] = newndx; 465a85fe12eSEd Maste 466a85fe12eSEd Maste /* 467a85fe12eSEd Maste * If strip action is STRIP_NONDEBUG(only keep debug), 46895fd7f26SEd Maste * change sections type of loadable sections and section 46995fd7f26SEd Maste * groups to SHT_NOBITS, and the content of those sections 47095fd7f26SEd Maste * will be discarded. However, SHT_NOTE sections should 47195fd7f26SEd Maste * be kept. 472a85fe12eSEd Maste */ 47395fd7f26SEd Maste if (ecp->strip == STRIP_NONDEBUG) { 47495fd7f26SEd Maste if (((ish.sh_flags & SHF_ALLOC) || 47595fd7f26SEd Maste (ish.sh_flags & SHF_GROUP)) && 47695fd7f26SEd Maste ish.sh_type != SHT_NOTE) 477a85fe12eSEd Maste s->type = SHT_NOBITS; 47895fd7f26SEd Maste } 479a85fe12eSEd Maste 480a85fe12eSEd Maste check_section_rename(ecp, s); 481a85fe12eSEd Maste 482a85fe12eSEd Maste /* create section header based on input object. */ 483a85fe12eSEd Maste if (strcmp(name, ".symtab") != 0 && 484a85fe12eSEd Maste strcmp(name, ".strtab") != 0 && 485a85fe12eSEd Maste strcmp(name, ".shstrtab") != 0) 486a85fe12eSEd Maste copy_shdr(ecp, s, NULL, 0, sec_flags); 487a85fe12eSEd Maste 488a85fe12eSEd Maste if (strcmp(name, ".symtab") == 0) { 489a85fe12eSEd Maste ecp->flags |= SYMTAB_EXIST; 490a85fe12eSEd Maste ecp->symtab = s; 491a85fe12eSEd Maste } 492a85fe12eSEd Maste if (strcmp(name, ".strtab") == 0) 493a85fe12eSEd Maste ecp->strtab = s; 494a85fe12eSEd Maste 495a85fe12eSEd Maste insert_to_sec_list(ecp, s, 0); 496a85fe12eSEd Maste } 497a85fe12eSEd Maste elferr = elf_errno(); 498a85fe12eSEd Maste if (elferr != 0) 499a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 500a85fe12eSEd Maste elf_errmsg(elferr)); 501a85fe12eSEd Maste } 502a85fe12eSEd Maste 503a85fe12eSEd Maste struct section * 504a85fe12eSEd Maste insert_shtab(struct elfcopy *ecp, int tail) 505a85fe12eSEd Maste { 506a85fe12eSEd Maste struct section *s, *shtab; 507a85fe12eSEd Maste GElf_Ehdr ieh; 508a85fe12eSEd Maste int nsecs; 509a85fe12eSEd Maste 510a85fe12eSEd Maste /* 511a85fe12eSEd Maste * Treat section header table as a "pseudo" section, insert it 512a85fe12eSEd Maste * into section list, so later it will get sorted and resynced 513a85fe12eSEd Maste * just as normal sections. 514a85fe12eSEd Maste */ 515a85fe12eSEd Maste if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 516a85fe12eSEd Maste errx(EXIT_FAILURE, "calloc failed"); 517a85fe12eSEd Maste if (!tail) { 5184a85c691SEd Maste /* 5194a85c691SEd Maste * "shoff" of input object is used as a hint for section 5204a85c691SEd Maste * resync later. 5214a85c691SEd Maste */ 522a85fe12eSEd Maste if (gelf_getehdr(ecp->ein, &ieh) == NULL) 523a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 524a85fe12eSEd Maste elf_errmsg(-1)); 525a85fe12eSEd Maste shtab->off = ieh.e_shoff; 526a85fe12eSEd Maste } else 527a85fe12eSEd Maste shtab->off = 0; 528a85fe12eSEd Maste /* Calculate number of sections in the output object. */ 529a85fe12eSEd Maste nsecs = 0; 530a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 531a85fe12eSEd Maste if (!s->pseudo) 532a85fe12eSEd Maste nsecs++; 533a85fe12eSEd Maste } 534a85fe12eSEd Maste /* Remember there is always a null section, so we +1 here. */ 535a85fe12eSEd Maste shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 536a85fe12eSEd Maste if (shtab->sz == 0) 537a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 538a85fe12eSEd Maste shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 539a85fe12eSEd Maste shtab->loadable = 0; 540a85fe12eSEd Maste shtab->pseudo = 1; 541a85fe12eSEd Maste insert_to_sec_list(ecp, shtab, tail); 542a85fe12eSEd Maste 543a85fe12eSEd Maste return (shtab); 544a85fe12eSEd Maste } 545a85fe12eSEd Maste 546a85fe12eSEd Maste void 547a85fe12eSEd Maste copy_content(struct elfcopy *ecp) 548a85fe12eSEd Maste { 549a85fe12eSEd Maste struct section *s; 550a85fe12eSEd Maste 551a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 552a85fe12eSEd Maste /* Skip pseudo section. */ 553a85fe12eSEd Maste if (s->pseudo) 554a85fe12eSEd Maste continue; 555a85fe12eSEd Maste 556a85fe12eSEd Maste /* Skip special sections. */ 557a85fe12eSEd Maste if (strcmp(s->name, ".symtab") == 0 || 558a85fe12eSEd Maste strcmp(s->name, ".strtab") == 0 || 559a85fe12eSEd Maste strcmp(s->name, ".shstrtab") == 0) 560a85fe12eSEd Maste continue; 561a85fe12eSEd Maste 562a85fe12eSEd Maste /* 563a85fe12eSEd Maste * If strip action is STRIP_ALL, relocation info need 564a85fe12eSEd Maste * to be stripped. Skip filtering otherwisw. 565a85fe12eSEd Maste */ 566a85fe12eSEd Maste if (ecp->strip == STRIP_ALL && 567a85fe12eSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 568a85fe12eSEd Maste filter_reloc(ecp, s); 569a85fe12eSEd Maste 5703ef90571SEd Maste /* 5713ef90571SEd Maste * The section indices in the SHT_GROUP section needs 5723ef90571SEd Maste * to be updated since we might have stripped some 5733ef90571SEd Maste * sections and changed section numbering. 5743ef90571SEd Maste */ 5753ef90571SEd Maste if (s->type == SHT_GROUP) 5763ef90571SEd Maste update_section_group(ecp, s); 5773ef90571SEd Maste 578a85fe12eSEd Maste if (is_modify_section(ecp, s->name)) 579a85fe12eSEd Maste modify_section(ecp, s); 580a85fe12eSEd Maste 581a85fe12eSEd Maste copy_data(s); 582a85fe12eSEd Maste 583a85fe12eSEd Maste /* 584a85fe12eSEd Maste * If symbol table is modified, relocation info might 585a85fe12eSEd Maste * need update, as symbol index may have changed. 586a85fe12eSEd Maste */ 587a85fe12eSEd Maste if ((ecp->flags & SYMTAB_INTACT) == 0 && 588a85fe12eSEd Maste (ecp->flags & SYMTAB_EXIST) && 589a85fe12eSEd Maste (s->type == SHT_REL || s->type == SHT_RELA)) 590a85fe12eSEd Maste update_reloc(ecp, s); 591a85fe12eSEd Maste 592a85fe12eSEd Maste if (is_print_section(ecp, s->name)) 593a85fe12eSEd Maste print_section(s); 594a85fe12eSEd Maste } 595a85fe12eSEd Maste } 596a85fe12eSEd Maste 5973ef90571SEd Maste 5983ef90571SEd Maste /* 5993ef90571SEd Maste * Update section group section. The section indices in the SHT_GROUP 6003ef90571SEd Maste * section need update after section numbering changed. 6013ef90571SEd Maste */ 6023ef90571SEd Maste static void 6033ef90571SEd Maste update_section_group(struct elfcopy *ecp, struct section *s) 6043ef90571SEd Maste { 6053ef90571SEd Maste GElf_Shdr ish; 6063ef90571SEd Maste Elf_Data *id; 6073ef90571SEd Maste uint32_t *ws, *wd; 6083ef90571SEd Maste uint64_t n; 6093ef90571SEd Maste size_t ishnum; 6103ef90571SEd Maste int i, j; 6113ef90571SEd Maste 6123ef90571SEd Maste if (!elf_getshnum(ecp->ein, &ishnum)) 6133ef90571SEd Maste errx(EXIT_FAILURE, "elf_getshnum failed: %s", 6143ef90571SEd Maste elf_errmsg(-1)); 6153ef90571SEd Maste 6163ef90571SEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 6173ef90571SEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 6183ef90571SEd Maste elf_errmsg(-1)); 6193ef90571SEd Maste 6203ef90571SEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) 6213ef90571SEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 6223ef90571SEd Maste elf_errmsg(-1)); 6233ef90571SEd Maste 6243ef90571SEd Maste if (ish.sh_size == 0) 6253ef90571SEd Maste return; 6263ef90571SEd Maste 6273ef90571SEd Maste if (ish.sh_entsize == 0) 6283ef90571SEd Maste ish.sh_entsize = 4; 6293ef90571SEd Maste 6303ef90571SEd Maste ws = id->d_buf; 6313ef90571SEd Maste 6323ef90571SEd Maste /* We only support COMDAT section. */ 6333ef90571SEd Maste #ifndef GRP_COMDAT 6343ef90571SEd Maste #define GRP_COMDAT 0x1 6353ef90571SEd Maste #endif 6363ef90571SEd Maste if ((*ws & GRP_COMDAT) == 0) 6373ef90571SEd Maste return; 6383ef90571SEd Maste 6393ef90571SEd Maste if ((s->buf = malloc(ish.sh_size)) == NULL) 6403ef90571SEd Maste err(EXIT_FAILURE, "malloc failed"); 6413ef90571SEd Maste 6423ef90571SEd Maste s->sz = ish.sh_size; 6433ef90571SEd Maste 6443ef90571SEd Maste wd = s->buf; 6453ef90571SEd Maste 6463ef90571SEd Maste /* Copy the flag word as-is. */ 6473ef90571SEd Maste *wd = *ws; 6483ef90571SEd Maste 6493ef90571SEd Maste /* Update the section indices. */ 6503ef90571SEd Maste n = ish.sh_size / ish.sh_entsize; 6513ef90571SEd Maste for(i = 1, j = 1; (uint64_t)i < n; i++) { 6523ef90571SEd Maste if (ws[i] != SHN_UNDEF && ws[i] < ishnum && 6533ef90571SEd Maste ecp->secndx[ws[i]] != 0) 6543ef90571SEd Maste wd[j++] = ecp->secndx[ws[i]]; 6553ef90571SEd Maste else 6563ef90571SEd Maste s->sz -= 4; 6573ef90571SEd Maste } 6583ef90571SEd Maste 6593ef90571SEd Maste s->nocopy = 1; 6603ef90571SEd Maste } 6613ef90571SEd Maste 662a85fe12eSEd Maste /* 663a85fe12eSEd Maste * Filter relocation entries, only keep those entries whose 664a85fe12eSEd Maste * symbol is in the keep list. 665a85fe12eSEd Maste */ 666a85fe12eSEd Maste static void 667a85fe12eSEd Maste filter_reloc(struct elfcopy *ecp, struct section *s) 668a85fe12eSEd Maste { 669a85fe12eSEd Maste const char *name; 670a85fe12eSEd Maste GElf_Shdr ish; 671a85fe12eSEd Maste GElf_Rel rel; 672a85fe12eSEd Maste GElf_Rela rela; 673a85fe12eSEd Maste Elf32_Rel *rel32; 674a85fe12eSEd Maste Elf64_Rel *rel64; 675a85fe12eSEd Maste Elf32_Rela *rela32; 676a85fe12eSEd Maste Elf64_Rela *rela64; 677a85fe12eSEd Maste Elf_Data *id; 678a85fe12eSEd Maste uint64_t cap, n, nrels; 679a85fe12eSEd Maste int elferr, i; 680a85fe12eSEd Maste 681a85fe12eSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 682a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 683a85fe12eSEd Maste elf_errmsg(-1)); 684a85fe12eSEd Maste 685a85fe12eSEd Maste /* We don't want to touch relocation info for dynamic symbols. */ 686a85fe12eSEd Maste if ((ecp->flags & SYMTAB_EXIST) == 0) { 687a85fe12eSEd Maste if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { 688a85fe12eSEd Maste /* 689a85fe12eSEd Maste * This reloc section applies to the symbol table 690a85fe12eSEd Maste * that was stripped, so discard whole section. 691a85fe12eSEd Maste */ 692a85fe12eSEd Maste s->nocopy = 1; 693a85fe12eSEd Maste s->sz = 0; 694a85fe12eSEd Maste } 695a85fe12eSEd Maste return; 696a85fe12eSEd Maste } else { 697a85fe12eSEd Maste /* Symbol table exist, check if index equals. */ 698a85fe12eSEd Maste if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 699a85fe12eSEd Maste return; 700a85fe12eSEd Maste } 701a85fe12eSEd Maste 702a85fe12eSEd Maste #define COPYREL(REL, SZ) do { \ 703a85fe12eSEd Maste if (nrels == 0) { \ 704a85fe12eSEd Maste if ((REL##SZ = malloc(cap * \ 705a85fe12eSEd Maste sizeof(Elf##SZ##_Rel))) == NULL) \ 706a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); \ 707a85fe12eSEd Maste } \ 708a85fe12eSEd Maste if (nrels >= cap) { \ 709a85fe12eSEd Maste cap *= 2; \ 710a85fe12eSEd Maste if ((REL##SZ = realloc(REL##SZ, cap * \ 711a85fe12eSEd Maste sizeof(Elf##SZ##_Rel))) == NULL) \ 712a85fe12eSEd Maste err(EXIT_FAILURE, "realloc failed"); \ 713a85fe12eSEd Maste } \ 714a85fe12eSEd Maste REL##SZ[nrels].r_offset = REL.r_offset; \ 715a85fe12eSEd Maste REL##SZ[nrels].r_info = REL.r_info; \ 716a85fe12eSEd Maste if (s->type == SHT_RELA) \ 717a85fe12eSEd Maste rela##SZ[nrels].r_addend = rela.r_addend; \ 718a85fe12eSEd Maste nrels++; \ 719a85fe12eSEd Maste } while (0) 720a85fe12eSEd Maste 721a85fe12eSEd Maste nrels = 0; 722a85fe12eSEd Maste cap = 4; /* keep list is usually small. */ 723a85fe12eSEd Maste rel32 = NULL; 724a85fe12eSEd Maste rel64 = NULL; 725a85fe12eSEd Maste rela32 = NULL; 726a85fe12eSEd Maste rela64 = NULL; 727a85fe12eSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) 728a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 729a85fe12eSEd Maste elf_errmsg(-1)); 730a85fe12eSEd Maste n = ish.sh_size / ish.sh_entsize; 731a85fe12eSEd Maste for(i = 0; (uint64_t)i < n; i++) { 732a85fe12eSEd Maste if (s->type == SHT_REL) { 733a85fe12eSEd Maste if (gelf_getrel(id, i, &rel) != &rel) 734a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 735a85fe12eSEd Maste elf_errmsg(-1)); 736a85fe12eSEd Maste } else { 737a85fe12eSEd Maste if (gelf_getrela(id, i, &rela) != &rela) 738a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getrel failed: %s", 739a85fe12eSEd Maste elf_errmsg(-1)); 740a85fe12eSEd Maste } 741a85fe12eSEd Maste name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 742a85fe12eSEd Maste GELF_R_SYM(rel.r_info)); 743a85fe12eSEd Maste if (name == NULL) 744a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_strptr failed: %s", 745a85fe12eSEd Maste elf_errmsg(-1)); 746a85fe12eSEd Maste if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { 747a85fe12eSEd Maste if (ecp->oec == ELFCLASS32) { 748a85fe12eSEd Maste if (s->type == SHT_REL) 749a85fe12eSEd Maste COPYREL(rel, 32); 750a85fe12eSEd Maste else 751a85fe12eSEd Maste COPYREL(rela, 32); 752a85fe12eSEd Maste } else { 753a85fe12eSEd Maste if (s->type == SHT_REL) 754a85fe12eSEd Maste COPYREL(rel, 64); 755a85fe12eSEd Maste else 756a85fe12eSEd Maste COPYREL(rela, 64); 757a85fe12eSEd Maste } 758a85fe12eSEd Maste } 759a85fe12eSEd Maste } 760a85fe12eSEd Maste elferr = elf_errno(); 761a85fe12eSEd Maste if (elferr != 0) 762a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 763a85fe12eSEd Maste elf_errmsg(elferr)); 764a85fe12eSEd Maste 765a85fe12eSEd Maste if (ecp->oec == ELFCLASS32) { 766a85fe12eSEd Maste if (s->type == SHT_REL) 767a85fe12eSEd Maste s->buf = rel32; 768a85fe12eSEd Maste else 769a85fe12eSEd Maste s->buf = rela32; 770a85fe12eSEd Maste } else { 771a85fe12eSEd Maste if (s->type == SHT_REL) 772a85fe12eSEd Maste s->buf = rel64; 773a85fe12eSEd Maste else 774a85fe12eSEd Maste s->buf = rela64; 775a85fe12eSEd Maste } 776a85fe12eSEd Maste s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 777a85fe12eSEd Maste ELF_T_RELA), nrels, EV_CURRENT); 778a85fe12eSEd Maste s->nocopy = 1; 779a85fe12eSEd Maste } 780a85fe12eSEd Maste 781a85fe12eSEd Maste static void 782a85fe12eSEd Maste update_reloc(struct elfcopy *ecp, struct section *s) 783a85fe12eSEd Maste { 784a85fe12eSEd Maste GElf_Shdr osh; 785a85fe12eSEd Maste GElf_Rel rel; 786a85fe12eSEd Maste GElf_Rela rela; 787a85fe12eSEd Maste Elf_Data *od; 788a85fe12eSEd Maste uint64_t n; 789a85fe12eSEd Maste int i; 790a85fe12eSEd Maste 791a85fe12eSEd Maste #define UPDATEREL(REL) do { \ 792a85fe12eSEd Maste if (gelf_get##REL(od, i, &REL) != &REL) \ 793a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 794a85fe12eSEd Maste elf_errmsg(-1)); \ 795a85fe12eSEd Maste REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 796a85fe12eSEd Maste GELF_R_TYPE(REL.r_info)); \ 797a85fe12eSEd Maste if (!gelf_update_##REL(od, i, &REL)) \ 798a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 799a85fe12eSEd Maste elf_errmsg(-1)); \ 800a85fe12eSEd Maste } while(0) 801a85fe12eSEd Maste 802a85fe12eSEd Maste if (s->sz == 0) 803a85fe12eSEd Maste return; 804a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 805a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 806a85fe12eSEd Maste elf_errmsg(-1)); 807a85fe12eSEd Maste /* Only process .symtab reloc info. */ 808a85fe12eSEd Maste if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 809a85fe12eSEd Maste return; 810a85fe12eSEd Maste if ((od = elf_getdata(s->os, NULL)) == NULL) 811a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 812a85fe12eSEd Maste elf_errmsg(-1)); 813a85fe12eSEd Maste n = osh.sh_size / osh.sh_entsize; 814a85fe12eSEd Maste for(i = 0; (uint64_t)i < n; i++) { 815a85fe12eSEd Maste if (s->type == SHT_REL) 816a85fe12eSEd Maste UPDATEREL(rel); 817a85fe12eSEd Maste else 818a85fe12eSEd Maste UPDATEREL(rela); 819a85fe12eSEd Maste } 820a85fe12eSEd Maste } 821a85fe12eSEd Maste 822a85fe12eSEd Maste static void 823a85fe12eSEd Maste pad_section(struct elfcopy *ecp, struct section *s) 824a85fe12eSEd Maste { 825a85fe12eSEd Maste GElf_Shdr osh; 826a85fe12eSEd Maste Elf_Data *od; 827a85fe12eSEd Maste 828a85fe12eSEd Maste if (s == NULL || s->pad_sz == 0) 829a85fe12eSEd Maste return; 830a85fe12eSEd Maste 831a85fe12eSEd Maste if ((s->pad = malloc(s->pad_sz)) == NULL) 832a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 833a85fe12eSEd Maste memset(s->pad, ecp->fill, s->pad_sz); 834a85fe12eSEd Maste 835a85fe12eSEd Maste /* Create a new Elf_Data to contain the padding bytes. */ 836a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 837a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 838a85fe12eSEd Maste elf_errmsg(-1)); 839a85fe12eSEd Maste od->d_align = 1; 840a85fe12eSEd Maste od->d_off = s->sz; 841a85fe12eSEd Maste od->d_buf = s->pad; 842a85fe12eSEd Maste od->d_type = ELF_T_BYTE; 843a85fe12eSEd Maste od->d_size = s->pad_sz; 844a85fe12eSEd Maste od->d_version = EV_CURRENT; 845a85fe12eSEd Maste 846a85fe12eSEd Maste /* Update section header. */ 847a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 848a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 849a85fe12eSEd Maste elf_errmsg(-1)); 850a85fe12eSEd Maste osh.sh_size = s->sz + s->pad_sz; 851a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 852a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 853a85fe12eSEd Maste elf_errmsg(-1)); 854a85fe12eSEd Maste } 855a85fe12eSEd Maste 856a85fe12eSEd Maste void 857a85fe12eSEd Maste resync_sections(struct elfcopy *ecp) 858a85fe12eSEd Maste { 859a85fe12eSEd Maste struct section *s, *ps; 860a85fe12eSEd Maste GElf_Shdr osh; 861a85fe12eSEd Maste uint64_t off; 862a85fe12eSEd Maste int first; 863a85fe12eSEd Maste 864a85fe12eSEd Maste ps = NULL; 865a85fe12eSEd Maste first = 1; 866a85fe12eSEd Maste off = 0; 867a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 868a85fe12eSEd Maste if (first) { 869a85fe12eSEd Maste off = s->off; 870a85fe12eSEd Maste first = 0; 871a85fe12eSEd Maste } 872a85fe12eSEd Maste 8734a85c691SEd Maste /* 8744a85c691SEd Maste * Ignore TLS sections with load address 0 and without 8754a85c691SEd Maste * content. We don't need to adjust their file offset or 8764a85c691SEd Maste * VMA, only the size matters. 8774a85c691SEd Maste */ 8784a85c691SEd Maste if (s->seg_tls != NULL && s->type == SHT_NOBITS && 8794a85c691SEd Maste s->off == 0) 8804a85c691SEd Maste continue; 8814a85c691SEd Maste 882a85fe12eSEd Maste /* Align section offset. */ 8832b39d4f6SEd Maste if (s->align == 0) 8842b39d4f6SEd Maste s->align = 1; 885a85fe12eSEd Maste if (off <= s->off) { 886*839529caSEd Maste if (!s->loadable || (ecp->flags & RELOCATABLE)) 887a85fe12eSEd Maste s->off = roundup(off, s->align); 888a85fe12eSEd Maste } else { 889*839529caSEd Maste if (s->loadable && (ecp->flags & RELOCATABLE) == 0) 89017eee522SEd Maste warnx("moving loadable section %s, " 89117eee522SEd Maste "is this intentional?", s->name); 892a85fe12eSEd Maste s->off = roundup(off, s->align); 893a85fe12eSEd Maste } 894a85fe12eSEd Maste 895a85fe12eSEd Maste /* Calculate next section offset. */ 896a85fe12eSEd Maste off = s->off; 897a85fe12eSEd Maste if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 898a85fe12eSEd Maste off += s->sz; 899a85fe12eSEd Maste 900a85fe12eSEd Maste if (s->pseudo) { 901a85fe12eSEd Maste ps = NULL; 902a85fe12eSEd Maste continue; 903a85fe12eSEd Maste } 904a85fe12eSEd Maste 905a85fe12eSEd Maste /* Count padding bytes added through --pad-to. */ 906a85fe12eSEd Maste if (s->pad_sz > 0) 907a85fe12eSEd Maste off += s->pad_sz; 908a85fe12eSEd Maste 909a85fe12eSEd Maste /* Update section header accordingly. */ 910a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 911a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 912a85fe12eSEd Maste elf_errmsg(-1)); 913a85fe12eSEd Maste osh.sh_addr = s->vma; 914a85fe12eSEd Maste osh.sh_offset = s->off; 915a85fe12eSEd Maste osh.sh_size = s->sz; 916a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 917a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 918a85fe12eSEd Maste elf_errmsg(-1)); 919a85fe12eSEd Maste 920a85fe12eSEd Maste /* Add padding for previous section, if need. */ 921a85fe12eSEd Maste if (ps != NULL) { 922a85fe12eSEd Maste if (ps->pad_sz > 0) { 923a85fe12eSEd Maste /* Apply padding added by --pad-to. */ 924a85fe12eSEd Maste pad_section(ecp, ps); 925a85fe12eSEd Maste } else if ((ecp->flags & GAP_FILL) && 926a85fe12eSEd Maste (ps->off + ps->sz < s->off)) { 927a85fe12eSEd Maste /* 928a85fe12eSEd Maste * Fill the gap between sections by padding 929a85fe12eSEd Maste * the section with lower address. 930a85fe12eSEd Maste */ 931a85fe12eSEd Maste ps->pad_sz = s->off - (ps->off + ps->sz); 932a85fe12eSEd Maste pad_section(ecp, ps); 933a85fe12eSEd Maste } 934a85fe12eSEd Maste } 935a85fe12eSEd Maste 936a85fe12eSEd Maste ps = s; 937a85fe12eSEd Maste } 938a85fe12eSEd Maste 939a85fe12eSEd Maste /* Pad the last section, if need. */ 940a85fe12eSEd Maste if (ps != NULL && ps->pad_sz > 0) 941a85fe12eSEd Maste pad_section(ecp, ps); 942a85fe12eSEd Maste } 943a85fe12eSEd Maste 944a85fe12eSEd Maste static void 945a85fe12eSEd Maste modify_section(struct elfcopy *ecp, struct section *s) 946a85fe12eSEd Maste { 947a85fe12eSEd Maste struct sec_action *sac; 948a85fe12eSEd Maste size_t srcsz, dstsz, p, len; 949a85fe12eSEd Maste char *b, *c, *d, *src, *end; 950a85fe12eSEd Maste int dupe; 951a85fe12eSEd Maste 952a85fe12eSEd Maste src = read_section(s, &srcsz); 953a85fe12eSEd Maste if (src == NULL || srcsz == 0) { 954a85fe12eSEd Maste /* For empty section, we proceed if we need to append. */ 955a85fe12eSEd Maste if (!is_append_section(ecp, s->name)) 956a85fe12eSEd Maste return; 957a85fe12eSEd Maste } 958a85fe12eSEd Maste 959a85fe12eSEd Maste /* Allocate buffer needed for new section data. */ 960a85fe12eSEd Maste dstsz = srcsz; 961a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 962a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 963a85fe12eSEd Maste dstsz += strlen(sac->string) + 1; 964a85fe12eSEd Maste } 965a85fe12eSEd Maste if ((b = malloc(dstsz)) == NULL) 966a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 967a85fe12eSEd Maste s->buf = b; 968a85fe12eSEd Maste 969a85fe12eSEd Maste /* Compress section. */ 970a85fe12eSEd Maste p = 0; 971a85fe12eSEd Maste if (is_compress_section(ecp, s->name)) { 972a85fe12eSEd Maste end = src + srcsz; 973a85fe12eSEd Maste for(c = src; c < end;) { 974a85fe12eSEd Maste len = 0; 975a85fe12eSEd Maste while(c + len < end && c[len] != '\0') 976a85fe12eSEd Maste len++; 977a85fe12eSEd Maste if (c + len == end) { 978a85fe12eSEd Maste /* XXX should we warn here? */ 979a85fe12eSEd Maste strncpy(&b[p], c, len); 980a85fe12eSEd Maste p += len; 981a85fe12eSEd Maste break; 982a85fe12eSEd Maste } 983a85fe12eSEd Maste dupe = 0; 984a85fe12eSEd Maste for (d = b; d < b + p; ) { 985a85fe12eSEd Maste if (strcmp(d, c) == 0) { 986a85fe12eSEd Maste dupe = 1; 987a85fe12eSEd Maste break; 988a85fe12eSEd Maste } 989a85fe12eSEd Maste d += strlen(d) + 1; 990a85fe12eSEd Maste } 991a85fe12eSEd Maste if (!dupe) { 992a85fe12eSEd Maste strncpy(&b[p], c, len); 993a85fe12eSEd Maste b[p + len] = '\0'; 994a85fe12eSEd Maste p += len + 1; 995a85fe12eSEd Maste } 996a85fe12eSEd Maste c += len + 1; 997a85fe12eSEd Maste } 998a85fe12eSEd Maste } else { 999a85fe12eSEd Maste memcpy(b, src, srcsz); 1000a85fe12eSEd Maste p += srcsz; 1001a85fe12eSEd Maste } 1002a85fe12eSEd Maste 1003a85fe12eSEd Maste /* Append section. */ 1004a85fe12eSEd Maste if (is_append_section(ecp, s->name)) { 1005a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 1006a85fe12eSEd Maste len = strlen(sac->string); 1007a85fe12eSEd Maste strncpy(&b[p], sac->string, len); 1008a85fe12eSEd Maste b[p + len] = '\0'; 1009a85fe12eSEd Maste p += len + 1; 1010a85fe12eSEd Maste } 1011a85fe12eSEd Maste 1012a85fe12eSEd Maste s->sz = p; 1013a85fe12eSEd Maste s->nocopy = 1; 1014a85fe12eSEd Maste } 1015a85fe12eSEd Maste 1016a85fe12eSEd Maste static void 1017a85fe12eSEd Maste print_data(const char *d, size_t sz) 1018a85fe12eSEd Maste { 1019a85fe12eSEd Maste const char *c; 1020a85fe12eSEd Maste 1021a85fe12eSEd Maste for (c = d; c < d + sz; c++) { 1022a85fe12eSEd Maste if (*c == '\0') 1023a85fe12eSEd Maste putchar('\n'); 1024a85fe12eSEd Maste else 1025a85fe12eSEd Maste putchar(*c); 1026a85fe12eSEd Maste } 1027a85fe12eSEd Maste } 1028a85fe12eSEd Maste 1029a85fe12eSEd Maste static void 1030a85fe12eSEd Maste print_section(struct section *s) 1031a85fe12eSEd Maste { 1032a85fe12eSEd Maste Elf_Data *id; 1033a85fe12eSEd Maste int elferr; 1034a85fe12eSEd Maste 1035a85fe12eSEd Maste if (s->buf != NULL && s->sz > 0) { 1036a85fe12eSEd Maste print_data(s->buf, s->sz); 1037a85fe12eSEd Maste } else { 1038a85fe12eSEd Maste id = NULL; 1039*839529caSEd Maste while ((id = elf_getdata(s->is, id)) != NULL || 1040*839529caSEd Maste (id = elf_rawdata(s->is, id)) != NULL) { 1041*839529caSEd Maste (void) elf_errno(); 1042a85fe12eSEd Maste print_data(id->d_buf, id->d_size); 1043*839529caSEd Maste } 1044a85fe12eSEd Maste elferr = elf_errno(); 1045a85fe12eSEd Maste if (elferr != 0) 1046a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1047a85fe12eSEd Maste elf_errmsg(elferr)); 1048a85fe12eSEd Maste } 1049a85fe12eSEd Maste putchar('\n'); 1050a85fe12eSEd Maste } 1051a85fe12eSEd Maste 1052a85fe12eSEd Maste static void * 1053a85fe12eSEd Maste read_section(struct section *s, size_t *size) 1054a85fe12eSEd Maste { 1055a85fe12eSEd Maste Elf_Data *id; 1056a85fe12eSEd Maste char *b; 1057a85fe12eSEd Maste size_t sz; 1058a85fe12eSEd Maste int elferr; 1059a85fe12eSEd Maste 1060a85fe12eSEd Maste sz = 0; 1061a85fe12eSEd Maste b = NULL; 1062a85fe12eSEd Maste id = NULL; 1063*839529caSEd Maste while ((id = elf_getdata(s->is, id)) != NULL || 1064*839529caSEd Maste (id = elf_rawdata(s->is, id)) != NULL) { 1065*839529caSEd Maste (void) elf_errno(); 1066a85fe12eSEd Maste if (b == NULL) 1067a85fe12eSEd Maste b = malloc(id->d_size); 1068a85fe12eSEd Maste else 1069a85fe12eSEd Maste b = malloc(sz + id->d_size); 1070a85fe12eSEd Maste if (b == NULL) 1071a85fe12eSEd Maste err(EXIT_FAILURE, "malloc or realloc failed"); 1072a85fe12eSEd Maste 1073a85fe12eSEd Maste memcpy(&b[sz], id->d_buf, id->d_size); 1074a85fe12eSEd Maste sz += id->d_size; 1075a85fe12eSEd Maste } 1076a85fe12eSEd Maste elferr = elf_errno(); 1077a85fe12eSEd Maste if (elferr != 0) 1078a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1079a85fe12eSEd Maste elf_errmsg(elferr)); 1080a85fe12eSEd Maste 1081a85fe12eSEd Maste *size = sz; 1082a85fe12eSEd Maste 1083a85fe12eSEd Maste return (b); 1084a85fe12eSEd Maste } 1085a85fe12eSEd Maste 1086a85fe12eSEd Maste void 1087a85fe12eSEd Maste copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 1088a85fe12eSEd Maste int sec_flags) 1089a85fe12eSEd Maste { 1090a85fe12eSEd Maste GElf_Shdr ish, osh; 1091a85fe12eSEd Maste 1092a85fe12eSEd Maste if (gelf_getshdr(s->is, &ish) == NULL) 1093*839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1094a85fe12eSEd Maste elf_errmsg(-1)); 1095a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 1096*839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1097a85fe12eSEd Maste elf_errmsg(-1)); 1098a85fe12eSEd Maste 1099a85fe12eSEd Maste if (copy) 1100a85fe12eSEd Maste (void) memcpy(&osh, &ish, sizeof(ish)); 1101a85fe12eSEd Maste else { 1102a85fe12eSEd Maste osh.sh_type = s->type; 1103a85fe12eSEd Maste osh.sh_addr = s->vma; 1104a85fe12eSEd Maste osh.sh_offset = s->off; 1105a85fe12eSEd Maste osh.sh_size = s->sz; 1106a85fe12eSEd Maste osh.sh_link = ish.sh_link; 1107a85fe12eSEd Maste osh.sh_info = ish.sh_info; 1108a85fe12eSEd Maste osh.sh_addralign = s->align; 1109a85fe12eSEd Maste osh.sh_entsize = ish.sh_entsize; 1110a85fe12eSEd Maste 1111a85fe12eSEd Maste if (sec_flags) { 1112a85fe12eSEd Maste osh.sh_flags = 0; 1113*839529caSEd Maste if (sec_flags & SF_ALLOC) 1114a85fe12eSEd Maste osh.sh_flags |= SHF_ALLOC; 1115a85fe12eSEd Maste if ((sec_flags & SF_READONLY) == 0) 1116a85fe12eSEd Maste osh.sh_flags |= SHF_WRITE; 1117a85fe12eSEd Maste if (sec_flags & SF_CODE) 1118a85fe12eSEd Maste osh.sh_flags |= SHF_EXECINSTR; 1119*839529caSEd Maste if ((sec_flags & SF_CONTENTS) && 1120*839529caSEd Maste s->type == SHT_NOBITS && s->sz > 0) { 1121*839529caSEd Maste /* 1122*839529caSEd Maste * Convert SHT_NOBITS section to section with 1123*839529caSEd Maste * (zero'ed) content on file. 1124*839529caSEd Maste */ 1125*839529caSEd Maste osh.sh_type = s->type = SHT_PROGBITS; 1126*839529caSEd Maste if ((s->buf = calloc(1, s->sz)) == NULL) 1127*839529caSEd Maste err(EXIT_FAILURE, "malloc failed"); 1128*839529caSEd Maste s->nocopy = 1; 1129*839529caSEd Maste } 11303ef90571SEd Maste } else { 1131a85fe12eSEd Maste osh.sh_flags = ish.sh_flags; 1132*839529caSEd Maste /* 1133*839529caSEd Maste * Newer binutils as(1) emits the section flag 1134*839529caSEd Maste * SHF_INFO_LINK for relocation sections. elfcopy 1135*839529caSEd Maste * emits this flag in the output section if it's 1136*839529caSEd Maste * missing in the input section, to remain compatible 1137*839529caSEd Maste * with binutils. 1138*839529caSEd Maste */ 11393ef90571SEd Maste if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 11403ef90571SEd Maste osh.sh_flags |= SHF_INFO_LINK; 11413ef90571SEd Maste } 1142a85fe12eSEd Maste } 1143a85fe12eSEd Maste 1144a85fe12eSEd Maste if (name == NULL) 1145a85fe12eSEd Maste add_to_shstrtab(ecp, s->name); 1146a85fe12eSEd Maste else 1147a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1148a85fe12eSEd Maste 1149a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1150a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1151a85fe12eSEd Maste elf_errmsg(-1)); 1152a85fe12eSEd Maste } 1153a85fe12eSEd Maste 1154a85fe12eSEd Maste void 1155a85fe12eSEd Maste copy_data(struct section *s) 1156a85fe12eSEd Maste { 1157a85fe12eSEd Maste Elf_Data *id, *od; 1158a85fe12eSEd Maste int elferr; 1159a85fe12eSEd Maste 1160a85fe12eSEd Maste if (s->nocopy && s->buf == NULL) 1161a85fe12eSEd Maste return; 1162a85fe12eSEd Maste 1163a85fe12eSEd Maste if ((id = elf_getdata(s->is, NULL)) == NULL) { 1164*839529caSEd Maste (void) elf_errno(); 1165*839529caSEd Maste if ((id = elf_rawdata(s->is, NULL)) == NULL) { 1166a85fe12eSEd Maste elferr = elf_errno(); 1167a85fe12eSEd Maste if (elferr != 0) 1168*839529caSEd Maste errx(EXIT_FAILURE, "failed to read section:" 1169*839529caSEd Maste " %s", s->name); 1170a85fe12eSEd Maste return; 1171a85fe12eSEd Maste } 1172*839529caSEd Maste } 1173a85fe12eSEd Maste 1174a85fe12eSEd Maste if ((od = elf_newdata(s->os)) == NULL) 1175a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1176a85fe12eSEd Maste elf_errmsg(-1)); 1177a85fe12eSEd Maste 1178a85fe12eSEd Maste if (s->nocopy) { 1179a85fe12eSEd Maste /* Use s->buf as content if s->nocopy is set. */ 1180a85fe12eSEd Maste od->d_align = id->d_align; 1181a85fe12eSEd Maste od->d_off = 0; 1182a85fe12eSEd Maste od->d_buf = s->buf; 1183a85fe12eSEd Maste od->d_type = id->d_type; 1184a85fe12eSEd Maste od->d_size = s->sz; 1185a85fe12eSEd Maste od->d_version = id->d_version; 1186a85fe12eSEd Maste } else { 1187a85fe12eSEd Maste od->d_align = id->d_align; 1188a85fe12eSEd Maste od->d_off = id->d_off; 1189a85fe12eSEd Maste od->d_buf = id->d_buf; 1190a85fe12eSEd Maste od->d_type = id->d_type; 1191a85fe12eSEd Maste od->d_size = id->d_size; 1192a85fe12eSEd Maste od->d_version = id->d_version; 1193a85fe12eSEd Maste } 11944a85c691SEd Maste 11954a85c691SEd Maste /* 11964a85c691SEd Maste * Alignment Fixup. libelf does not allow the alignment for 11974a85c691SEd Maste * Elf_Data descriptor to be set to 0. In this case we workaround 11984a85c691SEd Maste * it by setting the alignment to 1. 11994a85c691SEd Maste * 12004a85c691SEd Maste * According to the ELF ABI, alignment 0 and 1 has the same 12014a85c691SEd Maste * meaning: the section has no alignment constraints. 12024a85c691SEd Maste */ 12034a85c691SEd Maste if (od->d_align == 0) 12044a85c691SEd Maste od->d_align = 1; 1205a85fe12eSEd Maste } 1206a85fe12eSEd Maste 1207a85fe12eSEd Maste struct section * 1208a85fe12eSEd Maste create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1209a85fe12eSEd Maste void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1210a85fe12eSEd Maste uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1211a85fe12eSEd Maste { 1212a85fe12eSEd Maste struct section *s; 1213a85fe12eSEd Maste Elf_Scn *os; 1214a85fe12eSEd Maste Elf_Data *od; 1215a85fe12eSEd Maste GElf_Shdr osh; 1216a85fe12eSEd Maste 1217a85fe12eSEd Maste if ((os = elf_newscn(ecp->eout)) == NULL) 1218a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1219a85fe12eSEd Maste elf_errmsg(-1)); 1220a85fe12eSEd Maste if ((s = calloc(1, sizeof(*s))) == NULL) 1221a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1222a85fe12eSEd Maste s->name = name; 1223a85fe12eSEd Maste s->newname = newname; /* needs to be free()'ed */ 1224a85fe12eSEd Maste s->off = off; 1225a85fe12eSEd Maste s->sz = size; 1226a85fe12eSEd Maste s->vma = vma; 1227a85fe12eSEd Maste s->align = align; 1228a85fe12eSEd Maste s->loadable = loadable; 1229a85fe12eSEd Maste s->is = NULL; 1230a85fe12eSEd Maste s->os = os; 1231a85fe12eSEd Maste s->type = stype; 1232a85fe12eSEd Maste s->nocopy = 1; 1233a85fe12eSEd Maste insert_to_sec_list(ecp, s, 1); 1234a85fe12eSEd Maste 1235a85fe12eSEd Maste if (gelf_getshdr(os, &osh) == NULL) 1236a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1237a85fe12eSEd Maste elf_errmsg(-1)); 1238a85fe12eSEd Maste osh.sh_flags = flags; 1239a85fe12eSEd Maste osh.sh_type = s->type; 1240a85fe12eSEd Maste osh.sh_addr = s->vma; 1241a85fe12eSEd Maste osh.sh_addralign = s->align; 1242a85fe12eSEd Maste if (!gelf_update_shdr(os, &osh)) 1243a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1244a85fe12eSEd Maste elf_errmsg(-1)); 1245a85fe12eSEd Maste add_to_shstrtab(ecp, name); 1246a85fe12eSEd Maste 1247a85fe12eSEd Maste if (buf != NULL && size != 0) { 1248a85fe12eSEd Maste if ((od = elf_newdata(os)) == NULL) 1249a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1250a85fe12eSEd Maste elf_errmsg(-1)); 1251a85fe12eSEd Maste od->d_align = align; 1252a85fe12eSEd Maste od->d_off = 0; 1253a85fe12eSEd Maste od->d_buf = buf; 1254a85fe12eSEd Maste od->d_size = size; 1255a85fe12eSEd Maste od->d_type = dtype; 1256a85fe12eSEd Maste od->d_version = EV_CURRENT; 1257a85fe12eSEd Maste } 1258a85fe12eSEd Maste 1259a85fe12eSEd Maste /* 1260a85fe12eSEd Maste * Clear SYMTAB_INTACT, as we probably need to update/add new 1261a85fe12eSEd Maste * STT_SECTION symbols into the symbol table. 1262a85fe12eSEd Maste */ 1263a85fe12eSEd Maste ecp->flags &= ~SYMTAB_INTACT; 1264a85fe12eSEd Maste 1265a85fe12eSEd Maste return (s); 1266a85fe12eSEd Maste } 1267a85fe12eSEd Maste 1268a85fe12eSEd Maste /* 1269a85fe12eSEd Maste * Insert sections specified by --add-section to the end of section list. 1270a85fe12eSEd Maste */ 1271a85fe12eSEd Maste static void 1272a85fe12eSEd Maste insert_sections(struct elfcopy *ecp) 1273a85fe12eSEd Maste { 1274a85fe12eSEd Maste struct sec_add *sa; 1275a85fe12eSEd Maste struct section *s; 1276a85fe12eSEd Maste size_t off; 1277*839529caSEd Maste uint64_t stype; 1278a85fe12eSEd Maste 1279a85fe12eSEd Maste /* Put these sections in the end of current list. */ 1280a85fe12eSEd Maste off = 0; 1281a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1282a85fe12eSEd Maste if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1283a85fe12eSEd Maste off = s->off + s->sz; 1284a85fe12eSEd Maste else 1285a85fe12eSEd Maste off = s->off; 1286a85fe12eSEd Maste } 1287a85fe12eSEd Maste 1288a85fe12eSEd Maste STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1289a85fe12eSEd Maste 1290a85fe12eSEd Maste /* TODO: Add section header vma/lma, flag changes here */ 1291a85fe12eSEd Maste 1292*839529caSEd Maste /* 1293*839529caSEd Maste * The default section type for user added section is 1294*839529caSEd Maste * SHT_PROGBITS. If the section name match certain patterns, 1295*839529caSEd Maste * elfcopy will try to set a more appropriate section type. 1296*839529caSEd Maste * However, data type is always set to ELF_T_BYTE and no 1297*839529caSEd Maste * translation is performed by libelf. 1298*839529caSEd Maste */ 1299*839529caSEd Maste stype = SHT_PROGBITS; 1300*839529caSEd Maste if (strcmp(sa->name, ".note") == 0 || 1301*839529caSEd Maste strncmp(sa->name, ".note.", strlen(".note.")) == 0) 1302*839529caSEd Maste stype = SHT_NOTE; 1303*839529caSEd Maste 1304a85fe12eSEd Maste (void) create_external_section(ecp, sa->name, NULL, sa->content, 1305*839529caSEd Maste sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0); 1306a85fe12eSEd Maste } 1307a85fe12eSEd Maste } 1308a85fe12eSEd Maste 1309a85fe12eSEd Maste void 1310a85fe12eSEd Maste add_to_shstrtab(struct elfcopy *ecp, const char *name) 1311a85fe12eSEd Maste { 1312a85fe12eSEd Maste struct section *s; 1313a85fe12eSEd Maste 1314a85fe12eSEd Maste s = ecp->shstrtab; 1315a85fe12eSEd Maste insert_to_strtab(s, name); 1316a85fe12eSEd Maste } 1317a85fe12eSEd Maste 1318a85fe12eSEd Maste void 1319a85fe12eSEd Maste update_shdr(struct elfcopy *ecp, int update_link) 1320a85fe12eSEd Maste { 1321a85fe12eSEd Maste struct section *s; 1322a85fe12eSEd Maste GElf_Shdr osh; 1323a85fe12eSEd Maste int elferr; 1324a85fe12eSEd Maste 1325a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1326a85fe12eSEd Maste if (s->pseudo) 1327a85fe12eSEd Maste continue; 1328a85fe12eSEd Maste 1329a85fe12eSEd Maste if (gelf_getshdr(s->os, &osh) == NULL) 1330*839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 1331a85fe12eSEd Maste elf_errmsg(-1)); 1332a85fe12eSEd Maste 1333a85fe12eSEd Maste /* Find section name in string table and set sh_name. */ 1334a85fe12eSEd Maste osh.sh_name = lookup_string(ecp->shstrtab, s->name); 1335a85fe12eSEd Maste 1336a85fe12eSEd Maste /* 1337a85fe12eSEd Maste * sh_link needs to be updated, since the index of the 1338a85fe12eSEd Maste * linked section might have changed. 1339a85fe12eSEd Maste */ 1340a85fe12eSEd Maste if (update_link && osh.sh_link != 0) 1341a85fe12eSEd Maste osh.sh_link = ecp->secndx[osh.sh_link]; 1342a85fe12eSEd Maste 1343a85fe12eSEd Maste /* 1344a85fe12eSEd Maste * sh_info of relocation section links to the section to which 1345a85fe12eSEd Maste * its relocation info applies. So it may need update as well. 1346a85fe12eSEd Maste */ 1347a85fe12eSEd Maste if ((s->type == SHT_REL || s->type == SHT_RELA) && 1348a85fe12eSEd Maste osh.sh_info != 0) 1349a85fe12eSEd Maste osh.sh_info = ecp->secndx[osh.sh_info]; 1350a85fe12eSEd Maste 1351b00fe64fSEd Maste /* 1352b00fe64fSEd Maste * sh_info of SHT_GROUP section needs to point to the correct 1353b00fe64fSEd Maste * string in the symbol table. 1354b00fe64fSEd Maste */ 1355b00fe64fSEd Maste if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) && 1356b00fe64fSEd Maste (ecp->flags & SYMTAB_INTACT) == 0) 1357b00fe64fSEd Maste osh.sh_info = ecp->symndx[osh.sh_info]; 1358b00fe64fSEd Maste 1359a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &osh)) 1360a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1361a85fe12eSEd Maste elf_errmsg(-1)); 1362a85fe12eSEd Maste } 1363a85fe12eSEd Maste elferr = elf_errno(); 1364a85fe12eSEd Maste if (elferr != 0) 1365a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1366a85fe12eSEd Maste elf_errmsg(elferr)); 1367a85fe12eSEd Maste } 1368a85fe12eSEd Maste 1369a85fe12eSEd Maste void 1370a85fe12eSEd Maste init_shstrtab(struct elfcopy *ecp) 1371a85fe12eSEd Maste { 1372a85fe12eSEd Maste struct section *s; 1373a85fe12eSEd Maste 1374a85fe12eSEd Maste if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1375a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 1376a85fe12eSEd Maste s = ecp->shstrtab; 1377a85fe12eSEd Maste s->name = ".shstrtab"; 1378a85fe12eSEd Maste s->is = NULL; 1379a85fe12eSEd Maste s->sz = 0; 1380a85fe12eSEd Maste s->align = 1; 1381a85fe12eSEd Maste s->loadable = 0; 1382a85fe12eSEd Maste s->type = SHT_STRTAB; 1383a85fe12eSEd Maste s->vma = 0; 13849ef62fdbSEd Maste 13859ef62fdbSEd Maste insert_to_strtab(s, ""); 13869ef62fdbSEd Maste insert_to_strtab(s, ".symtab"); 13879ef62fdbSEd Maste insert_to_strtab(s, ".strtab"); 13889ef62fdbSEd Maste insert_to_strtab(s, ".shstrtab"); 1389a85fe12eSEd Maste } 1390a85fe12eSEd Maste 1391a85fe12eSEd Maste void 1392a85fe12eSEd Maste set_shstrtab(struct elfcopy *ecp) 1393a85fe12eSEd Maste { 1394a85fe12eSEd Maste struct section *s; 1395a85fe12eSEd Maste Elf_Data *data; 1396a85fe12eSEd Maste GElf_Shdr sh; 1397a85fe12eSEd Maste 1398a85fe12eSEd Maste s = ecp->shstrtab; 1399a85fe12eSEd Maste 1400619ba3b4SEd Maste if (s->os == NULL) { 1401619ba3b4SEd Maste /* Input object does not contain .shstrtab section */ 1402619ba3b4SEd Maste if ((s->os = elf_newscn(ecp->eout)) == NULL) 1403619ba3b4SEd Maste errx(EXIT_FAILURE, "elf_newscn failed: %s", 1404619ba3b4SEd Maste elf_errmsg(-1)); 1405619ba3b4SEd Maste insert_to_sec_list(ecp, s, 1); 1406619ba3b4SEd Maste } 1407619ba3b4SEd Maste 1408a85fe12eSEd Maste if (gelf_getshdr(s->os, &sh) == NULL) 1409*839529caSEd Maste errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1410a85fe12eSEd Maste elf_errmsg(-1)); 1411a85fe12eSEd Maste sh.sh_addr = 0; 1412a85fe12eSEd Maste sh.sh_addralign = 1; 1413a85fe12eSEd Maste sh.sh_offset = s->off; 1414a85fe12eSEd Maste sh.sh_type = SHT_STRTAB; 1415a85fe12eSEd Maste sh.sh_flags = 0; 1416a85fe12eSEd Maste sh.sh_entsize = 0; 1417a85fe12eSEd Maste sh.sh_info = 0; 1418a85fe12eSEd Maste sh.sh_link = 0; 1419a85fe12eSEd Maste 1420a85fe12eSEd Maste if ((data = elf_newdata(s->os)) == NULL) 1421a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1422a85fe12eSEd Maste elf_errmsg(-1)); 1423a85fe12eSEd Maste 1424a85fe12eSEd Maste /* 1425a85fe12eSEd Maste * If we don't have a symbol table, skip those a few bytes 1426a85fe12eSEd Maste * which are reserved for this in the beginning of shstrtab. 1427a85fe12eSEd Maste */ 1428a85fe12eSEd Maste if (!(ecp->flags & SYMTAB_EXIST)) { 1429a85fe12eSEd Maste s->sz -= sizeof(".symtab\0.strtab"); 1430a85fe12eSEd Maste memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), 1431a85fe12eSEd Maste s->sz); 1432a85fe12eSEd Maste } 1433a85fe12eSEd Maste 1434a85fe12eSEd Maste sh.sh_size = s->sz; 1435a85fe12eSEd Maste if (!gelf_update_shdr(s->os, &sh)) 1436a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1437a85fe12eSEd Maste elf_errmsg(-1)); 1438a85fe12eSEd Maste 1439a85fe12eSEd Maste data->d_align = 1; 1440a85fe12eSEd Maste data->d_buf = s->buf; 1441a85fe12eSEd Maste data->d_size = s->sz; 1442a85fe12eSEd Maste data->d_off = 0; 1443a85fe12eSEd Maste data->d_type = ELF_T_BYTE; 1444a85fe12eSEd Maste data->d_version = EV_CURRENT; 1445a85fe12eSEd Maste 1446a85fe12eSEd Maste if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1447a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1448a85fe12eSEd Maste elf_errmsg(-1)); 1449a85fe12eSEd Maste } 1450a85fe12eSEd Maste 1451a85fe12eSEd Maste void 1452a85fe12eSEd Maste add_section(struct elfcopy *ecp, const char *arg) 1453a85fe12eSEd Maste { 1454a85fe12eSEd Maste struct sec_add *sa; 1455a85fe12eSEd Maste struct stat sb; 1456a85fe12eSEd Maste const char *s, *fn; 1457a85fe12eSEd Maste FILE *fp; 1458a85fe12eSEd Maste int len; 1459a85fe12eSEd Maste 1460a85fe12eSEd Maste if ((s = strchr(arg, '=')) == NULL) 1461a85fe12eSEd Maste errx(EXIT_FAILURE, 1462a85fe12eSEd Maste "illegal format for --add-section option"); 1463a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1464a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1465a85fe12eSEd Maste 1466a85fe12eSEd Maste len = s - arg; 1467a85fe12eSEd Maste if ((sa->name = malloc(len + 1)) == NULL) 1468a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1469a85fe12eSEd Maste strncpy(sa->name, arg, len); 1470a85fe12eSEd Maste sa->name[len] = '\0'; 1471a85fe12eSEd Maste 1472a85fe12eSEd Maste fn = s + 1; 1473a85fe12eSEd Maste if (stat(fn, &sb) == -1) 1474a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1475a85fe12eSEd Maste sa->size = sb.st_size; 1476*839529caSEd Maste if (sa->size > 0) { 1477a85fe12eSEd Maste if ((sa->content = malloc(sa->size)) == NULL) 1478a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1479a85fe12eSEd Maste if ((fp = fopen(fn, "r")) == NULL) 1480a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", fn); 1481a85fe12eSEd Maste if (fread(sa->content, 1, sa->size, fp) == 0 || 1482a85fe12eSEd Maste ferror(fp)) 1483a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1484a85fe12eSEd Maste fclose(fp); 1485*839529caSEd Maste } else 1486*839529caSEd Maste sa->content = NULL; 1487a85fe12eSEd Maste 1488a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1489a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1490a85fe12eSEd Maste } 1491a85fe12eSEd Maste 1492a85fe12eSEd Maste void 1493a85fe12eSEd Maste free_sec_add(struct elfcopy *ecp) 1494a85fe12eSEd Maste { 1495a85fe12eSEd Maste struct sec_add *sa, *sa_temp; 1496a85fe12eSEd Maste 1497a85fe12eSEd Maste STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1498a85fe12eSEd Maste STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1499a85fe12eSEd Maste free(sa->name); 1500a85fe12eSEd Maste free(sa->content); 1501a85fe12eSEd Maste free(sa); 1502a85fe12eSEd Maste } 1503a85fe12eSEd Maste } 1504a85fe12eSEd Maste 1505a85fe12eSEd Maste static void 1506a85fe12eSEd Maste add_gnu_debuglink(struct elfcopy *ecp) 1507a85fe12eSEd Maste { 1508a85fe12eSEd Maste struct sec_add *sa; 1509a85fe12eSEd Maste struct stat sb; 1510a85fe12eSEd Maste FILE *fp; 1511a85fe12eSEd Maste char *fnbase, *buf; 1512a85fe12eSEd Maste int crc_off; 1513a85fe12eSEd Maste int crc; 1514a85fe12eSEd Maste 1515a85fe12eSEd Maste if (ecp->debuglink == NULL) 1516a85fe12eSEd Maste return; 1517a85fe12eSEd Maste 1518a85fe12eSEd Maste /* Read debug file content. */ 1519a85fe12eSEd Maste if ((sa = malloc(sizeof(*sa))) == NULL) 1520a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1521a85fe12eSEd Maste if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1522a85fe12eSEd Maste err(EXIT_FAILURE, "strdup failed"); 1523a85fe12eSEd Maste if (stat(ecp->debuglink, &sb) == -1) 1524a85fe12eSEd Maste err(EXIT_FAILURE, "stat failed"); 1525a85fe12eSEd Maste if ((buf = malloc(sb.st_size)) == NULL) 1526a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1527a85fe12eSEd Maste if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1528a85fe12eSEd Maste err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1529a85fe12eSEd Maste if (fread(buf, 1, sb.st_size, fp) == 0 || 1530a85fe12eSEd Maste ferror(fp)) 1531a85fe12eSEd Maste err(EXIT_FAILURE, "fread failed"); 1532a85fe12eSEd Maste fclose(fp); 1533a85fe12eSEd Maste 1534a85fe12eSEd Maste /* Calculate crc checksum. */ 1535a85fe12eSEd Maste crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1536a85fe12eSEd Maste free(buf); 1537a85fe12eSEd Maste 1538a85fe12eSEd Maste /* Calculate section size and the offset to store crc checksum. */ 1539a85fe12eSEd Maste if ((fnbase = basename(ecp->debuglink)) == NULL) 1540a85fe12eSEd Maste err(EXIT_FAILURE, "basename failed"); 1541a85fe12eSEd Maste crc_off = roundup(strlen(fnbase) + 1, 4); 1542a85fe12eSEd Maste sa->size = crc_off + 4; 1543a85fe12eSEd Maste 1544a85fe12eSEd Maste /* Section content. */ 1545a85fe12eSEd Maste if ((sa->content = calloc(1, sa->size)) == NULL) 1546a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1547a85fe12eSEd Maste strncpy(sa->content, fnbase, strlen(fnbase)); 1548a85fe12eSEd Maste if (ecp->oed == ELFDATA2LSB) { 1549a85fe12eSEd Maste sa->content[crc_off] = crc & 0xFF; 1550a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1551a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1552a85fe12eSEd Maste sa->content[crc_off + 3] = crc >> 24; 1553a85fe12eSEd Maste } else { 1554a85fe12eSEd Maste sa->content[crc_off] = crc >> 24; 1555a85fe12eSEd Maste sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1556a85fe12eSEd Maste sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1557a85fe12eSEd Maste sa->content[crc_off + 3] = crc & 0xFF; 1558a85fe12eSEd Maste } 1559a85fe12eSEd Maste 1560a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1561a85fe12eSEd Maste ecp->flags |= SEC_ADD; 1562a85fe12eSEd Maste } 1563a85fe12eSEd Maste 1564a85fe12eSEd Maste static void 1565a85fe12eSEd Maste insert_to_strtab(struct section *t, const char *s) 1566a85fe12eSEd Maste { 1567a85fe12eSEd Maste const char *r; 1568a85fe12eSEd Maste char *b, *c; 1569a85fe12eSEd Maste size_t len, slen; 1570a85fe12eSEd Maste int append; 1571a85fe12eSEd Maste 1572a85fe12eSEd Maste if (t->sz == 0) { 1573a85fe12eSEd Maste t->cap = 512; 1574a85fe12eSEd Maste if ((t->buf = malloc(t->cap)) == NULL) 1575a85fe12eSEd Maste err(EXIT_FAILURE, "malloc failed"); 1576a85fe12eSEd Maste } 1577a85fe12eSEd Maste 1578a85fe12eSEd Maste slen = strlen(s); 1579a85fe12eSEd Maste append = 0; 1580a85fe12eSEd Maste b = t->buf; 1581a85fe12eSEd Maste for (c = b; c < b + t->sz;) { 1582a85fe12eSEd Maste len = strlen(c); 1583a85fe12eSEd Maste if (!append && len >= slen) { 1584a85fe12eSEd Maste r = c + (len - slen); 1585a85fe12eSEd Maste if (strcmp(r, s) == 0) 1586a85fe12eSEd Maste return; 1587a85fe12eSEd Maste } else if (len < slen && len != 0) { 1588a85fe12eSEd Maste r = s + (slen - len); 1589a85fe12eSEd Maste if (strcmp(c, r) == 0) { 1590a85fe12eSEd Maste t->sz -= len + 1; 1591a85fe12eSEd Maste memmove(c, c + len + 1, t->sz - (c - b)); 1592a85fe12eSEd Maste append = 1; 1593a85fe12eSEd Maste continue; 1594a85fe12eSEd Maste } 1595a85fe12eSEd Maste } 1596a85fe12eSEd Maste c += len + 1; 1597a85fe12eSEd Maste } 1598a85fe12eSEd Maste 1599a85fe12eSEd Maste while (t->sz + slen + 1 >= t->cap) { 1600a85fe12eSEd Maste t->cap *= 2; 1601a85fe12eSEd Maste if ((t->buf = realloc(t->buf, t->cap)) == NULL) 1602a85fe12eSEd Maste err(EXIT_FAILURE, "realloc failed"); 1603a85fe12eSEd Maste } 1604a85fe12eSEd Maste b = t->buf; 1605a85fe12eSEd Maste strncpy(&b[t->sz], s, slen); 1606a85fe12eSEd Maste b[t->sz + slen] = '\0'; 1607a85fe12eSEd Maste t->sz += slen + 1; 1608a85fe12eSEd Maste } 1609a85fe12eSEd Maste 1610a85fe12eSEd Maste static int 1611a85fe12eSEd Maste lookup_string(struct section *t, const char *s) 1612a85fe12eSEd Maste { 1613a85fe12eSEd Maste const char *b, *c, *r; 1614a85fe12eSEd Maste size_t len, slen; 1615a85fe12eSEd Maste 1616a85fe12eSEd Maste slen = strlen(s); 1617a85fe12eSEd Maste b = t->buf; 1618a85fe12eSEd Maste for (c = b; c < b + t->sz;) { 1619a85fe12eSEd Maste len = strlen(c); 1620a85fe12eSEd Maste if (len >= slen) { 1621a85fe12eSEd Maste r = c + (len - slen); 1622a85fe12eSEd Maste if (strcmp(r, s) == 0) 1623a85fe12eSEd Maste return (r - b); 1624a85fe12eSEd Maste } 1625a85fe12eSEd Maste c += len + 1; 1626a85fe12eSEd Maste } 1627a85fe12eSEd Maste 1628a85fe12eSEd Maste return (-1); 1629a85fe12eSEd Maste } 1630a85fe12eSEd Maste 1631a85fe12eSEd Maste static uint32_t crctable[256] = 1632a85fe12eSEd Maste { 1633a85fe12eSEd Maste 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1634a85fe12eSEd Maste 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1635a85fe12eSEd Maste 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1636a85fe12eSEd Maste 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1637a85fe12eSEd Maste 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1638a85fe12eSEd Maste 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1639a85fe12eSEd Maste 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1640a85fe12eSEd Maste 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1641a85fe12eSEd Maste 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1642a85fe12eSEd Maste 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1643a85fe12eSEd Maste 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1644a85fe12eSEd Maste 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1645a85fe12eSEd Maste 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1646a85fe12eSEd Maste 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1647a85fe12eSEd Maste 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1648a85fe12eSEd Maste 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1649a85fe12eSEd Maste 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1650a85fe12eSEd Maste 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1651a85fe12eSEd Maste 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1652a85fe12eSEd Maste 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1653a85fe12eSEd Maste 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1654a85fe12eSEd Maste 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1655a85fe12eSEd Maste 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1656a85fe12eSEd Maste 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1657a85fe12eSEd Maste 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1658a85fe12eSEd Maste 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1659a85fe12eSEd Maste 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1660a85fe12eSEd Maste 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1661a85fe12eSEd Maste 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1662a85fe12eSEd Maste 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1663a85fe12eSEd Maste 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1664a85fe12eSEd Maste 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1665a85fe12eSEd Maste 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1666a85fe12eSEd Maste 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1667a85fe12eSEd Maste 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1668a85fe12eSEd Maste 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1669a85fe12eSEd Maste 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1670a85fe12eSEd Maste 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1671a85fe12eSEd Maste 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1672a85fe12eSEd Maste 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1673a85fe12eSEd Maste 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1674a85fe12eSEd Maste 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1675a85fe12eSEd Maste 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1676a85fe12eSEd Maste 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1677a85fe12eSEd Maste 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1678a85fe12eSEd Maste 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1679a85fe12eSEd Maste 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1680a85fe12eSEd Maste 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1681a85fe12eSEd Maste 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1682a85fe12eSEd Maste 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1683a85fe12eSEd Maste 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1684a85fe12eSEd Maste 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1685a85fe12eSEd Maste 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1686a85fe12eSEd Maste 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1687a85fe12eSEd Maste 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1688a85fe12eSEd Maste 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1689a85fe12eSEd Maste 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1690a85fe12eSEd Maste 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1691a85fe12eSEd Maste 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1692a85fe12eSEd Maste 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1693a85fe12eSEd Maste 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1694a85fe12eSEd Maste 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1695a85fe12eSEd Maste 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1696a85fe12eSEd Maste 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1697a85fe12eSEd Maste }; 1698a85fe12eSEd Maste 1699a85fe12eSEd Maste static uint32_t 1700a85fe12eSEd Maste calc_crc32(const char *p, size_t len, uint32_t crc) 1701a85fe12eSEd Maste { 1702a85fe12eSEd Maste uint32_t i; 1703a85fe12eSEd Maste 1704a85fe12eSEd Maste for (i = 0; i < len; i++) { 1705a85fe12eSEd Maste crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1706a85fe12eSEd Maste } 1707a85fe12eSEd Maste 1708a85fe12eSEd Maste return (crc ^ 0xFFFFFFFF); 1709a85fe12eSEd Maste } 1710