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