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 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 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