1*2722387fSrie /*
2*2722387fSrie  * CDDL HEADER START
3*2722387fSrie  *
4*2722387fSrie  * The contents of this file are subject to the terms of the
5*2722387fSrie  * Common Development and Distribution License (the "License").
6*2722387fSrie  * You may not use this file except in compliance with the License.
7*2722387fSrie  *
8*2722387fSrie  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2722387fSrie  * or http://www.opensolaris.org/os/licensing.
10*2722387fSrie  * See the License for the specific language governing permissions
11*2722387fSrie  * and limitations under the License.
12*2722387fSrie  *
13*2722387fSrie  * When distributing Covered Code, include this CDDL HEADER in each
14*2722387fSrie  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2722387fSrie  * If applicable, add the following below this CDDL HEADER, with the
16*2722387fSrie  * fields enclosed by brackets "[]" replaced with your own identifying
17*2722387fSrie  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2722387fSrie  *
19*2722387fSrie  * CDDL HEADER END
20*2722387fSrie  */
21*2722387fSrie 
22*2722387fSrie /*
23*2722387fSrie  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*2722387fSrie  * Use is subject to license terms.
25*2722387fSrie  */
26*2722387fSrie 
27*2722387fSrie #include	<sys/types.h>
28*2722387fSrie #include	<sys/stat.h>
29*2722387fSrie #include	<sys/mman.h>
30*2722387fSrie #include	<unistd.h>
31*2722387fSrie #include	<fcntl.h>
32*2722387fSrie #include	<libgen.h>
33*2722387fSrie #include	<errno.h>
34*2722387fSrie #include	<libelf.h>
35*2722387fSrie #include	<stdio.h>
36*2722387fSrie #include	<strings.h>
37*2722387fSrie #include	<msg.h>
38*2722387fSrie #include	<machdep.h>
39*2722387fSrie #include	<_libelf.h>
40*2722387fSrie #include	<_elfwrap.h>
41*2722387fSrie 
42*2722387fSrie /*
43*2722387fSrie  * This module is compiled to support 32-bit and 64-bit class objects.  Define
44*2722387fSrie  * the necessary interfaces for these classes.
45*2722387fSrie  */
46*2722387fSrie #if	defined(_ELF64)
47*2722387fSrie #define	input	input64
48*2722387fSrie #define	output	output64
49*2722387fSrie #else
50*2722387fSrie #define	input	input32
51*2722387fSrie #define	output	output32
52*2722387fSrie #endif
53*2722387fSrie 
54*2722387fSrie static StdSec_t	StdSecs[] = {
55*2722387fSrie 	{ MSG_ORIG(MSG_SCN_SYMTAB),	SHT_SYMTAB,	0 },
56*2722387fSrie 	{ MSG_ORIG(MSG_SCN_STRTAB),	SHT_STRTAB,	SHF_STRINGS},
57*2722387fSrie 	{ MSG_ORIG(MSG_SCN_SHSTRTAB),	SHT_STRTAB,	SHF_STRINGS},
58*2722387fSrie 	{ NULL,				0,		0 }
59*2722387fSrie };
60*2722387fSrie 
61*2722387fSrie /*
62*2722387fSrie  * Process all input files.  These contain the data that will be assigned to a
63*2722387fSrie  * new ELF section.
64*2722387fSrie  */
65*2722387fSrie int
input(int argc,char ** argv,const char * prog,const char * ofile,ObjDesc_t * odp)66*2722387fSrie input(int argc, char **argv, const char *prog, const char *ofile,
67*2722387fSrie     ObjDesc_t *odp)
68*2722387fSrie {
69*2722387fSrie 	OutSec_t	outsec;
70*2722387fSrie 	StdSec_t	*stdsecs;
71*2722387fSrie 	size_t		ndx, cnt;
72*2722387fSrie 	int		ret = 0, fd = -1;
73*2722387fSrie 
74*2722387fSrie 	/*
75*2722387fSrie 	 * Make sure we have access to read each input file, and prepare an
76*2722387fSrie 	 * output section descriptor for each.  Note, we assign section indexes
77*2722387fSrie 	 * starting at 1, as section index 0 is special, and is created by
78*2722387fSrie 	 * libelf.
79*2722387fSrie 	 */
80*2722387fSrie 	for (ndx = 1; argc; argc--, argv++, ndx++) {
81*2722387fSrie 		char		*file = *argv;
82*2722387fSrie 		struct stat	status;
83*2722387fSrie 		size_t		namesz;
84*2722387fSrie 
85*2722387fSrie 		/*
86*2722387fSrie 		 * Close any previously opened file.
87*2722387fSrie 		 */
88*2722387fSrie 		if (fd != -1)
89*2722387fSrie 			(void) close(fd);
90*2722387fSrie 
91*2722387fSrie 		/*
92*2722387fSrie 		 * Identify the section.
93*2722387fSrie 		 */
94*2722387fSrie 		outsec.os_name = basename(file);
95*2722387fSrie 		outsec.os_type = SHT_PROGBITS;
96*2722387fSrie 		outsec.os_flags = SHF_ALLOC;
97*2722387fSrie 		outsec.os_ndx = ndx;
98*2722387fSrie 
99*2722387fSrie 		if ((fd = open(file, O_RDONLY)) == -1) {
100*2722387fSrie 			int err = errno;
101*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
102*2722387fSrie 			    prog, file, strerror(err));
103*2722387fSrie 			ret = 1;
104*2722387fSrie 			continue;
105*2722387fSrie 		}
106*2722387fSrie 		if (fstat(fd, &status) == -1) {
107*2722387fSrie 			int err = errno;
108*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_FSTAT),
109*2722387fSrie 			    prog, file, strerror(err));
110*2722387fSrie 			ret = 1;
111*2722387fSrie 			continue;
112*2722387fSrie 		}
113*2722387fSrie 
114*2722387fSrie 		if ((outsec.os_size = status.st_size) == 0) {
115*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_WARN_ZERO),
116*2722387fSrie 			    prog, file);
117*2722387fSrie 			continue;
118*2722387fSrie 		}
119*2722387fSrie 
120*2722387fSrie 		if ((outsec.os_addr = mmap(0, outsec.os_size, PROT_READ,
121*2722387fSrie 		    MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
122*2722387fSrie 			int err = errno;
123*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_MMAP),
124*2722387fSrie 			    prog, file, strerror(err));
125*2722387fSrie 			ret = 1;
126*2722387fSrie 			continue;
127*2722387fSrie 		}
128*2722387fSrie 
129*2722387fSrie 		if (alist_append(&(odp->od_outsecs), &outsec, sizeof (OutSec_t),
130*2722387fSrie 		    AL_CNT_WOSECS) == 0) {
131*2722387fSrie 			int err = errno;
132*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_ALLOC),
133*2722387fSrie 			    prog, file, strerror(err));
134*2722387fSrie 			return (1);
135*2722387fSrie 		}
136*2722387fSrie 
137*2722387fSrie 		/*
138*2722387fSrie 		 * Each data section contributes:
139*2722387fSrie 		 *
140*2722387fSrie 		 * i.	its basename, prefixed with a "dot", to the .shstrtab.
141*2722387fSrie 		 * ii.	a section symbol.
142*2722387fSrie 		 * iii.	a data symbol, using the basename, with an
143*2722387fSrie 		 *	appended "_data" string.
144*2722387fSrie 		 * iv.	a data size symbol, using the basename with an
145*2722387fSrie 		 *	appended "_size" string.
146*2722387fSrie 		 */
147*2722387fSrie 		namesz = strlen(outsec.os_name) + 1;
148*2722387fSrie 
149*2722387fSrie 		odp->od_symtabno += 3;
150*2722387fSrie 		odp->od_strtabsz += (namesz + MSG_STR_START_SIZE);
151*2722387fSrie 		odp->od_strtabsz += (namesz + MSG_STR_END_SIZE);
152*2722387fSrie 		odp->od_shstrtabsz += (namesz + MSG_STR_DOT_SIZE);
153*2722387fSrie 	}
154*2722387fSrie 
155*2722387fSrie 	if (fd != -1)
156*2722387fSrie 		(void) close(fd);
157*2722387fSrie 
158*2722387fSrie 	/*
159*2722387fSrie 	 * If an error occurred, or no input files contributed data, bail now.
160*2722387fSrie 	 */
161*2722387fSrie 	if (ret || (odp->od_outsecs == NULL))
162*2722387fSrie 		return (1);
163*2722387fSrie 
164*2722387fSrie 	/*
165*2722387fSrie 	 * Create section descriptors for .symtab, .strtab, and .shstrtab.
166*2722387fSrie 	 */
167*2722387fSrie 	for (cnt = 0, stdsecs = &StdSecs[cnt]; stdsecs->ss_name; cnt++,
168*2722387fSrie 	    ndx++, stdsecs = &StdSecs[cnt]) {
169*2722387fSrie 
170*2722387fSrie 		/*
171*2722387fSrie 		 * Identify the section.
172*2722387fSrie 		 */
173*2722387fSrie 		outsec.os_name = stdsecs->ss_name;
174*2722387fSrie 		outsec.os_type = stdsecs->ss_type;
175*2722387fSrie 		outsec.os_flags = stdsecs->ss_flags;
176*2722387fSrie 		outsec.os_ndx = ndx;
177*2722387fSrie 		outsec.os_size = 0;
178*2722387fSrie 		outsec.os_addr = 0;
179*2722387fSrie 
180*2722387fSrie 		if (alist_append(&(odp->od_outsecs), &outsec, sizeof (OutSec_t),
181*2722387fSrie 		    AL_CNT_WOSECS) == 0) {
182*2722387fSrie 			int err = errno;
183*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ERR_ALLOC),
184*2722387fSrie 			    prog, outsec.os_name, strerror(err));
185*2722387fSrie 			return (1);
186*2722387fSrie 		}
187*2722387fSrie 
188*2722387fSrie 		/*
189*2722387fSrie 		 * Each standard section contributes:
190*2722387fSrie 		 *
191*2722387fSrie 		 * i.	its section name to the .shstrtab.
192*2722387fSrie 		 * ii.	a section symbol.
193*2722387fSrie 		 */
194*2722387fSrie 		odp->od_symtabno++;
195*2722387fSrie 		odp->od_shstrtabsz += (strlen(outsec.os_name) + 1);
196*2722387fSrie 	}
197*2722387fSrie 
198*2722387fSrie 	/*
199*2722387fSrie 	 * The symbol table requires an initial NULL entry and a following
200*2722387fSrie 	 * FILE entry.  Both string tables require an initial NULL byte.
201*2722387fSrie 	 * The .strtab requires room for the output file name (STT_FILE).
202*2722387fSrie 	 */
203*2722387fSrie 	odp->od_symtabno += 2;
204*2722387fSrie 	odp->od_strtabsz += strlen(ofile) + 2;
205*2722387fSrie 	odp->od_shstrtabsz++;
206*2722387fSrie 
207*2722387fSrie 	return (0);
208*2722387fSrie }
209*2722387fSrie 
210*2722387fSrie /*
211*2722387fSrie  * Having captured all input data, create the output file.
212*2722387fSrie  */
213*2722387fSrie int
output(const char * prog,int fd,const char * ofile,ushort_t mach,ObjDesc_t * odp)214*2722387fSrie output(const char *prog, int fd, const char *ofile, ushort_t mach,
215*2722387fSrie     ObjDesc_t *odp)
216*2722387fSrie {
217*2722387fSrie 	Aliste		off;
218*2722387fSrie 	Elf		*melf, *oelf;
219*2722387fSrie 	Ehdr		*ehdr;
220*2722387fSrie 	Sym		*symtab, *secsymtabent, *glbsymtabent;
221*2722387fSrie 	char		*strtab, *strtabent, *shstrtab, *shstrtabent;
222*2722387fSrie 	OutSec_t	*outsec, *outsymtab, *outstrtab, *outshstrtab;
223*2722387fSrie 	size_t		len;
224*2722387fSrie 	TargDesc_t	tdesc;
225*2722387fSrie 
226*2722387fSrie 	/*
227*2722387fSrie 	 * Obtain any target specific ELF information.
228*2722387fSrie 	 */
229*2722387fSrie 	if (mach == 0)
230*2722387fSrie 		mach = M_MACH;
231*2722387fSrie 
232*2722387fSrie 	switch (mach) {
233*2722387fSrie #if	!defined(lint)
234*2722387fSrie 		case EM_SPARC:
235*2722387fSrie 			target_init_sparc(&tdesc);
236*2722387fSrie 			break;
237*2722387fSrie 		case EM_SPARCV9:
238*2722387fSrie 			target_init_sparcv9(&tdesc);
239*2722387fSrie 			break;
240*2722387fSrie 		case EM_386:
241*2722387fSrie 			target_init_i386(&tdesc);
242*2722387fSrie 			break;
243*2722387fSrie 		case EM_AMD64:
244*2722387fSrie 			target_init_amd64(&tdesc);
245*2722387fSrie 			break;
246*2722387fSrie #else
247*2722387fSrie 		default:
248*2722387fSrie 			target_init(&tdesc);
249*2722387fSrie 			break;
250*2722387fSrie #endif
251*2722387fSrie 	}
252*2722387fSrie 	/*
253*2722387fSrie 	 * Create a new ELF descriptor for the new output file.
254*2722387fSrie 	 */
255*2722387fSrie 	if ((oelf = elf_begin(fd, ELF_C_WRITE, 0)) == NULL) {
256*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN), prog,
257*2722387fSrie 		    elf_errmsg(elf_errno()));
258*2722387fSrie 		return (1);
259*2722387fSrie 	}
260*2722387fSrie 
261*2722387fSrie 	/*
262*2722387fSrie 	 * Create and initialize the new ELF header.
263*2722387fSrie 	 */
264*2722387fSrie 	if ((ehdr = elf_newehdr(oelf)) == NULL) {
265*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_NEWEHDR), prog,
266*2722387fSrie 		    elf_errmsg(elf_errno()));
267*2722387fSrie 		return (1);
268*2722387fSrie 	}
269*2722387fSrie 
270*2722387fSrie 	/*
271*2722387fSrie 	 * Note, the ELF header is initialized to reflect the host running
272*2722387fSrie 	 * elfwrap(1) rather than the target.  Using host byte order allows
273*2722387fSrie 	 * elfwrap(1) to create the object data.  Prior to the final update,
274*2722387fSrie 	 * the output ELF header is modified to reflect the target, causing
275*2722387fSrie 	 * libelf to produce the output object using the correct byte order
276*2722387fSrie 	 * and other target information.
277*2722387fSrie 	 */
278*2722387fSrie 	ehdr->e_ident[EI_DATA] = M_DATA;
279*2722387fSrie 	ehdr->e_type = ET_REL;
280*2722387fSrie 	ehdr->e_version = EV_CURRENT;
281*2722387fSrie 
282*2722387fSrie 	/*
283*2722387fSrie 	 * Create the required number of new sections, their associated section
284*2722387fSrie 	 * header, and an initial data buffer.
285*2722387fSrie 	 */
286*2722387fSrie 	for (ALIST_TRAVERSE(odp->od_outsecs, off, outsec)) {
287*2722387fSrie 		Elf_Scn		*scn;
288*2722387fSrie 		Elf_Data	*data;
289*2722387fSrie 		Shdr		*shdr;
290*2722387fSrie 
291*2722387fSrie 		if ((scn = elf_newscn(oelf)) == NULL) {
292*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_NEWSCN),
293*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
294*2722387fSrie 			return (1);
295*2722387fSrie 		}
296*2722387fSrie 		if ((shdr = elf_getshdr(scn)) == NULL) {
297*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSHDR),
298*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
299*2722387fSrie 			return (1);
300*2722387fSrie 		}
301*2722387fSrie 
302*2722387fSrie 		/*
303*2722387fSrie 		 * Assign the section type and flags.
304*2722387fSrie 		 */
305*2722387fSrie 		shdr->sh_type = outsec->os_type;
306*2722387fSrie 		shdr->sh_flags = outsec->os_flags;
307*2722387fSrie 
308*2722387fSrie 		if ((data = elf_newdata(scn)) == NULL) {
309*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_NEWDATA),
310*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
311*2722387fSrie 			return (1);
312*2722387fSrie 		}
313*2722387fSrie 
314*2722387fSrie 		switch (shdr->sh_type) {
315*2722387fSrie 		case SHT_PROGBITS:
316*2722387fSrie 			/*
317*2722387fSrie 			 * If this is a PROGBITS section, then the data
318*2722387fSrie 			 * originates from an input file.  Assign the data
319*2722387fSrie 			 * buffer to this input file and provide a default
320*2722387fSrie 			 * alignment.
321*2722387fSrie 			 */
322*2722387fSrie 			data->d_buf = outsec->os_addr;
323*2722387fSrie 			data->d_type = ELF_T_BYTE;
324*2722387fSrie 			data->d_size = outsec->os_size;
325*2722387fSrie 			data->d_align = tdesc.td_align;
326*2722387fSrie 			break;
327*2722387fSrie 
328*2722387fSrie 		case SHT_SYMTAB:
329*2722387fSrie 			/*
330*2722387fSrie 			 * If this is the symbol table, use the symbol count to
331*2722387fSrie 			 * reserve sufficient space for the symbols we need.
332*2722387fSrie 			 */
333*2722387fSrie 			data->d_buf = 0;
334*2722387fSrie 			data->d_type = ELF_T_SYM;
335*2722387fSrie 			data->d_size = (odp->od_symtabno * tdesc.td_symsz);
336*2722387fSrie 			data->d_align = tdesc.td_align;
337*2722387fSrie 			break;
338*2722387fSrie 
339*2722387fSrie 		case SHT_STRTAB:
340*2722387fSrie 			/*
341*2722387fSrie 			 * If this is a string table, use the table size to
342*2722387fSrie 			 * reserve sufficient space for the strings we need.
343*2722387fSrie 			 */
344*2722387fSrie 			data->d_buf = 0;
345*2722387fSrie 			data->d_type = ELF_T_BYTE;
346*2722387fSrie 			if (strcmp(outsec->os_name, MSG_ORIG(MSG_SCN_STRTAB)))
347*2722387fSrie 				data->d_size = odp->od_shstrtabsz;
348*2722387fSrie 			else
349*2722387fSrie 				data->d_size = odp->od_strtabsz;
350*2722387fSrie 			data->d_align = 1;
351*2722387fSrie 			break;
352*2722387fSrie 		}
353*2722387fSrie 	}
354*2722387fSrie 
355*2722387fSrie 	/*
356*2722387fSrie 	 * Write the ELF data into a memory image.
357*2722387fSrie 	 */
358*2722387fSrie 	if ((elf_update(oelf, ELF_C_WRIMAGE)) == -1) {
359*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_UPDATE), prog,
360*2722387fSrie 		    elf_errmsg(elf_errno()));
361*2722387fSrie 		return (1);
362*2722387fSrie 	}
363*2722387fSrie 
364*2722387fSrie 	/*
365*2722387fSrie 	 * Assign an ELF descriptor to the memory image.
366*2722387fSrie 	 */
367*2722387fSrie 	if ((melf = elf_begin(0, ELF_C_IMAGE, oelf)) == NULL) {
368*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN), prog,
369*2722387fSrie 		    elf_errmsg(elf_errno()));
370*2722387fSrie 		return (1);
371*2722387fSrie 	}
372*2722387fSrie 
373*2722387fSrie 	/*
374*2722387fSrie 	 * Get the ELF header from the memory image.
375*2722387fSrie 	 */
376*2722387fSrie 	if ((ehdr = elf_getehdr(melf)) == NULL) {
377*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_GETEHDR), prog,
378*2722387fSrie 		    elf_errmsg(elf_errno()));
379*2722387fSrie 		return (1);
380*2722387fSrie 	}
381*2722387fSrie 
382*2722387fSrie 	/*
383*2722387fSrie 	 * Read the section header and data from the new sections of the
384*2722387fSrie 	 * memory image.
385*2722387fSrie 	 */
386*2722387fSrie 	for (ALIST_TRAVERSE(odp->od_outsecs, off, outsec)) {
387*2722387fSrie 		Elf_Scn		*scn;
388*2722387fSrie 		Shdr		*shdr;
389*2722387fSrie 
390*2722387fSrie 		if ((scn = elf_getscn(melf, outsec->os_ndx)) == NULL) {
391*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSCN),
392*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
393*2722387fSrie 			return (1);
394*2722387fSrie 		}
395*2722387fSrie 		if ((outsec->os_shdr = shdr = elf_getshdr(scn)) == NULL) {
396*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSHDR),
397*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
398*2722387fSrie 			return (1);
399*2722387fSrie 		}
400*2722387fSrie 		if ((outsec->os_data = elf_getdata(scn, NULL)) == NULL) {
401*2722387fSrie 			(void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA),
402*2722387fSrie 			    prog, outsec->os_name, elf_errmsg(elf_errno()));
403*2722387fSrie 			return (1);
404*2722387fSrie 		}
405*2722387fSrie 
406*2722387fSrie 		if (shdr->sh_type == SHT_PROGBITS)
407*2722387fSrie 			continue;
408*2722387fSrie 
409*2722387fSrie 		/*
410*2722387fSrie 		 * Remember the symbol table and string tables, so that they
411*2722387fSrie 		 * can be filled in later.
412*2722387fSrie 		 */
413*2722387fSrie 		if (shdr->sh_type == SHT_SYMTAB) {
414*2722387fSrie 			outsymtab = outsec;
415*2722387fSrie 			symtab = (Sym *)outsec->os_data->d_buf;
416*2722387fSrie 		} else if (shdr->sh_type == SHT_STRTAB) {
417*2722387fSrie 			if (strcmp(outsec->os_name, MSG_ORIG(MSG_SCN_STRTAB))) {
418*2722387fSrie 				outshstrtab = outsec;
419*2722387fSrie 				shstrtab = (char *)outsec->os_data->d_buf;
420*2722387fSrie 			} else {
421*2722387fSrie 				outstrtab = outsec;
422*2722387fSrie 				strtab = (char *)outsec->os_data->d_buf;
423*2722387fSrie 			}
424*2722387fSrie 		}
425*2722387fSrie 	}
426*2722387fSrie 
427*2722387fSrie 	/*
428*2722387fSrie 	 * Update the ELF header with the .shstrtab index.
429*2722387fSrie 	 */
430*2722387fSrie 	ehdr->e_shstrndx = outshstrtab->os_ndx;
431*2722387fSrie 
432*2722387fSrie 	/*
433*2722387fSrie 	 * Set up the string table entries, and skip the first byte.
434*2722387fSrie 	 */
435*2722387fSrie 	strtabent = strtab;
436*2722387fSrie 	strtabent++;
437*2722387fSrie 
438*2722387fSrie 	shstrtabent = shstrtab;
439*2722387fSrie 	shstrtabent++;
440*2722387fSrie 
441*2722387fSrie 	/*
442*2722387fSrie 	 * Skip the first symbol table entry.  Write a FILE entry, and set
443*2722387fSrie 	 * up for adding sections and data symbols.  Associate the symbol
444*2722387fSrie 	 * table with the string table.
445*2722387fSrie 	 */
446*2722387fSrie 	secsymtabent = symtab;
447*2722387fSrie 	secsymtabent++;
448*2722387fSrie 	secsymtabent->st_name = (strtabent - strtab);
449*2722387fSrie 	secsymtabent->st_info = ELF_ST_INFO(STB_LOCAL, STT_NOTYPE);
450*2722387fSrie 	secsymtabent->st_shndx = SHN_ABS;
451*2722387fSrie 	secsymtabent++;
452*2722387fSrie 
453*2722387fSrie 	glbsymtabent = secsymtabent;
454*2722387fSrie 	glbsymtabent += alist_nitems(odp->od_outsecs);
455*2722387fSrie 
456*2722387fSrie 	outsymtab->os_shdr->sh_link = outstrtab->os_ndx;
457*2722387fSrie 
458*2722387fSrie 	/*
459*2722387fSrie 	 * Write the output file name to the .strtab.
460*2722387fSrie 	 */
461*2722387fSrie 	len = strlen(ofile) + 1;
462*2722387fSrie 	(void) memcpy(strtabent, ofile, len);
463*2722387fSrie 	strtabent += len;
464*2722387fSrie 
465*2722387fSrie 	/*
466*2722387fSrie 	 * Rescan all the new sections, adding symbols and strings as required.
467*2722387fSrie 	 */
468*2722387fSrie 	for (ALIST_TRAVERSE(odp->od_outsecs, off, outsec)) {
469*2722387fSrie 		size_t	alen;
470*2722387fSrie 
471*2722387fSrie 		/*
472*2722387fSrie 		 * Create a section symbol.
473*2722387fSrie 		 */
474*2722387fSrie 		secsymtabent->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION);
475*2722387fSrie 		secsymtabent->st_shndx = outsec->os_ndx;
476*2722387fSrie 		secsymtabent++;
477*2722387fSrie 
478*2722387fSrie 		/*
479*2722387fSrie 		 * Store the section name, (with an appended "." if the section
480*2722387fSrie 		 * name is derived from the input file name), and point the
481*2722387fSrie 		 * section header to this name.
482*2722387fSrie 		 */
483*2722387fSrie 		outsec->os_shdr->sh_name = (shstrtabent - shstrtab);
484*2722387fSrie 
485*2722387fSrie 		if (outsec->os_shdr->sh_type == SHT_PROGBITS) {
486*2722387fSrie 			(void) memcpy(shstrtabent, MSG_ORIG(MSG_STR_DOT),
487*2722387fSrie 			    MSG_STR_DOT_SIZE);
488*2722387fSrie 			shstrtabent += MSG_STR_DOT_SIZE;
489*2722387fSrie 		}
490*2722387fSrie 
491*2722387fSrie 		len = strlen(outsec->os_name) + 1;
492*2722387fSrie 		(void) memcpy(shstrtabent, outsec->os_name, len);
493*2722387fSrie 		shstrtabent += len;
494*2722387fSrie 
495*2722387fSrie 		if (outsec->os_shdr->sh_type != SHT_PROGBITS)
496*2722387fSrie 			continue;
497*2722387fSrie 
498*2722387fSrie 		/*
499*2722387fSrie 		 * Add a symbol pointing to this PROGBITS section.  The value
500*2722387fSrie 		 * is the base offset of this section, which can only be 0.
501*2722387fSrie 		 * The size of the symbol can be taken straight from the section
502*2722387fSrie 		 * header information (that libelf generated).
503*2722387fSrie 		 */
504*2722387fSrie 		glbsymtabent->st_name = (strtabent - strtab);
505*2722387fSrie 		glbsymtabent->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
506*2722387fSrie 		glbsymtabent->st_shndx = outsec->os_ndx;
507*2722387fSrie 		glbsymtabent->st_size = outsec->os_shdr->sh_size;
508*2722387fSrie 		glbsymtabent++;
509*2722387fSrie 
510*2722387fSrie 		/*
511*2722387fSrie 		 * Store this symbol name (with an appended "_data") in the
512*2722387fSrie 		 * string table.
513*2722387fSrie 		 */
514*2722387fSrie 		len--;
515*2722387fSrie 		(void) memcpy(strtabent, outsec->os_name, len);
516*2722387fSrie 		strtabent += len;
517*2722387fSrie 		alen = (MSG_STR_START_SIZE + 1);
518*2722387fSrie 		(void) memcpy(strtabent, MSG_ORIG(MSG_STR_START), alen);
519*2722387fSrie 		strtabent += alen;
520*2722387fSrie 
521*2722387fSrie 		/*
522*2722387fSrie 		 * Add a symbol indicating the size of this PROGBITS section.
523*2722387fSrie 		 */
524*2722387fSrie 		glbsymtabent->st_name = (strtabent - strtab);
525*2722387fSrie 		glbsymtabent->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
526*2722387fSrie 		glbsymtabent->st_shndx = outsec->os_ndx;
527*2722387fSrie 		glbsymtabent->st_value = outsec->os_shdr->sh_size;
528*2722387fSrie 		glbsymtabent++;
529*2722387fSrie 
530*2722387fSrie 		/*
531*2722387fSrie 		 * Store this symbol name (with an appended "_end") in the
532*2722387fSrie 		 * string table.
533*2722387fSrie 		 */
534*2722387fSrie 		(void) memcpy(strtabent, outsec->os_name, len);
535*2722387fSrie 		strtabent += len;
536*2722387fSrie 		alen = (MSG_STR_END_SIZE + 1);
537*2722387fSrie 		(void) memcpy(strtabent, MSG_ORIG(MSG_STR_END), alen);
538*2722387fSrie 		strtabent += alen;
539*2722387fSrie 	}
540*2722387fSrie 
541*2722387fSrie 	/*
542*2722387fSrie 	 * Update the .symtab section header with the index of the first
543*2722387fSrie 	 * non-local symbol.  The only locals written are the section symbols.
544*2722387fSrie 	 */
545*2722387fSrie 	outsymtab->os_shdr->sh_info = (secsymtabent - symtab);
546*2722387fSrie 
547*2722387fSrie 	/*
548*2722387fSrie 	 * Having updated the image following the byte order of elfwrap(), seed
549*2722387fSrie 	 * the ELF header with the appropriate target information.
550*2722387fSrie 	 */
551*2722387fSrie 	ehdr->e_ident[EI_CLASS] = tdesc.td_class;
552*2722387fSrie 	ehdr->e_ident[EI_DATA] = tdesc.td_data;
553*2722387fSrie 	ehdr->e_machine = tdesc.td_mach;
554*2722387fSrie 
555*2722387fSrie 	/*
556*2722387fSrie 	 * If the output relocatable object is targeted to a machine with a
557*2722387fSrie 	 * different byte order than the host running elfwrap(1), swap the data
558*2722387fSrie 	 * to the target byte order.
559*2722387fSrie 	 */
560*2722387fSrie 	if ((_elf_sys_encoding() != ehdr->e_ident[EI_DATA]) &&
561*2722387fSrie 	    (_elf_swap_wrimage(melf) != 0)) {
562*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_SWAP_WRIMAGE), prog,
563*2722387fSrie 		    elf_errmsg(elf_errno()));
564*2722387fSrie 		return (1);
565*2722387fSrie 	}
566*2722387fSrie 	(void) elf_end(melf);
567*2722387fSrie 
568*2722387fSrie 	/*
569*2722387fSrie 	 * Finally, write the updated memory image out to disc.
570*2722387fSrie 	 */
571*2722387fSrie 	if ((elf_update(oelf, ELF_C_WRITE)) == -1) {
572*2722387fSrie 		(void) fprintf(stderr, MSG_INTL(MSG_ELF_UPDATE), prog,
573*2722387fSrie 		    elf_errmsg(elf_errno()));
574*2722387fSrie 		return (1);
575*2722387fSrie 	}
576*2722387fSrie 	(void) elf_end(oelf);
577*2722387fSrie 
578*2722387fSrie 	return (0);
579*2722387fSrie }
580