1*7fd79137SRobert Mustacchi /* 2*7fd79137SRobert Mustacchi * CDDL HEADER START 3*7fd79137SRobert Mustacchi * 4*7fd79137SRobert Mustacchi * The contents of this file are subject to the terms of the 5*7fd79137SRobert Mustacchi * Common Development and Distribution License (the "License"). 6*7fd79137SRobert Mustacchi * You may not use this file except in compliance with the License. 7*7fd79137SRobert Mustacchi * 8*7fd79137SRobert Mustacchi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7fd79137SRobert Mustacchi * or http://www.opensolaris.org/os/licensing. 10*7fd79137SRobert Mustacchi * See the License for the specific language governing permissions 11*7fd79137SRobert Mustacchi * and limitations under the License. 12*7fd79137SRobert Mustacchi * 13*7fd79137SRobert Mustacchi * When distributing Covered Code, include this CDDL HEADER in each 14*7fd79137SRobert Mustacchi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7fd79137SRobert Mustacchi * If applicable, add the following below this CDDL HEADER, with the 16*7fd79137SRobert Mustacchi * fields enclosed by brackets "[]" replaced with your own identifying 17*7fd79137SRobert Mustacchi * information: Portions Copyright [yyyy] [name of copyright owner] 18*7fd79137SRobert Mustacchi * 19*7fd79137SRobert Mustacchi * CDDL HEADER END 20*7fd79137SRobert Mustacchi */ 21*7fd79137SRobert Mustacchi /* 22*7fd79137SRobert Mustacchi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*7fd79137SRobert Mustacchi * Use is subject to license terms. 24*7fd79137SRobert Mustacchi */ 25*7fd79137SRobert Mustacchi /* 26*7fd79137SRobert Mustacchi * Copyright (c) 2015, Joyent, Inc. 27*7fd79137SRobert Mustacchi */ 28*7fd79137SRobert Mustacchi 29*7fd79137SRobert Mustacchi /* 30*7fd79137SRobert Mustacchi * Routines for writing ctf data to elf files. 31*7fd79137SRobert Mustacchi */ 32*7fd79137SRobert Mustacchi 33*7fd79137SRobert Mustacchi #include <libctf_impl.h> 34*7fd79137SRobert Mustacchi #include <libctf.h> 35*7fd79137SRobert Mustacchi #include <gelf.h> 36*7fd79137SRobert Mustacchi #include <sys/stat.h> 37*7fd79137SRobert Mustacchi #include <sys/types.h> 38*7fd79137SRobert Mustacchi #include <fcntl.h> 39*7fd79137SRobert Mustacchi #include <errno.h> 40*7fd79137SRobert Mustacchi #include <unistd.h> 41*7fd79137SRobert Mustacchi #include <libelf.h> 42*7fd79137SRobert Mustacchi 43*7fd79137SRobert Mustacchi static int 44*7fd79137SRobert Mustacchi ctf_write_elf(ctf_file_t *fp, Elf *src, Elf *dst, int flags) 45*7fd79137SRobert Mustacchi { 46*7fd79137SRobert Mustacchi GElf_Ehdr sehdr, dehdr; 47*7fd79137SRobert Mustacchi Elf_Scn *sscn, *dscn; 48*7fd79137SRobert Mustacchi Elf_Data *sdata, *ddata; 49*7fd79137SRobert Mustacchi GElf_Shdr shdr; 50*7fd79137SRobert Mustacchi int symtab_idx = -1; 51*7fd79137SRobert Mustacchi off_t new_offset = 0; 52*7fd79137SRobert Mustacchi off_t ctfnameoff = 0; 53*7fd79137SRobert Mustacchi int compress = (flags & CTF_ELFWRITE_F_COMPRESS); 54*7fd79137SRobert Mustacchi int *secxlate = NULL; 55*7fd79137SRobert Mustacchi int srcidx, dstidx, pad, i; 56*7fd79137SRobert Mustacchi int curnmoff = 0; 57*7fd79137SRobert Mustacchi int changing = 0; 58*7fd79137SRobert Mustacchi int ret; 59*7fd79137SRobert Mustacchi size_t nshdr, nphdr, strndx; 60*7fd79137SRobert Mustacchi void *strdatabuf = NULL, *symdatabuf = NULL; 61*7fd79137SRobert Mustacchi size_t strdatasz = 0, symdatasz = 0; 62*7fd79137SRobert Mustacchi 63*7fd79137SRobert Mustacchi void *cdata = NULL; 64*7fd79137SRobert Mustacchi size_t elfsize, asize; 65*7fd79137SRobert Mustacchi 66*7fd79137SRobert Mustacchi if ((flags & ~(CTF_ELFWRITE_F_COMPRESS)) != 0) { 67*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, EINVAL); 68*7fd79137SRobert Mustacchi goto out; 69*7fd79137SRobert Mustacchi } 70*7fd79137SRobert Mustacchi 71*7fd79137SRobert Mustacchi if (gelf_newehdr(dst, gelf_getclass(src)) == NULL) { 72*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 73*7fd79137SRobert Mustacchi goto out; 74*7fd79137SRobert Mustacchi } 75*7fd79137SRobert Mustacchi if (gelf_getehdr(src, &sehdr) == NULL) { 76*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 77*7fd79137SRobert Mustacchi goto out; 78*7fd79137SRobert Mustacchi } 79*7fd79137SRobert Mustacchi (void) memcpy(&dehdr, &sehdr, sizeof (GElf_Ehdr)); 80*7fd79137SRobert Mustacchi if (gelf_update_ehdr(dst, &dehdr) == 0) { 81*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 82*7fd79137SRobert Mustacchi goto out; 83*7fd79137SRobert Mustacchi } 84*7fd79137SRobert Mustacchi 85*7fd79137SRobert Mustacchi /* 86*7fd79137SRobert Mustacchi * Use libelf to get the number of sections and the string section to 87*7fd79137SRobert Mustacchi * deal with ELF files that may have a large number of sections. We just 88*7fd79137SRobert Mustacchi * always use this to make our live easier. 89*7fd79137SRobert Mustacchi */ 90*7fd79137SRobert Mustacchi if (elf_getphdrnum(src, &nphdr) != 0) { 91*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 92*7fd79137SRobert Mustacchi goto out; 93*7fd79137SRobert Mustacchi } 94*7fd79137SRobert Mustacchi if (elf_getshdrnum(src, &nshdr) != 0) { 95*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 96*7fd79137SRobert Mustacchi goto out; 97*7fd79137SRobert Mustacchi } 98*7fd79137SRobert Mustacchi if (elf_getshdrstrndx(src, &strndx) != 0) { 99*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 100*7fd79137SRobert Mustacchi goto out; 101*7fd79137SRobert Mustacchi } 102*7fd79137SRobert Mustacchi 103*7fd79137SRobert Mustacchi /* 104*7fd79137SRobert Mustacchi * Neither the existing debug sections nor the SUNW_ctf sections (new or 105*7fd79137SRobert Mustacchi * existing) are SHF_ALLOC'd, so they won't be in areas referenced by 106*7fd79137SRobert Mustacchi * program headers. As such, we can just blindly copy the program 107*7fd79137SRobert Mustacchi * headers from the existing file to the new file. 108*7fd79137SRobert Mustacchi */ 109*7fd79137SRobert Mustacchi if (nphdr != 0) { 110*7fd79137SRobert Mustacchi (void) elf_flagelf(dst, ELF_C_SET, ELF_F_LAYOUT); 111*7fd79137SRobert Mustacchi if (gelf_newphdr(dst, nphdr) == NULL) { 112*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 113*7fd79137SRobert Mustacchi goto out; 114*7fd79137SRobert Mustacchi } 115*7fd79137SRobert Mustacchi 116*7fd79137SRobert Mustacchi for (i = 0; i < nphdr; i++) { 117*7fd79137SRobert Mustacchi GElf_Phdr phdr; 118*7fd79137SRobert Mustacchi 119*7fd79137SRobert Mustacchi if (gelf_getphdr(src, i, &phdr) == NULL) { 120*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 121*7fd79137SRobert Mustacchi goto out; 122*7fd79137SRobert Mustacchi } 123*7fd79137SRobert Mustacchi if (gelf_update_phdr(dst, i, &phdr) == 0) { 124*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 125*7fd79137SRobert Mustacchi goto out; 126*7fd79137SRobert Mustacchi } 127*7fd79137SRobert Mustacchi } 128*7fd79137SRobert Mustacchi } 129*7fd79137SRobert Mustacchi 130*7fd79137SRobert Mustacchi secxlate = ctf_alloc(sizeof (int) * nshdr); 131*7fd79137SRobert Mustacchi for (srcidx = dstidx = 0; srcidx < nshdr; srcidx++) { 132*7fd79137SRobert Mustacchi Elf_Scn *scn = elf_getscn(src, srcidx); 133*7fd79137SRobert Mustacchi GElf_Shdr shdr; 134*7fd79137SRobert Mustacchi char *sname; 135*7fd79137SRobert Mustacchi 136*7fd79137SRobert Mustacchi if (gelf_getshdr(scn, &shdr) == NULL) { 137*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 138*7fd79137SRobert Mustacchi goto out; 139*7fd79137SRobert Mustacchi } 140*7fd79137SRobert Mustacchi sname = elf_strptr(src, strndx, shdr.sh_name); 141*7fd79137SRobert Mustacchi if (sname == NULL) { 142*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 143*7fd79137SRobert Mustacchi goto out; 144*7fd79137SRobert Mustacchi } 145*7fd79137SRobert Mustacchi 146*7fd79137SRobert Mustacchi if (strcmp(sname, CTF_ELF_SCN_NAME) == 0) { 147*7fd79137SRobert Mustacchi secxlate[srcidx] = -1; 148*7fd79137SRobert Mustacchi } else { 149*7fd79137SRobert Mustacchi secxlate[srcidx] = dstidx++; 150*7fd79137SRobert Mustacchi curnmoff += strlen(sname) + 1; 151*7fd79137SRobert Mustacchi } 152*7fd79137SRobert Mustacchi 153*7fd79137SRobert Mustacchi new_offset = (off_t)dehdr.e_phoff; 154*7fd79137SRobert Mustacchi } 155*7fd79137SRobert Mustacchi 156*7fd79137SRobert Mustacchi for (srcidx = 1; srcidx < nshdr; srcidx++) { 157*7fd79137SRobert Mustacchi char *sname; 158*7fd79137SRobert Mustacchi 159*7fd79137SRobert Mustacchi sscn = elf_getscn(src, srcidx); 160*7fd79137SRobert Mustacchi if (gelf_getshdr(sscn, &shdr) == NULL) { 161*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 162*7fd79137SRobert Mustacchi goto out; 163*7fd79137SRobert Mustacchi } 164*7fd79137SRobert Mustacchi 165*7fd79137SRobert Mustacchi if (secxlate[srcidx] == -1) { 166*7fd79137SRobert Mustacchi changing = 1; 167*7fd79137SRobert Mustacchi continue; 168*7fd79137SRobert Mustacchi } 169*7fd79137SRobert Mustacchi 170*7fd79137SRobert Mustacchi dscn = elf_newscn(dst); 171*7fd79137SRobert Mustacchi if (dscn == NULL) { 172*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 173*7fd79137SRobert Mustacchi goto out; 174*7fd79137SRobert Mustacchi } 175*7fd79137SRobert Mustacchi 176*7fd79137SRobert Mustacchi /* 177*7fd79137SRobert Mustacchi * If this file has program headers, we need to explicitly lay 178*7fd79137SRobert Mustacchi * out sections. If none of the sections prior to this one have 179*7fd79137SRobert Mustacchi * been removed, then we can just use the existing location. If 180*7fd79137SRobert Mustacchi * one or more sections have been changed, then we need to 181*7fd79137SRobert Mustacchi * adjust this one to avoid holes. 182*7fd79137SRobert Mustacchi */ 183*7fd79137SRobert Mustacchi if (changing && nphdr != 0) { 184*7fd79137SRobert Mustacchi pad = new_offset % shdr.sh_addralign; 185*7fd79137SRobert Mustacchi 186*7fd79137SRobert Mustacchi if (pad != 0) 187*7fd79137SRobert Mustacchi new_offset += shdr.sh_addralign - pad; 188*7fd79137SRobert Mustacchi shdr.sh_offset = new_offset; 189*7fd79137SRobert Mustacchi } 190*7fd79137SRobert Mustacchi 191*7fd79137SRobert Mustacchi shdr.sh_link = secxlate[shdr.sh_link]; 192*7fd79137SRobert Mustacchi 193*7fd79137SRobert Mustacchi if (shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) 194*7fd79137SRobert Mustacchi shdr.sh_info = secxlate[shdr.sh_info]; 195*7fd79137SRobert Mustacchi 196*7fd79137SRobert Mustacchi sname = elf_strptr(src, strndx, shdr.sh_name); 197*7fd79137SRobert Mustacchi if (sname == NULL) { 198*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 199*7fd79137SRobert Mustacchi goto out; 200*7fd79137SRobert Mustacchi } 201*7fd79137SRobert Mustacchi if ((sdata = elf_getdata(sscn, NULL)) == NULL) { 202*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 203*7fd79137SRobert Mustacchi goto out; 204*7fd79137SRobert Mustacchi } 205*7fd79137SRobert Mustacchi if ((ddata = elf_newdata(dscn)) == NULL) { 206*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 207*7fd79137SRobert Mustacchi goto out; 208*7fd79137SRobert Mustacchi } 209*7fd79137SRobert Mustacchi bcopy(sdata, ddata, sizeof (Elf_Data)); 210*7fd79137SRobert Mustacchi 211*7fd79137SRobert Mustacchi if (srcidx == strndx) { 212*7fd79137SRobert Mustacchi char seclen = strlen(CTF_ELF_SCN_NAME); 213*7fd79137SRobert Mustacchi 214*7fd79137SRobert Mustacchi strdatasz = ddata->d_size + shdr.sh_size + 215*7fd79137SRobert Mustacchi seclen + 1; 216*7fd79137SRobert Mustacchi ddata->d_buf = strdatabuf = ctf_alloc(strdatasz); 217*7fd79137SRobert Mustacchi if (ddata->d_buf == NULL) { 218*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 219*7fd79137SRobert Mustacchi goto out; 220*7fd79137SRobert Mustacchi } 221*7fd79137SRobert Mustacchi bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); 222*7fd79137SRobert Mustacchi (void) strcpy((caddr_t)ddata->d_buf + shdr.sh_size, 223*7fd79137SRobert Mustacchi CTF_ELF_SCN_NAME); 224*7fd79137SRobert Mustacchi ctfnameoff = (off_t)shdr.sh_size; 225*7fd79137SRobert Mustacchi shdr.sh_size += seclen + 1; 226*7fd79137SRobert Mustacchi ddata->d_size += seclen + 1; 227*7fd79137SRobert Mustacchi 228*7fd79137SRobert Mustacchi if (nphdr != 0) 229*7fd79137SRobert Mustacchi changing = 1; 230*7fd79137SRobert Mustacchi } 231*7fd79137SRobert Mustacchi 232*7fd79137SRobert Mustacchi if (shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) { 233*7fd79137SRobert Mustacchi int nsym = shdr.sh_size / shdr.sh_entsize; 234*7fd79137SRobert Mustacchi 235*7fd79137SRobert Mustacchi symtab_idx = secxlate[srcidx]; 236*7fd79137SRobert Mustacchi 237*7fd79137SRobert Mustacchi symdatasz = shdr.sh_size; 238*7fd79137SRobert Mustacchi ddata->d_buf = symdatabuf = ctf_alloc(symdatasz); 239*7fd79137SRobert Mustacchi if (ddata->d_buf == NULL) { 240*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 241*7fd79137SRobert Mustacchi goto out; 242*7fd79137SRobert Mustacchi } 243*7fd79137SRobert Mustacchi (void) bcopy(sdata->d_buf, ddata->d_buf, shdr.sh_size); 244*7fd79137SRobert Mustacchi 245*7fd79137SRobert Mustacchi for (i = 0; i < nsym; i++) { 246*7fd79137SRobert Mustacchi GElf_Sym sym; 247*7fd79137SRobert Mustacchi short newscn; 248*7fd79137SRobert Mustacchi 249*7fd79137SRobert Mustacchi (void) gelf_getsym(ddata, i, &sym); 250*7fd79137SRobert Mustacchi 251*7fd79137SRobert Mustacchi if (sym.st_shndx >= SHN_LORESERVE) 252*7fd79137SRobert Mustacchi continue; 253*7fd79137SRobert Mustacchi 254*7fd79137SRobert Mustacchi if ((newscn = secxlate[sym.st_shndx]) != 255*7fd79137SRobert Mustacchi sym.st_shndx) { 256*7fd79137SRobert Mustacchi sym.st_shndx = 257*7fd79137SRobert Mustacchi (newscn == -1 ? 1 : newscn); 258*7fd79137SRobert Mustacchi 259*7fd79137SRobert Mustacchi if (gelf_update_sym(ddata, i, &sym) == 260*7fd79137SRobert Mustacchi 0) { 261*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, 262*7fd79137SRobert Mustacchi ECTF_ELF); 263*7fd79137SRobert Mustacchi goto out; 264*7fd79137SRobert Mustacchi } 265*7fd79137SRobert Mustacchi } 266*7fd79137SRobert Mustacchi } 267*7fd79137SRobert Mustacchi } 268*7fd79137SRobert Mustacchi 269*7fd79137SRobert Mustacchi if (gelf_update_shdr(dscn, &shdr) == NULL) { 270*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 271*7fd79137SRobert Mustacchi goto out; 272*7fd79137SRobert Mustacchi } 273*7fd79137SRobert Mustacchi 274*7fd79137SRobert Mustacchi new_offset = (off_t)shdr.sh_offset; 275*7fd79137SRobert Mustacchi if (shdr.sh_type != SHT_NOBITS) 276*7fd79137SRobert Mustacchi new_offset += shdr.sh_size; 277*7fd79137SRobert Mustacchi } 278*7fd79137SRobert Mustacchi 279*7fd79137SRobert Mustacchi if (symtab_idx == -1) { 280*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 281*7fd79137SRobert Mustacchi goto out; 282*7fd79137SRobert Mustacchi } 283*7fd79137SRobert Mustacchi 284*7fd79137SRobert Mustacchi /* Add the ctf section */ 285*7fd79137SRobert Mustacchi if ((dscn = elf_newscn(dst)) == NULL) { 286*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 287*7fd79137SRobert Mustacchi goto out; 288*7fd79137SRobert Mustacchi } 289*7fd79137SRobert Mustacchi if (gelf_getshdr(dscn, &shdr) == NULL) { 290*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 291*7fd79137SRobert Mustacchi goto out; 292*7fd79137SRobert Mustacchi } 293*7fd79137SRobert Mustacchi shdr.sh_name = ctfnameoff; 294*7fd79137SRobert Mustacchi shdr.sh_type = SHT_PROGBITS; 295*7fd79137SRobert Mustacchi shdr.sh_size = fp->ctf_size; 296*7fd79137SRobert Mustacchi shdr.sh_link = symtab_idx; 297*7fd79137SRobert Mustacchi shdr.sh_addralign = 4; 298*7fd79137SRobert Mustacchi if (changing && nphdr != 0) { 299*7fd79137SRobert Mustacchi pad = new_offset % shdr.sh_addralign; 300*7fd79137SRobert Mustacchi 301*7fd79137SRobert Mustacchi if (pad) 302*7fd79137SRobert Mustacchi new_offset += shdr.sh_addralign - pad; 303*7fd79137SRobert Mustacchi 304*7fd79137SRobert Mustacchi shdr.sh_offset = new_offset; 305*7fd79137SRobert Mustacchi new_offset += shdr.sh_size; 306*7fd79137SRobert Mustacchi } 307*7fd79137SRobert Mustacchi 308*7fd79137SRobert Mustacchi if ((ddata = elf_newdata(dscn)) == NULL) { 309*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 310*7fd79137SRobert Mustacchi goto out; 311*7fd79137SRobert Mustacchi } 312*7fd79137SRobert Mustacchi 313*7fd79137SRobert Mustacchi if (compress != 0) { 314*7fd79137SRobert Mustacchi int err; 315*7fd79137SRobert Mustacchi 316*7fd79137SRobert Mustacchi if (ctf_zopen(&err) == NULL) { 317*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, err); 318*7fd79137SRobert Mustacchi goto out; 319*7fd79137SRobert Mustacchi } 320*7fd79137SRobert Mustacchi 321*7fd79137SRobert Mustacchi if ((err = ctf_compress(fp, &cdata, &asize, &elfsize)) != 0) { 322*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, err); 323*7fd79137SRobert Mustacchi goto out; 324*7fd79137SRobert Mustacchi } 325*7fd79137SRobert Mustacchi ddata->d_buf = cdata; 326*7fd79137SRobert Mustacchi ddata->d_size = elfsize; 327*7fd79137SRobert Mustacchi } else { 328*7fd79137SRobert Mustacchi ddata->d_buf = (void *)fp->ctf_base; 329*7fd79137SRobert Mustacchi ddata->d_size = fp->ctf_size; 330*7fd79137SRobert Mustacchi } 331*7fd79137SRobert Mustacchi ddata->d_align = shdr.sh_addralign; 332*7fd79137SRobert Mustacchi 333*7fd79137SRobert Mustacchi if (gelf_update_shdr(dscn, &shdr) == 0) { 334*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 335*7fd79137SRobert Mustacchi goto out; 336*7fd79137SRobert Mustacchi } 337*7fd79137SRobert Mustacchi 338*7fd79137SRobert Mustacchi /* update the section header location */ 339*7fd79137SRobert Mustacchi if (nphdr != 0) { 340*7fd79137SRobert Mustacchi size_t align = gelf_fsize(dst, ELF_T_ADDR, 1, EV_CURRENT); 341*7fd79137SRobert Mustacchi size_t r = new_offset % align; 342*7fd79137SRobert Mustacchi 343*7fd79137SRobert Mustacchi if (r) 344*7fd79137SRobert Mustacchi new_offset += align - r; 345*7fd79137SRobert Mustacchi 346*7fd79137SRobert Mustacchi dehdr.e_shoff = new_offset; 347*7fd79137SRobert Mustacchi } 348*7fd79137SRobert Mustacchi 349*7fd79137SRobert Mustacchi /* commit to disk */ 350*7fd79137SRobert Mustacchi if (sehdr.e_shstrndx == SHN_XINDEX) 351*7fd79137SRobert Mustacchi dehdr.e_shstrndx = SHN_XINDEX; 352*7fd79137SRobert Mustacchi else 353*7fd79137SRobert Mustacchi dehdr.e_shstrndx = secxlate[sehdr.e_shstrndx]; 354*7fd79137SRobert Mustacchi if (gelf_update_ehdr(dst, &dehdr) == NULL) { 355*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 356*7fd79137SRobert Mustacchi goto out; 357*7fd79137SRobert Mustacchi } 358*7fd79137SRobert Mustacchi if (elf_update(dst, ELF_C_WRITE) < 0) { 359*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, ECTF_ELF); 360*7fd79137SRobert Mustacchi goto out; 361*7fd79137SRobert Mustacchi } 362*7fd79137SRobert Mustacchi 363*7fd79137SRobert Mustacchi ret = 0; 364*7fd79137SRobert Mustacchi 365*7fd79137SRobert Mustacchi out: 366*7fd79137SRobert Mustacchi if (strdatabuf != NULL) 367*7fd79137SRobert Mustacchi ctf_free(strdatabuf, strdatasz); 368*7fd79137SRobert Mustacchi if (symdatabuf != NULL) 369*7fd79137SRobert Mustacchi ctf_free(symdatabuf, symdatasz); 370*7fd79137SRobert Mustacchi if (cdata != NULL) 371*7fd79137SRobert Mustacchi ctf_data_free(cdata, fp->ctf_size); 372*7fd79137SRobert Mustacchi if (secxlate != NULL) 373*7fd79137SRobert Mustacchi ctf_free(secxlate, sizeof (int) * nshdr); 374*7fd79137SRobert Mustacchi 375*7fd79137SRobert Mustacchi return (ret); 376*7fd79137SRobert Mustacchi } 377*7fd79137SRobert Mustacchi 378*7fd79137SRobert Mustacchi int 379*7fd79137SRobert Mustacchi ctf_elffdwrite(ctf_file_t *fp, int ifd, int ofd, int flags) 380*7fd79137SRobert Mustacchi { 381*7fd79137SRobert Mustacchi int ret; 382*7fd79137SRobert Mustacchi Elf *ielf, *oelf; 383*7fd79137SRobert Mustacchi 384*7fd79137SRobert Mustacchi (void) elf_version(EV_CURRENT); 385*7fd79137SRobert Mustacchi if ((ielf = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) 386*7fd79137SRobert Mustacchi return (ctf_set_errno(fp, ECTF_ELF)); 387*7fd79137SRobert Mustacchi 388*7fd79137SRobert Mustacchi if ((oelf = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL) 389*7fd79137SRobert Mustacchi return (ctf_set_errno(fp, ECTF_ELF)); 390*7fd79137SRobert Mustacchi 391*7fd79137SRobert Mustacchi ret = ctf_write_elf(fp, ielf, oelf, flags); 392*7fd79137SRobert Mustacchi 393*7fd79137SRobert Mustacchi (void) elf_end(ielf); 394*7fd79137SRobert Mustacchi (void) elf_end(oelf); 395*7fd79137SRobert Mustacchi 396*7fd79137SRobert Mustacchi return (ret); 397*7fd79137SRobert Mustacchi } 398*7fd79137SRobert Mustacchi 399*7fd79137SRobert Mustacchi int 400*7fd79137SRobert Mustacchi ctf_elfwrite(ctf_file_t *fp, const char *input, const char *output, int flags) 401*7fd79137SRobert Mustacchi { 402*7fd79137SRobert Mustacchi struct stat st; 403*7fd79137SRobert Mustacchi int ifd, ofd, ret; 404*7fd79137SRobert Mustacchi 405*7fd79137SRobert Mustacchi if ((ifd = open(input, O_RDONLY)) < 0) 406*7fd79137SRobert Mustacchi return (ctf_set_errno(fp, errno)); 407*7fd79137SRobert Mustacchi 408*7fd79137SRobert Mustacchi if (fstat(ifd, &st) < 0) 409*7fd79137SRobert Mustacchi return (ctf_set_errno(fp, errno)); 410*7fd79137SRobert Mustacchi 411*7fd79137SRobert Mustacchi if ((ofd = open(output, O_RDWR | O_CREAT | O_TRUNC, st.st_mode)) < 0) 412*7fd79137SRobert Mustacchi return (ctf_set_errno(fp, errno)); 413*7fd79137SRobert Mustacchi 414*7fd79137SRobert Mustacchi ret = ctf_elffdwrite(fp, ifd, ofd, flags); 415*7fd79137SRobert Mustacchi 416*7fd79137SRobert Mustacchi if (close(ifd) != 0 && ret == 0) 417*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, errno); 418*7fd79137SRobert Mustacchi if (close(ofd) != 0 && ret == 0) 419*7fd79137SRobert Mustacchi ret = ctf_set_errno(fp, errno); 420*7fd79137SRobert Mustacchi 421*7fd79137SRobert Mustacchi return (ret); 422*7fd79137SRobert Mustacchi } 423