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