17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*30a4e2aaSab * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 297c478bd9Sstevel@tonic-gate * All Rights Reserved 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include "gelf.h" 367c478bd9Sstevel@tonic-gate #include "inc.h" 377c478bd9Sstevel@tonic-gate #include "extern.h" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate static char *str_base; /* start of string table for names */ 407c478bd9Sstevel@tonic-gate static char *str_top; /* pointer to next available location */ 417c478bd9Sstevel@tonic-gate static char *str_base1, *str_top1; 427c478bd9Sstevel@tonic-gate static int pad_symtab; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* 467c478bd9Sstevel@tonic-gate * Function Prototypes 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate static long mklong_tab(int *); 497c478bd9Sstevel@tonic-gate static char *trimslash(char *s); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static long mksymtab(ARFILEP **, Cmd_info *, int *); 527c478bd9Sstevel@tonic-gate static int writesymtab(char *, long, ARFILEP *); 537c478bd9Sstevel@tonic-gate static void savename(char *); 547c478bd9Sstevel@tonic-gate static void savelongname(ARFILE *, char *); 557c478bd9Sstevel@tonic-gate static void sputl(long, char *); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static char *writelargefile(Cmd_info *cmd_info, long long_tab_size, 587c478bd9Sstevel@tonic-gate int longnames, ARFILEP *symlist, long nsyms, int found_obj, 597c478bd9Sstevel@tonic-gate int new_archive); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate static int sizeofmembers(); 627c478bd9Sstevel@tonic-gate static int sizeofnewarchive(int, int); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static int search_sym_tab(ARFILE *, Elf *, Elf_Scn *, 657c478bd9Sstevel@tonic-gate long *, ARFILEP **, int *); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #ifdef BROWSER 687c478bd9Sstevel@tonic-gate static void sbrowser_search_stab(Elf *, int, int, char *); 697c478bd9Sstevel@tonic-gate #endif 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate int 737c478bd9Sstevel@tonic-gate getaf(Cmd_info *cmd_info) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate Elf_Cmd cmd; 767c478bd9Sstevel@tonic-gate int fd; 777c478bd9Sstevel@tonic-gate char *arnam = cmd_info->arnam; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate if (elf_version(EV_CURRENT) == EV_NONE) { 807c478bd9Sstevel@tonic-gate error_message(ELF_VERSION_ERROR, 817c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 827c478bd9Sstevel@tonic-gate exit(1); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) { 867c478bd9Sstevel@tonic-gate if (errno == ENOENT) { 877c478bd9Sstevel@tonic-gate /* archive does not exist yet, may have to create one */ 887c478bd9Sstevel@tonic-gate return (fd); 897c478bd9Sstevel@tonic-gate } else { 907c478bd9Sstevel@tonic-gate /* problem other than "does not exist" */ 917c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 927c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), arnam); 937c478bd9Sstevel@tonic-gate exit(1); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate cmd = ELF_C_READ; 987c478bd9Sstevel@tonic-gate cmd_info->arf = elf_begin(fd, cmd, (Elf *)0); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate if (elf_kind(cmd_info->arf) != ELF_K_AR) { 1017c478bd9Sstevel@tonic-gate error_message(NOT_ARCHIVE_ERROR, 1027c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, arnam); 1037c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) 1047c478bd9Sstevel@tonic-gate error_message(USAGE_06_ERROR, 1057c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, cmd_info->ponam); 1067c478bd9Sstevel@tonic-gate exit(1); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate return (fd); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 111*30a4e2aaSab /* 112*30a4e2aaSab * If the current archive item is a 32 or 64-bit object, then 113*30a4e2aaSab * ar(1) may have added newline padding at the end in order to 114*30a4e2aaSab * bring 64-bit objects into 8-byte alignment within the file. This 115*30a4e2aaSab * padding cannot be distinguished from data using the information kept 116*30a4e2aaSab * in the ar headers. This routine examines the objects, using knowledge of 117*30a4e2aaSab * ELF and how our tools lay out objects to determine whether padding was 118*30a4e2aaSab * added to an archive item. If so, it adjusts the st_size and 119*30a4e2aaSab * st_padding fields of the file argument to reflect it. 120*30a4e2aaSab */ 121*30a4e2aaSab static void 122*30a4e2aaSab recover_padding(Elf *elf, ARFILE *file) 123*30a4e2aaSab { 124*30a4e2aaSab long extent; 125*30a4e2aaSab long padding; 126*30a4e2aaSab GElf_Ehdr ehdr; 127*30a4e2aaSab 128*30a4e2aaSab 129*30a4e2aaSab /* ar(1) only pads objects, so bail if not looking at one */ 130*30a4e2aaSab if (gelf_getclass(elf) == ELFCLASSNONE) 131*30a4e2aaSab return; 132*30a4e2aaSab 133*30a4e2aaSab /* 134*30a4e2aaSab * elflib always puts the section header array at the end 135*30a4e2aaSab * of the object, and all of our compilers and other tools 136*30a4e2aaSab * use elflib or follow this convention. So, it is extremely 137*30a4e2aaSab * likely that the section header array is at the end of this 138*30a4e2aaSab * object: Find the address at the end of the array and compare 139*30a4e2aaSab * it to the archive ar_size. If they are within 8 bytes, then 140*30a4e2aaSab * we've found the end, and the difference is padding (no ELF 141*30a4e2aaSab * section can fit into 8 bytes). 142*30a4e2aaSab */ 143*30a4e2aaSab extent = gelf_getehdr(elf, &ehdr) 144*30a4e2aaSab ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0; 145*30a4e2aaSab padding = file->ar_size - extent; 146*30a4e2aaSab 147*30a4e2aaSab if ((padding < 0) || (padding >= 8)) { 148*30a4e2aaSab /* 149*30a4e2aaSab * The section header array is not at the end of the object. 150*30a4e2aaSab * Traverse the section headers and look for the one with 151*30a4e2aaSab * the highest used address. If this address is within 152*30a4e2aaSab * 8-bytes of ar_size, then this is the end of the object. 153*30a4e2aaSab */ 154*30a4e2aaSab Elf_Scn *scn = 0; 155*30a4e2aaSab 156*30a4e2aaSab do { 157*30a4e2aaSab scn = elf_nextscn(elf, scn); 158*30a4e2aaSab if (scn) { 159*30a4e2aaSab GElf_Shdr shdr; 160*30a4e2aaSab 161*30a4e2aaSab if (gelf_getshdr(scn, &shdr)) { 162*30a4e2aaSab long t = shdr.sh_offset + shdr.sh_size; 163*30a4e2aaSab if (t > extent) 164*30a4e2aaSab extent = t; 165*30a4e2aaSab } 166*30a4e2aaSab } 167*30a4e2aaSab } while (scn); 168*30a4e2aaSab } 169*30a4e2aaSab 170*30a4e2aaSab /* 171*30a4e2aaSab * Now, test the padding. We only act on padding in the range 172*30a4e2aaSab * 1-7 (ar(1) will never add more than this). A pad of 0 173*30a4e2aaSab * requires no action, and any other size outside of 1-7 means 174*30a4e2aaSab * that we don't understand the layout of this object, and as such, 175*30a4e2aaSab * cannot do anything. 176*30a4e2aaSab * 177*30a4e2aaSab * If the padding is in the range 1-7, and the raw data for the 178*30a4e2aaSab * object is available, then we perform one additional sanity 179*30a4e2aaSab * check before moving forward: ar(1) always pads with newline 180*30a4e2aaSab * characters. If anything else is seen, it is not padding so 181*30a4e2aaSab * leave it alone. 182*30a4e2aaSab */ 183*30a4e2aaSab if ((padding > 0) && (padding < 8)) { 184*30a4e2aaSab if (file->ar_contents) { 185*30a4e2aaSab long cnt = padding; 186*30a4e2aaSab char *p = file->ar_contents + extent; 187*30a4e2aaSab 188*30a4e2aaSab while (cnt--) { 189*30a4e2aaSab if (*p++ != '\n') { /* No padding */ 190*30a4e2aaSab padding = 0; 191*30a4e2aaSab break; 192*30a4e2aaSab } 193*30a4e2aaSab } 194*30a4e2aaSab } 195*30a4e2aaSab 196*30a4e2aaSab /* Remove the padding from the size */ 197*30a4e2aaSab file->ar_size -= padding; 198*30a4e2aaSab file->ar_padding = padding; 199*30a4e2aaSab } 200*30a4e2aaSab } 201*30a4e2aaSab 2027c478bd9Sstevel@tonic-gate ARFILE * 2037c478bd9Sstevel@tonic-gate getfile(Cmd_info *cmd_info) 2047c478bd9Sstevel@tonic-gate { 2057c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header; 2067c478bd9Sstevel@tonic-gate ARFILE *file; 2077c478bd9Sstevel@tonic-gate char *tmp_rawname, *file_rawname; 2087c478bd9Sstevel@tonic-gate Elf *elf; 2097c478bd9Sstevel@tonic-gate char *arnam = cmd_info->arnam; 2107c478bd9Sstevel@tonic-gate int fd = cmd_info->afd; 2117c478bd9Sstevel@tonic-gate Elf *arf = cmd_info->arf; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if (fd == -1) 2147c478bd9Sstevel@tonic-gate return (NULL); /* the archive doesn't exist */ 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 2177c478bd9Sstevel@tonic-gate return (NULL); /* the archive is empty or have hit the end */ 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) { 2207c478bd9Sstevel@tonic-gate error_message(ELF_MALARCHIVE_ERROR, 2217c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 2227c478bd9Sstevel@tonic-gate arnam, elf_getbase(elf)); 2237c478bd9Sstevel@tonic-gate exit(1); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* zip past special members like the symbol and string table members */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate while (strncmp(mem_header->ar_name, "/", 1) == 0 || 2297c478bd9Sstevel@tonic-gate strncmp(mem_header->ar_name, "//", 2) == 0) { 2307c478bd9Sstevel@tonic-gate (void) elf_next(elf); 2317c478bd9Sstevel@tonic-gate (void) elf_end(elf); 2327c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) 2337c478bd9Sstevel@tonic-gate return (NULL); 2347c478bd9Sstevel@tonic-gate /* the archive is empty or have hit the end */ 2357c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) { 2367c478bd9Sstevel@tonic-gate error_message(ELF_MALARCHIVE_ERROR, 2377c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 2387c478bd9Sstevel@tonic-gate arnam, elf_getbase(elf)); 2397c478bd9Sstevel@tonic-gate exit(0); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * NOTE: 2457c478bd9Sstevel@tonic-gate * The mem_header->ar_name[] is set to a NULL string 2467c478bd9Sstevel@tonic-gate * if the archive member header has some error. 2477c478bd9Sstevel@tonic-gate * (See elf_getarhdr() man page.) 2487c478bd9Sstevel@tonic-gate * It is set to NULL for example, the ar command reads 2497c478bd9Sstevel@tonic-gate * the archive files created by SunOS 4.1 system. 2507c478bd9Sstevel@tonic-gate * See c block comment in cmd.c, "Incompatible Archive Header". 2517c478bd9Sstevel@tonic-gate */ 2527c478bd9Sstevel@tonic-gate file = newfile(); 2537c478bd9Sstevel@tonic-gate (void) strncpy(file->ar_name, mem_header->ar_name, SNAME); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate if ((file->ar_longname 2567c478bd9Sstevel@tonic-gate = malloc(strlen(mem_header->ar_name) + 1)) 2577c478bd9Sstevel@tonic-gate == NULL) { 2587c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 2597c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 2607c478bd9Sstevel@tonic-gate exit(1); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate (void) strcpy(file->ar_longname, mem_header->ar_name); 2637c478bd9Sstevel@tonic-gate if ((file->ar_rawname 2647c478bd9Sstevel@tonic-gate = malloc(strlen(mem_header->ar_rawname) + 1)) 2657c478bd9Sstevel@tonic-gate == NULL) { 2667c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 2677c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 2687c478bd9Sstevel@tonic-gate exit(1); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate tmp_rawname = mem_header->ar_rawname; 2717c478bd9Sstevel@tonic-gate file_rawname = file->ar_rawname; 2727c478bd9Sstevel@tonic-gate while (!isspace(*tmp_rawname) && 2737c478bd9Sstevel@tonic-gate ((*file_rawname = *tmp_rawname) != '\0')) { 2747c478bd9Sstevel@tonic-gate file_rawname++; 2757c478bd9Sstevel@tonic-gate tmp_rawname++; 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate if (!(*tmp_rawname == '\0')) 2787c478bd9Sstevel@tonic-gate *file_rawname = '\0'; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate file->ar_date = mem_header->ar_date; 2817c478bd9Sstevel@tonic-gate file->ar_uid = mem_header->ar_uid; 2827c478bd9Sstevel@tonic-gate file->ar_gid = mem_header->ar_gid; 2837c478bd9Sstevel@tonic-gate file->ar_mode = (unsigned long) mem_header->ar_mode; 2847c478bd9Sstevel@tonic-gate file->ar_size = mem_header->ar_size; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* reverse logic */ 2877c478bd9Sstevel@tonic-gate if (!(opt_FLAG(cmd_info, t_FLAG) && !opt_FLAG(cmd_info, s_FLAG))) { 2887c478bd9Sstevel@tonic-gate size_t ptr; 2897c478bd9Sstevel@tonic-gate file->ar_flag = F_ELFRAW; 2907c478bd9Sstevel@tonic-gate if ((file->ar_contents = elf_rawfile(elf, &ptr)) 2917c478bd9Sstevel@tonic-gate == NULL) { 2927c478bd9Sstevel@tonic-gate if (ptr != 0) { 2937c478bd9Sstevel@tonic-gate error_message(ELF_RAWFILE_ERROR, 2947c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 2957c478bd9Sstevel@tonic-gate exit(1); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate file->ar_elf = elf; 2997c478bd9Sstevel@tonic-gate } 300*30a4e2aaSab 301*30a4e2aaSab recover_padding(elf, file); 302*30a4e2aaSab 3037c478bd9Sstevel@tonic-gate (void) elf_next(elf); 3047c478bd9Sstevel@tonic-gate return (file); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate ARFILE * 308d6555420Smike_s newfile(void) 3097c478bd9Sstevel@tonic-gate { 3107c478bd9Sstevel@tonic-gate static ARFILE *buffer = NULL; 3117c478bd9Sstevel@tonic-gate static int count = 0; 3127c478bd9Sstevel@tonic-gate ARFILE *fileptr; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if (count == 0) { 3157c478bd9Sstevel@tonic-gate if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE))) 3167c478bd9Sstevel@tonic-gate == NULL) { 3177c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 3187c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 3197c478bd9Sstevel@tonic-gate exit(1); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate count = CHUNK; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate count--; 3247c478bd9Sstevel@tonic-gate fileptr = buffer++; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (listhead) 3277c478bd9Sstevel@tonic-gate listend->ar_next = fileptr; 3287c478bd9Sstevel@tonic-gate else 3297c478bd9Sstevel@tonic-gate listhead = fileptr; 3307c478bd9Sstevel@tonic-gate listend = fileptr; 3317c478bd9Sstevel@tonic-gate return (fileptr); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate static char * 3357c478bd9Sstevel@tonic-gate trimslash(char *s) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate static char buf[SNAME]; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate (void) strncpy(buf, trim(s), SNAME - 2); 3407c478bd9Sstevel@tonic-gate buf[SNAME - 2] = '\0'; 3417c478bd9Sstevel@tonic-gate return (strcat(buf, "/")); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate char * 3457c478bd9Sstevel@tonic-gate trim(char *s) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate char *p1, *p2; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate for (p1 = s; *p1; p1++) 3507c478bd9Sstevel@tonic-gate ; 3517c478bd9Sstevel@tonic-gate while (p1 > s) { 3527c478bd9Sstevel@tonic-gate if (*--p1 != '/') 3537c478bd9Sstevel@tonic-gate break; 3547c478bd9Sstevel@tonic-gate *p1 = 0; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate p2 = s; 3577c478bd9Sstevel@tonic-gate for (p1 = s; *p1; p1++) 3587c478bd9Sstevel@tonic-gate if (*p1 == '/') 3597c478bd9Sstevel@tonic-gate p2 = p1 + 1; 3607c478bd9Sstevel@tonic-gate return (p2); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate static long 3657c478bd9Sstevel@tonic-gate mksymtab(ARFILEP **symlist, Cmd_info *cmd_info, int *found_obj) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate ARFILE *fptr; 3687c478bd9Sstevel@tonic-gate long mem_offset = 0; 3697c478bd9Sstevel@tonic-gate Elf *elf; 3707c478bd9Sstevel@tonic-gate Elf_Scn *scn; 3717c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 3727c478bd9Sstevel@tonic-gate int newfd; 3737c478bd9Sstevel@tonic-gate long nsyms = 0; 3747c478bd9Sstevel@tonic-gate int class = 0; 3757c478bd9Sstevel@tonic-gate Elf_Data *data; 3767c478bd9Sstevel@tonic-gate char *sbshstr; 3777c478bd9Sstevel@tonic-gate char *sbshstrtp; 3787c478bd9Sstevel@tonic-gate int sbstabsect = -1; 3797c478bd9Sstevel@tonic-gate int sbstabstrsect = -1; 3807c478bd9Sstevel@tonic-gate int num_errs = 0; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate newfd = 0; 3837c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 3847c478bd9Sstevel@tonic-gate /* determine if file is coming from the archive or not */ 3857c478bd9Sstevel@tonic-gate if ((fptr->ar_elf != 0) && (fptr->ar_pathname == NULL)) { 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * I can use the saved elf descriptor. 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate elf = fptr->ar_elf; 3907c478bd9Sstevel@tonic-gate } else if ((fptr->ar_elf == 0) && 3917c478bd9Sstevel@tonic-gate (fptr->ar_pathname != NULL)) { 3927c478bd9Sstevel@tonic-gate if ((newfd = 3937c478bd9Sstevel@tonic-gate open(fptr->ar_pathname, O_RDONLY)) == -1) { 3947c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 3957c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 3967c478bd9Sstevel@tonic-gate fptr->ar_pathname); 3977c478bd9Sstevel@tonic-gate num_errs++; 3987c478bd9Sstevel@tonic-gate continue; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate if ((elf = elf_begin(newfd, 4027c478bd9Sstevel@tonic-gate ELF_C_READ, 4037c478bd9Sstevel@tonic-gate (Elf *)0)) == 0) { 4047c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4057c478bd9Sstevel@tonic-gate error_message(ELF_BEGIN_02_ERROR, 4067c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 4077c478bd9Sstevel@tonic-gate fptr->ar_pathname); 4087c478bd9Sstevel@tonic-gate else 4097c478bd9Sstevel@tonic-gate error_message(ELF_BEGIN_03_ERROR, 4107c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 4117c478bd9Sstevel@tonic-gate (void) close(newfd); 4127c478bd9Sstevel@tonic-gate newfd = 0; 4137c478bd9Sstevel@tonic-gate num_errs++; 4147c478bd9Sstevel@tonic-gate continue; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate if (elf_kind(elf) == ELF_K_AR) { 4177c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4187c478bd9Sstevel@tonic-gate error_message(ARCHIVE_IN_ARCHIVE_ERROR, 4197c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4207c478bd9Sstevel@tonic-gate fptr->ar_pathname); 4217c478bd9Sstevel@tonic-gate else 4227c478bd9Sstevel@tonic-gate error_message(ARCHIVE_USAGE_ERROR, 4237c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 4247c478bd9Sstevel@tonic-gate if (newfd) { 4257c478bd9Sstevel@tonic-gate (void) close(newfd); 4267c478bd9Sstevel@tonic-gate newfd = 0; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4297c478bd9Sstevel@tonic-gate continue; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate } else { 4327c478bd9Sstevel@tonic-gate error_message(INTERNAL_01_ERROR, 4337c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 4347c478bd9Sstevel@tonic-gate exit(1); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) != 0) { 4377c478bd9Sstevel@tonic-gate if ((class = gelf_getclass(elf)) == ELFCLASS64) { 4387c478bd9Sstevel@tonic-gate fptr->ar_flag |= F_CLASS64; 4397c478bd9Sstevel@tonic-gate } else if (class == ELFCLASS32) 4407c478bd9Sstevel@tonic-gate fptr->ar_flag |= F_CLASS32; 4417c478bd9Sstevel@tonic-gate scn = elf_getscn(elf, ehdr.e_shstrndx); 4427c478bd9Sstevel@tonic-gate if (scn == NULL) { 4437c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4447c478bd9Sstevel@tonic-gate error_message(ELF_GETSCN_01_ERROR, 4457c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 4467c478bd9Sstevel@tonic-gate fptr->ar_pathname); 4477c478bd9Sstevel@tonic-gate else 4487c478bd9Sstevel@tonic-gate error_message(ELF_GETSCN_02_ERROR, 4497c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 4507c478bd9Sstevel@tonic-gate num_errs++; 4517c478bd9Sstevel@tonic-gate if (newfd) { 4527c478bd9Sstevel@tonic-gate (void) close(newfd); 4537c478bd9Sstevel@tonic-gate newfd = 0; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4567c478bd9Sstevel@tonic-gate continue; 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate data = 0; 4607c478bd9Sstevel@tonic-gate data = elf_getdata(scn, data); 4617c478bd9Sstevel@tonic-gate if (data == NULL) { 4627c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4637c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 4647c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 4657c478bd9Sstevel@tonic-gate fptr->ar_pathname); 4667c478bd9Sstevel@tonic-gate else 4677c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 4687c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 4697c478bd9Sstevel@tonic-gate num_errs++; 4707c478bd9Sstevel@tonic-gate if (newfd) { 4717c478bd9Sstevel@tonic-gate (void) close(newfd); 4727c478bd9Sstevel@tonic-gate newfd = 0; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4757c478bd9Sstevel@tonic-gate continue; 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate if (data->d_size == 0) { 4787c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 4797c478bd9Sstevel@tonic-gate error_message(W_ELF_NO_DATA_01_ERROR, 4807c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 4817c478bd9Sstevel@tonic-gate fptr->ar_pathname); 4827c478bd9Sstevel@tonic-gate else 4837c478bd9Sstevel@tonic-gate error_message(W_ELF_NO_DATA_02_ERROR, 4847c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 4857c478bd9Sstevel@tonic-gate if (newfd) { 4867c478bd9Sstevel@tonic-gate (void) close(newfd); 4877c478bd9Sstevel@tonic-gate newfd = 0; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate (void) elf_end(elf); 4907c478bd9Sstevel@tonic-gate num_errs++; 4917c478bd9Sstevel@tonic-gate continue; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate sbshstr = (char *)data->d_buf; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* loop through sections to find symbol table */ 4967c478bd9Sstevel@tonic-gate scn = 0; 4977c478bd9Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) { 4987c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 4997c478bd9Sstevel@tonic-gate if (gelf_getshdr(scn, &shdr) == NULL) { 5007c478bd9Sstevel@tonic-gate if (fptr->ar_pathname != NULL) 5017c478bd9Sstevel@tonic-gate error_message( 5027c478bd9Sstevel@tonic-gate ELF_GETDATA_01_ERROR, 5037c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 5047c478bd9Sstevel@tonic-gate fptr->ar_pathname); 5057c478bd9Sstevel@tonic-gate else 5067c478bd9Sstevel@tonic-gate error_message( 5077c478bd9Sstevel@tonic-gate ELF_GETDATA_02_ERROR, 5087c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 5097c478bd9Sstevel@tonic-gate if (newfd) { 5107c478bd9Sstevel@tonic-gate (void) close(newfd); 5117c478bd9Sstevel@tonic-gate newfd = 0; 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate num_errs++; 5147c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5157c478bd9Sstevel@tonic-gate continue; 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate *found_obj = 1; 5187c478bd9Sstevel@tonic-gate if (shdr.sh_type == SHT_SYMTAB) 5197c478bd9Sstevel@tonic-gate if (search_sym_tab(fptr, elf, 5207c478bd9Sstevel@tonic-gate scn, 5217c478bd9Sstevel@tonic-gate &nsyms, 5227c478bd9Sstevel@tonic-gate symlist, 5237c478bd9Sstevel@tonic-gate &num_errs) == -1) { 5247c478bd9Sstevel@tonic-gate if (newfd) { 5257c478bd9Sstevel@tonic-gate (void) close(newfd); 5267c478bd9Sstevel@tonic-gate newfd = 0; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate continue; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate #ifdef BROWSER 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * XX64: sbrowser_search_stab() currently gets 5337c478bd9Sstevel@tonic-gate * confused by sb-tabs in v9. at this 5347c478bd9Sstevel@tonic-gate * point, no one knows what v9 sb-tabs are 5357c478bd9Sstevel@tonic-gate * supposed to look like. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate /* if (shdr.sh_name != 0) { */ 5387c478bd9Sstevel@tonic-gate if ((class == ELFCLASS32) && 5397c478bd9Sstevel@tonic-gate (shdr.sh_name != 0)) { 5407c478bd9Sstevel@tonic-gate sbshstrtp = (char *) 5417c478bd9Sstevel@tonic-gate ((long)sbshstr + shdr.sh_name); 5427c478bd9Sstevel@tonic-gate if (strcmp(sbshstrtp, ".stab") == 0) { 5437c478bd9Sstevel@tonic-gate sbstabsect = elf_ndxscn(scn); 5447c478bd9Sstevel@tonic-gate } else if (strcmp(sbshstrtp, 5457c478bd9Sstevel@tonic-gate ".stabstr") == 0) { 5467c478bd9Sstevel@tonic-gate sbstabstrsect = elf_ndxscn(scn); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate #endif 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate #ifdef BROWSER 5527c478bd9Sstevel@tonic-gate if (sbstabsect != -1 || sbstabstrsect != -1) { 5537c478bd9Sstevel@tonic-gate sbrowser_search_stab( 5547c478bd9Sstevel@tonic-gate elf, 5557c478bd9Sstevel@tonic-gate sbstabsect, 5567c478bd9Sstevel@tonic-gate sbstabstrsect, 5577c478bd9Sstevel@tonic-gate cmd_info->arnam); 5587c478bd9Sstevel@tonic-gate sbstabsect = -1; 5597c478bd9Sstevel@tonic-gate sbstabstrsect = -1; 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate #endif 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate mem_offset += sizeof (struct ar_hdr) + fptr->ar_size; 5647c478bd9Sstevel@tonic-gate if (fptr->ar_size & 01) 5657c478bd9Sstevel@tonic-gate mem_offset++; 5667c478bd9Sstevel@tonic-gate (void) elf_end(elf); 5677c478bd9Sstevel@tonic-gate if (newfd) { 5687c478bd9Sstevel@tonic-gate (void) close(newfd); 5697c478bd9Sstevel@tonic-gate newfd = 0; 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate } /* for */ 5727c478bd9Sstevel@tonic-gate if (num_errs) 5737c478bd9Sstevel@tonic-gate exit(1); 5747c478bd9Sstevel@tonic-gate return (nsyms); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * This routine writes an archive symbol table for the 5797c478bd9Sstevel@tonic-gate * output archive file. The symbol table is built if 5807c478bd9Sstevel@tonic-gate * there was at least one object file specified. 5817c478bd9Sstevel@tonic-gate * In rare case, there could be no symbol. 5827c478bd9Sstevel@tonic-gate * In this case, str_top and str_base can not be used to 5837c478bd9Sstevel@tonic-gate * make the string table. So the routine adjust the size 5847c478bd9Sstevel@tonic-gate * and make a dummy string table. String table is needed 5857c478bd9Sstevel@tonic-gate * by elf_getarsym(). 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate static int 5887c478bd9Sstevel@tonic-gate writesymtab(char *dst, long nsyms, ARFILEP *symlist) 5897c478bd9Sstevel@tonic-gate { 5907c478bd9Sstevel@tonic-gate char buf1[sizeof (struct ar_hdr) + 1]; 5917c478bd9Sstevel@tonic-gate char *buf2, *bptr; 5927c478bd9Sstevel@tonic-gate int i, j; 5937c478bd9Sstevel@tonic-gate ARFILEP *ptr; 5947c478bd9Sstevel@tonic-gate long sym_tab_size = 0; 5957c478bd9Sstevel@tonic-gate int sum = 0; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * patch up archive pointers and write the symbol entries 5997c478bd9Sstevel@tonic-gate */ 6007c478bd9Sstevel@tonic-gate while ((str_top - str_base) & 03) /* round up string table */ 6017c478bd9Sstevel@tonic-gate *str_top++ = '\0'; 6027c478bd9Sstevel@tonic-gate sym_tab_size = (nsyms +1) * 4 + sizeof (char) * (str_top - str_base); 6037c478bd9Sstevel@tonic-gate if (nsyms == 0) 6047c478bd9Sstevel@tonic-gate sym_tab_size += 4; 6057c478bd9Sstevel@tonic-gate sym_tab_size += pad_symtab; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate (void) sprintf(buf1, FORMAT, SYMDIRNAME, time(0), (unsigned)0, 6087c478bd9Sstevel@tonic-gate (unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG); 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (strlen(buf1) != sizeof (struct ar_hdr)) { 6117c478bd9Sstevel@tonic-gate error_message(INTERNAL_02_ERROR); 6127c478bd9Sstevel@tonic-gate exit(1); 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if ((buf2 = malloc(4 * (nsyms + 1))) == NULL) { 6167c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR); 6177c478bd9Sstevel@tonic-gate error_message(DIAG_01_ERROR, errno); 6187c478bd9Sstevel@tonic-gate exit(1); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate sputl(nsyms, buf2); 6217c478bd9Sstevel@tonic-gate bptr = buf2 + 4; 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) { 6247c478bd9Sstevel@tonic-gate if (!j) { 6257c478bd9Sstevel@tonic-gate j = SYMCHUNK; 6267c478bd9Sstevel@tonic-gate ptr = (ARFILEP *)*ptr; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate sputl((*ptr)->ar_offset, bptr); 6297c478bd9Sstevel@tonic-gate bptr += 4; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate (void) memcpy(dst, buf1, sizeof (struct ar_hdr)); 6327c478bd9Sstevel@tonic-gate dst += sizeof (struct ar_hdr); 6337c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate (void) memcpy(dst, buf2, (nsyms + 1) * 4); 6367c478bd9Sstevel@tonic-gate dst += (nsyms + 1)*4; 6377c478bd9Sstevel@tonic-gate sum += (nsyms + 1)*4; 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate if (nsyms != 0) { 6407c478bd9Sstevel@tonic-gate (void) memcpy(dst, str_base, (str_top - str_base)); 6417c478bd9Sstevel@tonic-gate dst += str_top - str_base; 6427c478bd9Sstevel@tonic-gate sum += str_top - str_base; 6437c478bd9Sstevel@tonic-gate } else { 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * Writing a dummy string table. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate int i; 6487c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) 6497c478bd9Sstevel@tonic-gate *dst++ = 0; 6507c478bd9Sstevel@tonic-gate sum += 4; 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * The first member file is ELFCLASS64. We need to make the member 6557c478bd9Sstevel@tonic-gate * to be placed at the 8 byte boundary. 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate if (pad_symtab) { 6587c478bd9Sstevel@tonic-gate int i; 6597c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) 6607c478bd9Sstevel@tonic-gate *dst++ = 0; 6617c478bd9Sstevel@tonic-gate sum += 4; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate free(buf2); 6657c478bd9Sstevel@tonic-gate return (sum); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate static void 6697c478bd9Sstevel@tonic-gate savename(char *symbol) 6707c478bd9Sstevel@tonic-gate { 6717c478bd9Sstevel@tonic-gate static int str_length = BUFSIZ * 5; 6727c478bd9Sstevel@tonic-gate char *p, *s; 6737c478bd9Sstevel@tonic-gate unsigned int i; 6747c478bd9Sstevel@tonic-gate int diff; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate diff = 0; 6777c478bd9Sstevel@tonic-gate if (str_base == (char *)0) { 6787c478bd9Sstevel@tonic-gate /* no space allocated yet */ 6797c478bd9Sstevel@tonic-gate if ((str_base = malloc((unsigned)str_length)) 6807c478bd9Sstevel@tonic-gate == NULL) { 6817c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 6827c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 6837c478bd9Sstevel@tonic-gate exit(1); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate str_top = str_base; 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate p = str_top; 6897c478bd9Sstevel@tonic-gate str_top += strlen(symbol) + 1; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (str_top > str_base + str_length) { 6927c478bd9Sstevel@tonic-gate char *old_base = str_base; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate do 6957c478bd9Sstevel@tonic-gate str_length += BUFSIZ * 2; 6967c478bd9Sstevel@tonic-gate while (str_top > str_base + str_length); 6977c478bd9Sstevel@tonic-gate if ((str_base = (char *)realloc(str_base, str_length)) == 6987c478bd9Sstevel@tonic-gate NULL) { 6997c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 7007c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 7017c478bd9Sstevel@tonic-gate exit(1); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate /* 7047c478bd9Sstevel@tonic-gate * Re-adjust other pointers 7057c478bd9Sstevel@tonic-gate */ 7067c478bd9Sstevel@tonic-gate diff = str_base - old_base; 7077c478bd9Sstevel@tonic-gate p += diff; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate for (i = 0, s = symbol; 7107c478bd9Sstevel@tonic-gate i < strlen(symbol) && *s != '\0'; i++) { 7117c478bd9Sstevel@tonic-gate *p++ = *s++; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate *p++ = '\0'; 7147c478bd9Sstevel@tonic-gate str_top = p; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate static void 7187c478bd9Sstevel@tonic-gate savelongname(ARFILE *fptr, char *ptr_index) 7197c478bd9Sstevel@tonic-gate { 7207c478bd9Sstevel@tonic-gate static int str_length = BUFSIZ * 5; 7217c478bd9Sstevel@tonic-gate char *p, *s; 7227c478bd9Sstevel@tonic-gate unsigned int i; 7237c478bd9Sstevel@tonic-gate int diff; 7247c478bd9Sstevel@tonic-gate static int bytes_used; 7257c478bd9Sstevel@tonic-gate int index; 7267c478bd9Sstevel@tonic-gate char ptr_index1[SNAME-1]; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate diff = 0; 7297c478bd9Sstevel@tonic-gate if (str_base1 == (char *)0) { 7307c478bd9Sstevel@tonic-gate /* no space allocated yet */ 7317c478bd9Sstevel@tonic-gate if ((str_base1 = malloc((unsigned)str_length)) 7327c478bd9Sstevel@tonic-gate == NULL) { 7337c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 7347c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 7357c478bd9Sstevel@tonic-gate exit(1); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate str_top1 = str_base1; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate p = str_top1; 7417c478bd9Sstevel@tonic-gate str_top1 += strlen(fptr->ar_longname) + 2; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate index = bytes_used; 7447c478bd9Sstevel@tonic-gate (void) sprintf(ptr_index1, "%d", index); /* holds digits */ 7457c478bd9Sstevel@tonic-gate (void) sprintf(ptr_index, FNFORMAT, SYMDIRNAME); 7467c478bd9Sstevel@tonic-gate ptr_index[1] = '\0'; 7477c478bd9Sstevel@tonic-gate (void) strcat(ptr_index, ptr_index1); 7487c478bd9Sstevel@tonic-gate (void) strcpy(fptr->ar_name, ptr_index); 7497c478bd9Sstevel@tonic-gate bytes_used += strlen(fptr->ar_longname) + 2; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate if (str_top1 > str_base1 + str_length) { 7527c478bd9Sstevel@tonic-gate char *old_base = str_base1; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate do 7557c478bd9Sstevel@tonic-gate str_length += BUFSIZ * 2; 7567c478bd9Sstevel@tonic-gate while (str_top1 > str_base1 + str_length); 7577c478bd9Sstevel@tonic-gate if ((str_base1 = (char *)realloc(str_base1, str_length)) 7587c478bd9Sstevel@tonic-gate == NULL) { 7597c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 7607c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 7617c478bd9Sstevel@tonic-gate exit(1); 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * Re-adjust other pointers 7657c478bd9Sstevel@tonic-gate */ 7667c478bd9Sstevel@tonic-gate diff = str_base1 - old_base; 7677c478bd9Sstevel@tonic-gate p += diff; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate for (i = 0, s = fptr->ar_longname; 7707c478bd9Sstevel@tonic-gate i < strlen(fptr->ar_longname) && *s != '\0'; 7717c478bd9Sstevel@tonic-gate i++) { 7727c478bd9Sstevel@tonic-gate *p++ = *s++; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate *p++ = '/'; 7757c478bd9Sstevel@tonic-gate *p++ = '\n'; 7767c478bd9Sstevel@tonic-gate str_top1 = p; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate char * 7807c478bd9Sstevel@tonic-gate writefile(Cmd_info *cmd_info) 7817c478bd9Sstevel@tonic-gate { 7827c478bd9Sstevel@tonic-gate ARFILE * fptr; 7837c478bd9Sstevel@tonic-gate ARFILEP *symlist = 0; 7847c478bd9Sstevel@tonic-gate int i; 7857c478bd9Sstevel@tonic-gate int longnames = 0; 7867c478bd9Sstevel@tonic-gate long long_tab_size = 0; 7877c478bd9Sstevel@tonic-gate long nsyms; 7887c478bd9Sstevel@tonic-gate int new_archive = 0; 7897c478bd9Sstevel@tonic-gate char *name = cmd_info->arnam; 7907c478bd9Sstevel@tonic-gate int arsize; 7917c478bd9Sstevel@tonic-gate char *dst; 7927c478bd9Sstevel@tonic-gate char *tmp_dst; 7937c478bd9Sstevel@tonic-gate int nfd; 7947c478bd9Sstevel@tonic-gate int found_obj = 0; 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate long_tab_size = mklong_tab(&longnames); 7977c478bd9Sstevel@tonic-gate nsyms = mksymtab(&symlist, cmd_info, &found_obj); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate for (i = 0; signum[i]; i++) 8007c478bd9Sstevel@tonic-gate /* started writing, cannot interrupt */ 8017c478bd9Sstevel@tonic-gate (void) signal(signum[i], SIG_IGN); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* Is this a new archive? */ 8057c478bd9Sstevel@tonic-gate if ((access(cmd_info->arnam, 0) < 0) && (errno == ENOENT)) { 8067c478bd9Sstevel@tonic-gate new_archive = 1; 8077c478bd9Sstevel@tonic-gate if (!opt_FLAG(cmd_info, c_FLAG)) { 8087c478bd9Sstevel@tonic-gate error_message(BER_MES_CREATE_ERROR, 8097c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, cmd_info->arnam); 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate else 8137c478bd9Sstevel@tonic-gate new_archive = 0; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate /* 8167c478bd9Sstevel@tonic-gate * Calculate the size of the new archive 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate arsize = sizeofnewarchive(nsyms, longnames); 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate /* 8217c478bd9Sstevel@tonic-gate * Dummy symtab ? 8227c478bd9Sstevel@tonic-gate */ 8237c478bd9Sstevel@tonic-gate if (nsyms == 0 && found_obj != 0) 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * 4 + 4 = First 4 bytes to keep the number of symbols. 8267c478bd9Sstevel@tonic-gate * The second 4 bytes for string table. 8277c478bd9Sstevel@tonic-gate */ 8287c478bd9Sstevel@tonic-gate arsize += sizeof (struct ar_hdr) + 4 + 4; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate if (arsize > AR_MAX_BYTES_IN_MEM) { 8317c478bd9Sstevel@tonic-gate tmp_dst = dst = NULL; 8327c478bd9Sstevel@tonic-gate } else { 8337c478bd9Sstevel@tonic-gate tmp_dst = dst = malloc(arsize); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate if (dst == NULL) { 8367c478bd9Sstevel@tonic-gate return writelargefile(cmd_info, long_tab_size, 8377c478bd9Sstevel@tonic-gate longnames, symlist, nsyms, found_obj, new_archive); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, ARMAG, SARMAG); 8417c478bd9Sstevel@tonic-gate tmp_dst += SARMAG; 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate if (nsyms || found_obj != 0) { 8447c478bd9Sstevel@tonic-gate int diff; 8457c478bd9Sstevel@tonic-gate diff = writesymtab(tmp_dst, nsyms, symlist); 8467c478bd9Sstevel@tonic-gate tmp_dst += diff; 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate if (longnames) { 8507c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 8517c478bd9Sstevel@tonic-gate (unsigned)0, (unsigned)0, (unsigned)0, 8527c478bd9Sstevel@tonic-gate (long)long_tab_size, ARFMAG); 8537c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 8547c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 8557c478bd9Sstevel@tonic-gate tmp_dst += str_top1 - str_base1; 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate /* 8607c478bd9Sstevel@tonic-gate * NOTE: 8617c478bd9Sstevel@tonic-gate * The mem_header->ar_name[] is set to a NULL string 8627c478bd9Sstevel@tonic-gate * if the archive member header has some error. 8637c478bd9Sstevel@tonic-gate * (See elf_getarhdr() man page.) 8647c478bd9Sstevel@tonic-gate * It is set to NULL for example, the ar command reads 8657c478bd9Sstevel@tonic-gate * the archive files created by SunOS 4.1 system. 8667c478bd9Sstevel@tonic-gate * See c block comment in cmd.c, "Incompatible Archive Header". 8677c478bd9Sstevel@tonic-gate */ 8687c478bd9Sstevel@tonic-gate if (fptr->ar_name[0] == 0) { 8697c478bd9Sstevel@tonic-gate fptr->ar_longname = fptr->ar_rawname; 8707c478bd9Sstevel@tonic-gate (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 8737c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FNFORMAT, 8747c478bd9Sstevel@tonic-gate trimslash(fptr->ar_longname)); 8757c478bd9Sstevel@tonic-gate else 8767c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FNFORMAT, fptr->ar_name); 8777c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst+16, TLFORMAT, fptr->ar_date, 8787c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 8797c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 8807c478bd9Sstevel@tonic-gate ARFMAG); 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate if (!(fptr->ar_flag & F_MALLOCED) && 8857c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_MMAPED) && 8867c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_ELFRAW)) { 8877c478bd9Sstevel@tonic-gate /* file was not read in fptr->ar_contents during 'cmd' */ 8887c478bd9Sstevel@tonic-gate /* do it now */ 8897c478bd9Sstevel@tonic-gate FILE *f; 8907c478bd9Sstevel@tonic-gate f = fopen(fptr->ar_pathname, "r"); 8917c478bd9Sstevel@tonic-gate if (f == NULL) { 8927c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 8937c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 8947c478bd9Sstevel@tonic-gate fptr->ar_longname); 8957c478bd9Sstevel@tonic-gate exit(1); 8967c478bd9Sstevel@tonic-gate } else { 8977c478bd9Sstevel@tonic-gate if (fread(tmp_dst, 8987c478bd9Sstevel@tonic-gate sizeof (char), 8997c478bd9Sstevel@tonic-gate fptr->ar_size, f) != fptr->ar_size) { 9007c478bd9Sstevel@tonic-gate error_message(SYS_READ_ERROR, 9017c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 9027c478bd9Sstevel@tonic-gate fptr->ar_longname); 9037c478bd9Sstevel@tonic-gate exit(1); 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate } 906d6555420Smike_s (void) fclose(f); 9077c478bd9Sstevel@tonic-gate } else { 9087c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, fptr->ar_contents, 9097c478bd9Sstevel@tonic-gate fptr->ar_size); 9107c478bd9Sstevel@tonic-gate if (fptr->ar_flag & F_MALLOCED) { 9117c478bd9Sstevel@tonic-gate (void) free(fptr->ar_contents); 9127c478bd9Sstevel@tonic-gate fptr->ar_flag &= ~(F_MALLOCED); 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate tmp_dst += fptr->ar_size; 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate if (fptr->ar_size & 0x1) { 9187c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, "\n", 1); 9197c478bd9Sstevel@tonic-gate tmp_dst++; 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate if (fptr->ar_padding) { 9237c478bd9Sstevel@tonic-gate int i = fptr->ar_padding; 9247c478bd9Sstevel@tonic-gate while (i) { 9257c478bd9Sstevel@tonic-gate *tmp_dst++ = '\n'; 9267c478bd9Sstevel@tonic-gate --i; 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate * All preparation for writing is done. 9337c478bd9Sstevel@tonic-gate */ 9347c478bd9Sstevel@tonic-gate (void) elf_end(cmd_info->arf); 9357c478bd9Sstevel@tonic-gate (void) close(cmd_info->afd); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* 9387c478bd9Sstevel@tonic-gate * Write out to the file 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate if (new_archive) { 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * create a new file 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate nfd = creat(name, 0666); 9457c478bd9Sstevel@tonic-gate if (nfd == -1) { 9467c478bd9Sstevel@tonic-gate error_message(SYS_CREATE_01_ERROR, 9477c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 9487c478bd9Sstevel@tonic-gate exit(1); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate } else { 9517c478bd9Sstevel@tonic-gate /* 9527c478bd9Sstevel@tonic-gate * Open the new file 9537c478bd9Sstevel@tonic-gate */ 9547c478bd9Sstevel@tonic-gate nfd = open(name, O_RDWR|O_TRUNC); 9557c478bd9Sstevel@tonic-gate if (nfd == -1) { 9567c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_02_ERROR, 9577c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 9587c478bd9Sstevel@tonic-gate exit(1); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate #ifndef XPG4 9627c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 9637c478bd9Sstevel@tonic-gate error_message(BER_MES_WRITE_ERROR, 9647c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 9657c478bd9Sstevel@tonic-gate cmd_info->arnam); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate #endif 9687c478bd9Sstevel@tonic-gate if (write(nfd, dst, arsize) != arsize) { 9697c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_04_ERROR, 9707c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 9717c478bd9Sstevel@tonic-gate if (!new_archive) 9727c478bd9Sstevel@tonic-gate error_message(WARN_USER_ERROR, 9737c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 9747c478bd9Sstevel@tonic-gate exit(2); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate return (dst); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate static long 9807c478bd9Sstevel@tonic-gate mklong_tab(int *longnames) 9817c478bd9Sstevel@tonic-gate { 9827c478bd9Sstevel@tonic-gate ARFILE *fptr; 9837c478bd9Sstevel@tonic-gate char ptr_index[SNAME+1]; 9847c478bd9Sstevel@tonic-gate long ret = 0; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 9877c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) { 9887c478bd9Sstevel@tonic-gate (*longnames)++; 9897c478bd9Sstevel@tonic-gate savelongname(fptr, ptr_index); 9907c478bd9Sstevel@tonic-gate (void) strcpy(fptr->ar_name, ptr_index); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate if (*longnames) { 9947c478bd9Sstevel@tonic-gate /* round up table that keeps the long filenames */ 9957c478bd9Sstevel@tonic-gate while ((str_top1 - str_base1) & 03) 9967c478bd9Sstevel@tonic-gate *str_top1++ = '\n'; 9977c478bd9Sstevel@tonic-gate ret = sizeof (char) * (str_top1 - str_base1); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate return (ret); 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate /* Put bytes in archive header in machine independent order. */ 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate static void 10057c478bd9Sstevel@tonic-gate sputl(long n, char *cp) 10067c478bd9Sstevel@tonic-gate { 10077c478bd9Sstevel@tonic-gate *cp++ = n >> 24; 10087c478bd9Sstevel@tonic-gate *cp++ = n >> 16; 10097c478bd9Sstevel@tonic-gate *cp++ = n >> 8; 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate *cp++ = n & 255; 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate #ifdef BROWSER 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate static void 10177c478bd9Sstevel@tonic-gate sbrowser_search_stab(Elf *elf, int stabid, int stabstrid, char *arnam) 10187c478bd9Sstevel@tonic-gate { 10197c478bd9Sstevel@tonic-gate Elf_Scn *stab_scn; 10207c478bd9Sstevel@tonic-gate Elf_Scn *stabstr_scn; 10217c478bd9Sstevel@tonic-gate Elf_Data *data; 10227c478bd9Sstevel@tonic-gate struct nlist *np; 10237c478bd9Sstevel@tonic-gate struct nlist *stabtab; 10247c478bd9Sstevel@tonic-gate char *stabstrtab; 10257c478bd9Sstevel@tonic-gate char *stabstroff; 10267c478bd9Sstevel@tonic-gate char *symname; 10277c478bd9Sstevel@tonic-gate int prevstabstrsz; 10287c478bd9Sstevel@tonic-gate GElf_Xword nstab; 10297c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* use the .stab and stabstr section index to find the data buffer */ 10327c478bd9Sstevel@tonic-gate if (stabid == -1) { 10337c478bd9Sstevel@tonic-gate error_message(SBROW_01_ERROR, 10347c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 10357c478bd9Sstevel@tonic-gate return; 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate stab_scn = elf_getscn(elf, (size_t)stabid); 10387c478bd9Sstevel@tonic-gate if (stab_scn == NULL) { 10397c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 10407c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 10417c478bd9Sstevel@tonic-gate return; 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate (void) gelf_getshdr(stab_scn, &shdr); 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * Zero length .stab sections have been produced by some compilers so 10477c478bd9Sstevel@tonic-gate * ignore the section if this is the case. 10487c478bd9Sstevel@tonic-gate */ 10497c478bd9Sstevel@tonic-gate if ((nstab = shdr.sh_size / shdr.sh_entsize) == 0) 10507c478bd9Sstevel@tonic-gate return; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if (stabstrid == -1) { 10537c478bd9Sstevel@tonic-gate error_message(SBROW_02_ERROR, 10547c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 10557c478bd9Sstevel@tonic-gate return; 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate stabstr_scn = elf_getscn(elf, (size_t)stabstrid); 10587c478bd9Sstevel@tonic-gate if (stabstr_scn == NULL) { 10597c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 10607c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 10617c478bd9Sstevel@tonic-gate return; 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate if (gelf_getshdr(stabstr_scn, &shdr) == NULL) { 10647c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 10657c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 10667c478bd9Sstevel@tonic-gate return; 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate if (shdr.sh_size == 0) { 10697c478bd9Sstevel@tonic-gate error_message(SBROW_03_ERROR, 10707c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 10717c478bd9Sstevel@tonic-gate return; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate data = 0; 10757c478bd9Sstevel@tonic-gate data = elf_getdata(stabstr_scn, data); 10767c478bd9Sstevel@tonic-gate if (data == NULL) { 10777c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 10787c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 10797c478bd9Sstevel@tonic-gate return; 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate if (data->d_size == 0) { 10827c478bd9Sstevel@tonic-gate error_message(SBROW_02_ERROR, 10837c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 10847c478bd9Sstevel@tonic-gate return; 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate stabstrtab = (char *)data->d_buf; 10877c478bd9Sstevel@tonic-gate data = 0; 10887c478bd9Sstevel@tonic-gate data = elf_getdata(stab_scn, data); 10897c478bd9Sstevel@tonic-gate if (data == NULL) { 10907c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 10917c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 10927c478bd9Sstevel@tonic-gate return; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate if (data->d_size == 0) { 10957c478bd9Sstevel@tonic-gate error_message(SBROW_03_ERROR, 10967c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 10977c478bd9Sstevel@tonic-gate return; 10987c478bd9Sstevel@tonic-gate } 10997c478bd9Sstevel@tonic-gate stabtab = (struct nlist *)data->d_buf; 11007c478bd9Sstevel@tonic-gate stabstroff = stabstrtab; 11017c478bd9Sstevel@tonic-gate prevstabstrsz = 0; 11027c478bd9Sstevel@tonic-gate for (np = stabtab; np < &stabtab[nstab]; np++) { 11037c478bd9Sstevel@tonic-gate if (np->n_type == 0) { 11047c478bd9Sstevel@tonic-gate stabstroff += prevstabstrsz; 11057c478bd9Sstevel@tonic-gate prevstabstrsz = np->n_value; 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate symname = stabstroff + np->n_un.n_strx; 11087c478bd9Sstevel@tonic-gate if (np->n_type == 0x48) { 11097c478bd9Sstevel@tonic-gate sbfocus_symbol(&sb_data, arnam, "-a", symname); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate #endif 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate static int 11187c478bd9Sstevel@tonic-gate search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, 11197c478bd9Sstevel@tonic-gate long *nsyms, ARFILEP **symlist, int *num_errs) 11207c478bd9Sstevel@tonic-gate { 11217c478bd9Sstevel@tonic-gate Elf_Data *str_data, *sym_data; /* string table, symbol table */ 11227c478bd9Sstevel@tonic-gate Elf_Scn *str_scn; 11237c478bd9Sstevel@tonic-gate GElf_Sxword no_of_symbols; 11247c478bd9Sstevel@tonic-gate GElf_Shdr shdr; 11257c478bd9Sstevel@tonic-gate int counter; 11267c478bd9Sstevel@tonic-gate int str_shtype; 11277c478bd9Sstevel@tonic-gate char *symname; 11287c478bd9Sstevel@tonic-gate static ARFILEP *sym_ptr = 0; 11297c478bd9Sstevel@tonic-gate static ARFILEP *nextsym = NULL; 11307c478bd9Sstevel@tonic-gate static int syms_left = 0; 11317c478bd9Sstevel@tonic-gate char *fname = fptr->ar_pathname; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate (void) gelf_getshdr(scn, &shdr); 11347c478bd9Sstevel@tonic-gate str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */ 11357c478bd9Sstevel@tonic-gate if (str_scn == NULL) { 11367c478bd9Sstevel@tonic-gate if (fname != NULL) 11377c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 11387c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 11397c478bd9Sstevel@tonic-gate fname); 11407c478bd9Sstevel@tonic-gate else 11417c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 11427c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 11437c478bd9Sstevel@tonic-gate (*num_errs)++; 11447c478bd9Sstevel@tonic-gate return (-1); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate no_of_symbols = shdr.sh_size / shdr.sh_entsize; 11487c478bd9Sstevel@tonic-gate if (no_of_symbols == -1) { 11497c478bd9Sstevel@tonic-gate error_message(SYMTAB_01_ERROR, 11507c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 11517c478bd9Sstevel@tonic-gate return (-1); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate (void) gelf_getshdr(str_scn, &shdr); 11557c478bd9Sstevel@tonic-gate str_shtype = shdr.sh_type; 11567c478bd9Sstevel@tonic-gate if (str_shtype == -1) { 11577c478bd9Sstevel@tonic-gate if (fname != NULL) 11587c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_01_ERROR, 11597c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), fname); 11607c478bd9Sstevel@tonic-gate else 11617c478bd9Sstevel@tonic-gate error_message(ELF_GETDATA_02_ERROR, 11627c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1)); 11637c478bd9Sstevel@tonic-gate (*num_errs)++; 11647c478bd9Sstevel@tonic-gate return (-1); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate /* This test must happen before testing the string table. */ 11687c478bd9Sstevel@tonic-gate if (no_of_symbols == 1) 11697c478bd9Sstevel@tonic-gate return (0); /* no symbols; 0th symbol is the non-symbol */ 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate if (str_shtype != SHT_STRTAB) { 11727c478bd9Sstevel@tonic-gate if (fname != NULL) 11737c478bd9Sstevel@tonic-gate error_message(SYMTAB_02_ERROR, 11747c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 11757c478bd9Sstevel@tonic-gate fname); 11767c478bd9Sstevel@tonic-gate else 11777c478bd9Sstevel@tonic-gate error_message(SYMTAB_03_ERROR, 11787c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 11797c478bd9Sstevel@tonic-gate return (0); 11807c478bd9Sstevel@tonic-gate } 11817c478bd9Sstevel@tonic-gate str_data = 0; 11827c478bd9Sstevel@tonic-gate if ((str_data = elf_getdata(str_scn, str_data)) == 0) { 11837c478bd9Sstevel@tonic-gate if (fname != NULL) 11847c478bd9Sstevel@tonic-gate error_message(SYMTAB_04_ERROR, 11857c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 11867c478bd9Sstevel@tonic-gate fname); 11877c478bd9Sstevel@tonic-gate else 11887c478bd9Sstevel@tonic-gate error_message(SYMTAB_05_ERROR, 11897c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 11907c478bd9Sstevel@tonic-gate return (0); 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate if (str_data->d_size == 0) { 11937c478bd9Sstevel@tonic-gate if (fname != NULL) 11947c478bd9Sstevel@tonic-gate error_message(SYMTAB_06_ERROR, 11957c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 11967c478bd9Sstevel@tonic-gate fname); 11977c478bd9Sstevel@tonic-gate else 11987c478bd9Sstevel@tonic-gate error_message(SYMTAB_07_ERROR, 11997c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 12007c478bd9Sstevel@tonic-gate return (0); 12017c478bd9Sstevel@tonic-gate } 12027c478bd9Sstevel@tonic-gate sym_data = 0; 12037c478bd9Sstevel@tonic-gate if ((sym_data = elf_getdata(scn, sym_data)) == NULL) { 12047c478bd9Sstevel@tonic-gate if (fname != NULL) 12057c478bd9Sstevel@tonic-gate error_message(ELF_01_ERROR, 12067c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 12077c478bd9Sstevel@tonic-gate fname, elf_errmsg(-1)); 12087c478bd9Sstevel@tonic-gate else 12097c478bd9Sstevel@tonic-gate error_message(ELF_02_ERROR, 12107c478bd9Sstevel@tonic-gate LIBELF_ERROR, elf_errmsg(-1), 12117c478bd9Sstevel@tonic-gate elf_errmsg(-1)); 12127c478bd9Sstevel@tonic-gate return (0); 12137c478bd9Sstevel@tonic-gate } 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate /* start at 1, first symbol entry is ignored */ 12167c478bd9Sstevel@tonic-gate for (counter = 1; counter < no_of_symbols; counter++) { 12177c478bd9Sstevel@tonic-gate GElf_Sym sym; 12187c478bd9Sstevel@tonic-gate (void) gelf_getsym(sym_data, counter, &sym); 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate symname = (char *)(str_data->d_buf) + sym.st_name; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if (((GELF_ST_BIND(sym.st_info) == STB_GLOBAL) || 12237c478bd9Sstevel@tonic-gate (GELF_ST_BIND(sym.st_info) == STB_WEAK)) && 12247c478bd9Sstevel@tonic-gate (sym.st_shndx != SHN_UNDEF)) { 12257c478bd9Sstevel@tonic-gate if (!syms_left) { 12267c478bd9Sstevel@tonic-gate sym_ptr = malloc((SYMCHUNK+1) 12277c478bd9Sstevel@tonic-gate * sizeof (ARFILEP)); 12287c478bd9Sstevel@tonic-gate if (sym_ptr == NULL) { 12297c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 12307c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 12317c478bd9Sstevel@tonic-gate exit(1); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate syms_left = SYMCHUNK; 12347c478bd9Sstevel@tonic-gate if (nextsym) 12357c478bd9Sstevel@tonic-gate *nextsym = (ARFILEP)sym_ptr; 12367c478bd9Sstevel@tonic-gate else 12377c478bd9Sstevel@tonic-gate *symlist = sym_ptr; 12387c478bd9Sstevel@tonic-gate nextsym = sym_ptr; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate sym_ptr = nextsym; 12417c478bd9Sstevel@tonic-gate nextsym++; 12427c478bd9Sstevel@tonic-gate syms_left--; 12437c478bd9Sstevel@tonic-gate (*nsyms)++; 12447c478bd9Sstevel@tonic-gate *sym_ptr = fptr; 12457c478bd9Sstevel@tonic-gate savename(symname); /* put name in the archiver's */ 12467c478bd9Sstevel@tonic-gate /* symbol table string table */ 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate return (0); 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate /* 12537c478bd9Sstevel@tonic-gate * Get the output file size 12547c478bd9Sstevel@tonic-gate */ 12557c478bd9Sstevel@tonic-gate static int 12567c478bd9Sstevel@tonic-gate sizeofmembers(int psum) 12577c478bd9Sstevel@tonic-gate { 12587c478bd9Sstevel@tonic-gate int sum = 0; 12597c478bd9Sstevel@tonic-gate ARFILE *fptr; 12607c478bd9Sstevel@tonic-gate int hdrsize = sizeof (struct ar_hdr); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 12637c478bd9Sstevel@tonic-gate fptr->ar_offset = psum + sum; 12647c478bd9Sstevel@tonic-gate sum += fptr->ar_size; 12657c478bd9Sstevel@tonic-gate if (fptr->ar_size & 01) 12667c478bd9Sstevel@tonic-gate sum++; 12677c478bd9Sstevel@tonic-gate sum += hdrsize; 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) && 12707c478bd9Sstevel@tonic-gate fptr->ar_next && (fptr->ar_next->ar_flag & F_CLASS64)) { 12717c478bd9Sstevel@tonic-gate int remainder; 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate remainder = (psum + sum + hdrsize) % 8; 12747c478bd9Sstevel@tonic-gate if (remainder) { 12757c478bd9Sstevel@tonic-gate sum += (8 - remainder); 12767c478bd9Sstevel@tonic-gate fptr->ar_padding = 8 - remainder; 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate return (sum); 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate static int 12847c478bd9Sstevel@tonic-gate sizeofnewarchive(int nsyms, int longnames) 12857c478bd9Sstevel@tonic-gate { 12867c478bd9Sstevel@tonic-gate int sum = 0; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate sum += SARMAG; 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate if (nsyms) { 12917c478bd9Sstevel@tonic-gate char *top = (char *)str_top; 12927c478bd9Sstevel@tonic-gate char *base = (char *)str_base; 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate while ((top - base) & 03) 12957c478bd9Sstevel@tonic-gate top++; 12967c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 12977c478bd9Sstevel@tonic-gate sum += (nsyms + 1) * 4; 12987c478bd9Sstevel@tonic-gate sum += top - base; 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate if (longnames) { 13027c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 13037c478bd9Sstevel@tonic-gate sum += str_top1 - str_base1; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate /* 13077c478bd9Sstevel@tonic-gate * If the first member file is ELFCLASS64 type, 13087c478bd9Sstevel@tonic-gate * we have to ensure the member contents will align 13097c478bd9Sstevel@tonic-gate * on 8 byte boundary. 13107c478bd9Sstevel@tonic-gate */ 13117c478bd9Sstevel@tonic-gate if (listhead && (listhead->ar_flag & F_CLASS64)) { 13127c478bd9Sstevel@tonic-gate if (((sum + (sizeof (struct ar_hdr))) % 8) != 0) { 13137c478bd9Sstevel@tonic-gate sum += 4; 13147c478bd9Sstevel@tonic-gate pad_symtab = 4; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate sum += sizeofmembers(sum); 13187c478bd9Sstevel@tonic-gate return (sum); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate static void 13227c478bd9Sstevel@tonic-gate arwrite(char *name, int nfd, char *dst, int size) { 13237c478bd9Sstevel@tonic-gate if (write(nfd, dst, size) != size) { 13247c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_04_ERROR, 13257c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 13267c478bd9Sstevel@tonic-gate exit(2); 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate static char * 13317c478bd9Sstevel@tonic-gate make_tmpname(char *filename) { 13327c478bd9Sstevel@tonic-gate static char template[] = "arXXXXXX"; 13337c478bd9Sstevel@tonic-gate char *tmpname; 13347c478bd9Sstevel@tonic-gate char *slash = strrchr(filename, '/'); 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate if (slash != (char *)NULL) { 13377c478bd9Sstevel@tonic-gate char c; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate c = *slash; 13407c478bd9Sstevel@tonic-gate *slash = 0; 13417c478bd9Sstevel@tonic-gate tmpname = (char *)malloc(strlen(filename) + 13427c478bd9Sstevel@tonic-gate sizeof (template) + 2); 1343d6555420Smike_s (void) strcpy(tmpname, filename); 1344d6555420Smike_s (void) strcat(tmpname, "/"); 1345d6555420Smike_s (void) strcat(tmpname, template); 1346d6555420Smike_s (void) mktemp(tmpname); 13477c478bd9Sstevel@tonic-gate *slash = c; 13487c478bd9Sstevel@tonic-gate } else { 13497c478bd9Sstevel@tonic-gate tmpname = malloc(sizeof (template)); 1350d6555420Smike_s (void) strcpy(tmpname, template); 1351d6555420Smike_s (void) mktemp(tmpname); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate return (tmpname); 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate static int 13577c478bd9Sstevel@tonic-gate ar_copy(char *from, char *to) { 13587c478bd9Sstevel@tonic-gate int fromfd, tofd, nread; 13597c478bd9Sstevel@tonic-gate int saved; 13607c478bd9Sstevel@tonic-gate char buf[8192]; 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate fromfd = open(from, O_RDONLY); 13637c478bd9Sstevel@tonic-gate if (fromfd < 0) 13647c478bd9Sstevel@tonic-gate return (-1); 13657c478bd9Sstevel@tonic-gate tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 0777); 13667c478bd9Sstevel@tonic-gate if (tofd < 0) { 13677c478bd9Sstevel@tonic-gate saved = errno; 1368d6555420Smike_s (void) close(fromfd); 13697c478bd9Sstevel@tonic-gate errno = saved; 13707c478bd9Sstevel@tonic-gate return (-1); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate while ((nread = read(fromfd, buf, sizeof (buf))) > 0) { 13737c478bd9Sstevel@tonic-gate if (write(tofd, buf, nread) != nread) { 13747c478bd9Sstevel@tonic-gate saved = errno; 1375d6555420Smike_s (void) close(fromfd); 1376d6555420Smike_s (void) close(tofd); 13777c478bd9Sstevel@tonic-gate errno = saved; 13787c478bd9Sstevel@tonic-gate return (-1); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate saved = errno; 1382d6555420Smike_s (void) close(fromfd); 1383d6555420Smike_s (void) close(tofd); 13847c478bd9Sstevel@tonic-gate if (nread < 0) { 13857c478bd9Sstevel@tonic-gate errno = saved; 13867c478bd9Sstevel@tonic-gate return (-1); 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate return (0); 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate static int 1392d6555420Smike_s ar_rename(char *from, char *to) 1393d6555420Smike_s { 13947c478bd9Sstevel@tonic-gate int exists; 13957c478bd9Sstevel@tonic-gate struct stat s; 13967c478bd9Sstevel@tonic-gate int ret = 0; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate exists = lstat(to, &s) == 0; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate if (! exists || (!S_ISLNK(s.st_mode) && s.st_nlink == 1)) { 14017c478bd9Sstevel@tonic-gate ret = rename(from, to); 14027c478bd9Sstevel@tonic-gate if (ret == 0) { 14037c478bd9Sstevel@tonic-gate if (exists) { 1404d6555420Smike_s (void) chmod(to, s.st_mode & 0777); 14057c478bd9Sstevel@tonic-gate if (chown(to, s.st_uid, s.st_gid) >= 0) 1406d6555420Smike_s (void) chmod(to, s.st_mode & 07777); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate } else { 1409d6555420Smike_s (void) unlink(from); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate } else { 14127c478bd9Sstevel@tonic-gate ret = ar_copy(from, to); 1413d6555420Smike_s (void) unlink(from); 14147c478bd9Sstevel@tonic-gate } 14157c478bd9Sstevel@tonic-gate return (ret); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate static int 14197c478bd9Sstevel@tonic-gate sizeofnewarchiveheader(int nsyms, int longnames) 14207c478bd9Sstevel@tonic-gate { 14217c478bd9Sstevel@tonic-gate int sum = 0; 14227c478bd9Sstevel@tonic-gate 14237c478bd9Sstevel@tonic-gate sum += SARMAG; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (nsyms) { 14267c478bd9Sstevel@tonic-gate char *top = (char *)str_top; 14277c478bd9Sstevel@tonic-gate char *base = (char *)str_base; 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate while ((top - base) & 03) 14307c478bd9Sstevel@tonic-gate top++; 14317c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 14327c478bd9Sstevel@tonic-gate sum += (nsyms + 1) * 4; 14337c478bd9Sstevel@tonic-gate sum += top - base; 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate if (longnames) { 14377c478bd9Sstevel@tonic-gate sum += sizeof (struct ar_hdr); 14387c478bd9Sstevel@tonic-gate sum += str_top1 - str_base1; 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate /* 14427c478bd9Sstevel@tonic-gate * If the first member file is ELFCLASS64 type, 14437c478bd9Sstevel@tonic-gate * we have to ensure the member contents will align 14447c478bd9Sstevel@tonic-gate * on 8 byte boundary. 14457c478bd9Sstevel@tonic-gate */ 14467c478bd9Sstevel@tonic-gate if (listhead && (listhead->ar_flag & F_CLASS64)) { 14477c478bd9Sstevel@tonic-gate if (((sum + (sizeof (struct ar_hdr))) % 8) != 0) { 14487c478bd9Sstevel@tonic-gate sum += 4; 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate return (sum); 14527c478bd9Sstevel@tonic-gate } 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate static char * 14557c478bd9Sstevel@tonic-gate writelargefile(Cmd_info *cmd_info, long long_tab_size, int longnames, 14567c478bd9Sstevel@tonic-gate ARFILEP *symlist, long nsyms, int found_obj, int new_archive) 14577c478bd9Sstevel@tonic-gate { 1458d6555420Smike_s ARFILE * fptr; 14597c478bd9Sstevel@tonic-gate char *name = cmd_info->arnam; 14607c478bd9Sstevel@tonic-gate int arsize; 14617c478bd9Sstevel@tonic-gate char *dst; 14627c478bd9Sstevel@tonic-gate char *tmp_dst; 14637c478bd9Sstevel@tonic-gate int nfd; 14647c478bd9Sstevel@tonic-gate char *new_name; 14657c478bd9Sstevel@tonic-gate FILE *f; 14667c478bd9Sstevel@tonic-gate struct stat stbuf; 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate new_name = make_tmpname(name); 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate if (new_archive) { 14717c478bd9Sstevel@tonic-gate nfd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 14727c478bd9Sstevel@tonic-gate if (nfd == -1) { 14737c478bd9Sstevel@tonic-gate error_message(SYS_CREATE_01_ERROR, 14747c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 14757c478bd9Sstevel@tonic-gate exit(1); 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate } else { 14787c478bd9Sstevel@tonic-gate nfd = open(new_name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); 14797c478bd9Sstevel@tonic-gate if (nfd == -1) { 14807c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_02_ERROR, 14817c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), name); 14827c478bd9Sstevel@tonic-gate exit(1); 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate arsize = sizeofnewarchiveheader(nsyms, longnames); 14877c478bd9Sstevel@tonic-gate if (nsyms == 0 && found_obj != 0) 14887c478bd9Sstevel@tonic-gate arsize += sizeof (struct ar_hdr) + 4 + 4; 14897c478bd9Sstevel@tonic-gate if (arsize < 2048) { 14907c478bd9Sstevel@tonic-gate arsize = 2048; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate dst = tmp_dst = (char *)malloc(arsize); 14937c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, ARMAG, SARMAG); 14947c478bd9Sstevel@tonic-gate tmp_dst += SARMAG; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate if (nsyms || found_obj != 0) { 14977c478bd9Sstevel@tonic-gate int diff; 14987c478bd9Sstevel@tonic-gate diff = writesymtab(tmp_dst, nsyms, symlist); 14997c478bd9Sstevel@tonic-gate tmp_dst += diff; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate if (longnames) { 15037c478bd9Sstevel@tonic-gate (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), 15047c478bd9Sstevel@tonic-gate (unsigned)0, (unsigned)0, (unsigned)0, 15057c478bd9Sstevel@tonic-gate (long)long_tab_size, ARFMAG); 15067c478bd9Sstevel@tonic-gate tmp_dst += sizeof (struct ar_hdr); 15077c478bd9Sstevel@tonic-gate (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); 15087c478bd9Sstevel@tonic-gate tmp_dst += str_top1 - str_base1; 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate #ifndef XPG4 15117c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 15127c478bd9Sstevel@tonic-gate error_message(BER_MES_WRITE_ERROR, 15137c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, 15147c478bd9Sstevel@tonic-gate cmd_info->arnam); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate #endif 15177c478bd9Sstevel@tonic-gate arwrite(name, nfd, dst, (int)(tmp_dst - dst)); 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate for (fptr = listhead; fptr; fptr = fptr->ar_next) { 15207c478bd9Sstevel@tonic-gate if (fptr->ar_name[0] == 0) { 15217c478bd9Sstevel@tonic-gate fptr->ar_longname = fptr->ar_rawname; 15227c478bd9Sstevel@tonic-gate (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) 15257c478bd9Sstevel@tonic-gate (void) sprintf(dst, FNFORMAT, 15267c478bd9Sstevel@tonic-gate trimslash(fptr->ar_longname)); 15277c478bd9Sstevel@tonic-gate else 15287c478bd9Sstevel@tonic-gate (void) sprintf(dst, FNFORMAT, fptr->ar_name); 15297c478bd9Sstevel@tonic-gate (void) sprintf(dst+16, TLFORMAT, fptr->ar_date, 15307c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, 15317c478bd9Sstevel@tonic-gate (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, 15327c478bd9Sstevel@tonic-gate ARFMAG); 15337c478bd9Sstevel@tonic-gate arwrite(name, nfd, dst, sizeof (struct ar_hdr)); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate if (!(fptr->ar_flag & F_MALLOCED) && 15367c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_MMAPED) && 15377c478bd9Sstevel@tonic-gate !(fptr->ar_flag & F_ELFRAW)) { 15387c478bd9Sstevel@tonic-gate f = fopen(fptr->ar_pathname, "r"); 15397c478bd9Sstevel@tonic-gate if (stat(fptr->ar_pathname, &stbuf) < 0) { 15407c478bd9Sstevel@tonic-gate (void) fclose(f); 15417c478bd9Sstevel@tonic-gate f = NULL; 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate if (f == NULL) { 15447c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 15457c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 15467c478bd9Sstevel@tonic-gate fptr->ar_longname); 15477c478bd9Sstevel@tonic-gate exit(1); 15487c478bd9Sstevel@tonic-gate } else { 15497c478bd9Sstevel@tonic-gate if ((fptr->ar_contents = (char *) 15507c478bd9Sstevel@tonic-gate malloc(ROUNDUP(stbuf.st_size))) == NULL) { 15517c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 15527c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 15537c478bd9Sstevel@tonic-gate exit(1); 15547c478bd9Sstevel@tonic-gate } 15557c478bd9Sstevel@tonic-gate if (fread(fptr->ar_contents, 15567c478bd9Sstevel@tonic-gate sizeof (char), 15577c478bd9Sstevel@tonic-gate stbuf.st_size, f) != stbuf.st_size) { 15587c478bd9Sstevel@tonic-gate error_message(SYS_READ_ERROR, 15597c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 15607c478bd9Sstevel@tonic-gate fptr->ar_longname); 15617c478bd9Sstevel@tonic-gate exit(1); 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 1565d6555420Smike_s (void) fclose(f); 15667c478bd9Sstevel@tonic-gate free(fptr->ar_contents); 15677c478bd9Sstevel@tonic-gate } else { 15687c478bd9Sstevel@tonic-gate arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); 15697c478bd9Sstevel@tonic-gate if (fptr->ar_flag & F_MALLOCED) { 15707c478bd9Sstevel@tonic-gate (void) free(fptr->ar_contents); 15717c478bd9Sstevel@tonic-gate fptr->ar_flag &= ~(F_MALLOCED); 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate if (fptr->ar_size & 0x1) { 15767c478bd9Sstevel@tonic-gate arwrite(name, nfd, "\n", 1); 15777c478bd9Sstevel@tonic-gate } 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate if (fptr->ar_padding) { 15807c478bd9Sstevel@tonic-gate int i = fptr->ar_padding; 15817c478bd9Sstevel@tonic-gate while (i) { 15827c478bd9Sstevel@tonic-gate arwrite(name, nfd, "\n", 1); 15837c478bd9Sstevel@tonic-gate --i; 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate } 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * All preparation for writing is done. 15907c478bd9Sstevel@tonic-gate */ 15917c478bd9Sstevel@tonic-gate (void) elf_end(cmd_info->arf); 15927c478bd9Sstevel@tonic-gate (void) close(cmd_info->afd); 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate if (!new_archive) { 1595d6555420Smike_s (void) ar_rename(new_name, name); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate return (dst); 15997c478bd9Sstevel@tonic-gate } 1600