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