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