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