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
55aefb655Srie * Common Development and Distribution License (the "License").
65aefb655Srie * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
215aefb655Srie
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate * All Rights Reserved
257c478bd9Sstevel@tonic-gate *
26*ba7866cdSAli Bahrami * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include <errno.h>
3057ef7aa9SRod Evans #include "alist.h"
317c478bd9Sstevel@tonic-gate #include "mcs.h"
327c478bd9Sstevel@tonic-gate #include "extern.h"
337c478bd9Sstevel@tonic-gate #include "gelf.h"
347c478bd9Sstevel@tonic-gate
350d15df17Sab196087 /*
360d15df17Sab196087 * Type used to pass state information for the current
370d15df17Sab196087 * file between routines.
380d15df17Sab196087 */
390d15df17Sab196087 typedef struct {
400d15df17Sab196087 int Sect_exists;
410d15df17Sab196087 int notesegndx;
420d15df17Sab196087 int notesctndx;
430d15df17Sab196087 Seg_Table *b_e_seg_table;
440d15df17Sab196087 section_info_table *sec_table;
450d15df17Sab196087 int64_t *off_table; /* maintains section's offset; set to */
460d15df17Sab196087 /* retain old offset, else 0 */
470d15df17Sab196087 int64_t *nobits_table; /* maintains NOBITS sections */
480d15df17Sab196087 char *new_sec_string;
490d15df17Sab196087 } file_state_t;
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * Function prototypes.
547c478bd9Sstevel@tonic-gate */
55d1477c77SAli Bahrami static void copy_file(int, char *, Tmp_File *);
567c478bd9Sstevel@tonic-gate static void
577c478bd9Sstevel@tonic-gate copy_non_elf_to_temp_ar(int, Elf *, int, Elf_Arhdr *, char *, Cmd_Info *);
587c478bd9Sstevel@tonic-gate static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *);
597c478bd9Sstevel@tonic-gate static int process_file(Elf *, char *, Cmd_Info *);
600d15df17Sab196087 static void initialize(int shnum, Cmd_Info *, file_state_t *);
610d15df17Sab196087 static int build_segment_table(Elf*, GElf_Ehdr *, file_state_t *);
620d15df17Sab196087 static int traverse_file(Elf *, GElf_Ehdr *, char *, Cmd_Info *,
630d15df17Sab196087 file_state_t *);
640d15df17Sab196087 static uint64_t location(int64_t, int, Elf *, file_state_t *);
650d15df17Sab196087 static uint64_t scn_location(Elf_Scn *, Elf *, file_state_t *);
660d15df17Sab196087 static int build_file(Elf *, GElf_Ehdr *, Cmd_Info *, file_state_t *);
670d15df17Sab196087 static void post_process(Cmd_Info *, file_state_t *);
680d15df17Sab196087
690d15df17Sab196087
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate int
each_file(char * cur_file,Cmd_Info * cmd_info)727c478bd9Sstevel@tonic-gate each_file(char *cur_file, Cmd_Info *cmd_info)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate Elf *elf = 0;
757c478bd9Sstevel@tonic-gate Elf_Cmd cmd;
767c478bd9Sstevel@tonic-gate Elf *arf = 0;
777c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header;
787c478bd9Sstevel@tonic-gate char *cur_filenm = NULL;
797c478bd9Sstevel@tonic-gate int code = 0;
807c478bd9Sstevel@tonic-gate int error = 0, err = 0;
817c478bd9Sstevel@tonic-gate int ar_file = 0;
827c478bd9Sstevel@tonic-gate int fdartmp;
837c478bd9Sstevel@tonic-gate int fd;
847c478bd9Sstevel@tonic-gate int oflag;
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate if (cmd_info->flags & MIGHT_CHG)
877c478bd9Sstevel@tonic-gate oflag = O_RDWR;
887c478bd9Sstevel@tonic-gate else
897c478bd9Sstevel@tonic-gate oflag = O_RDONLY;
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate if ((fd = open(cur_file, oflag)) == -1) {
920d15df17Sab196087 error_message(OPEN_ERROR, SYSTEM_ERROR, strerror(errno),
930d15df17Sab196087 prog, cur_file);
947c478bd9Sstevel@tonic-gate return (FAILURE);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect.
997c478bd9Sstevel@tonic-gate * libelf does not allow elf_begin() with ELF_C_RDWR when processing
1007c478bd9Sstevel@tonic-gate * archive file members. Because we are limited to ELF_C_READ use, any
1017c478bd9Sstevel@tonic-gate * ELF data modification must be provided by updating a copy of
1027c478bd9Sstevel@tonic-gate * the data, rather than updating the original file data.
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate cmd = ELF_C_READ;
10557ef7aa9SRod Evans if ((arf = elf_begin(fd, cmd, NULL)) == NULL) {
1060d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
1077c478bd9Sstevel@tonic-gate (void) elf_end(arf);
1087c478bd9Sstevel@tonic-gate (void) close(fd); /* done processing this file */
1097c478bd9Sstevel@tonic-gate return (FAILURE);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate if ((elf_kind(arf) == ELF_K_AR)) {
1137c478bd9Sstevel@tonic-gate ar_file = 1;
1147c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, MIGHT_CHG)) {
115d1477c77SAli Bahrami artmpfile.tmp_name = tempnam(TMPDIR, "mcs2");
116d1477c77SAli Bahrami if ((fdartmp = open(artmpfile.tmp_name,
1177c478bd9Sstevel@tonic-gate O_WRONLY | O_APPEND | O_CREAT,
1187c478bd9Sstevel@tonic-gate (mode_t)0666)) == NULL) {
1197c478bd9Sstevel@tonic-gate error_message(OPEN_TEMP_ERROR,
1207c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno),
1217c478bd9Sstevel@tonic-gate prog, artmpfile);
1227c478bd9Sstevel@tonic-gate (void) elf_end(arf);
1237c478bd9Sstevel@tonic-gate (void) close(fd);
124d1477c77SAli Bahrami mcs_exit(FAILURE);
1257c478bd9Sstevel@tonic-gate }
126d1477c77SAli Bahrami artmpfile.tmp_unlink = 1;
1277c478bd9Sstevel@tonic-gate /* write magic string to artmpfile */
1287c478bd9Sstevel@tonic-gate if ((write(fdartmp, ARMAG, SARMAG)) != SARMAG) {
1297c478bd9Sstevel@tonic-gate error_message(WRITE_ERROR,
1307c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno),
131d1477c77SAli Bahrami prog, artmpfile.tmp_name, cur_file);
1327c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate } else {
1367c478bd9Sstevel@tonic-gate ar_file = 0;
1377c478bd9Sstevel@tonic-gate cur_filenm = cur_file;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * Holds temporary file;
1427c478bd9Sstevel@tonic-gate * if archive, holds the current member file if it has an ehdr,
1437c478bd9Sstevel@tonic-gate * and there were no errors in
1447c478bd9Sstevel@tonic-gate * processing the object file.
1457c478bd9Sstevel@tonic-gate */
146d1477c77SAli Bahrami elftmpfile.tmp_name = tempnam(TMPDIR, "mcs1");
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate while ((elf = elf_begin(fd, cmd, arf)) != 0) {
1497c478bd9Sstevel@tonic-gate if (ar_file) /* get header info */ {
1505aefb655Srie size_t len;
1515aefb655Srie
1527c478bd9Sstevel@tonic-gate if ((mem_header = elf_getarhdr(elf)) == NULL) {
1530d15df17Sab196087 error_message(GETARHDR_ERROR, LIBelf_ERROR,
1540d15df17Sab196087 elf_errmsg(-1), prog, cur_file,
1550d15df17Sab196087 elf_getbase(elf));
1567c478bd9Sstevel@tonic-gate (void) elf_end(elf);
1577c478bd9Sstevel@tonic-gate (void) elf_end(arf);
1587c478bd9Sstevel@tonic-gate (void) close(fd);
159d1477c77SAli Bahrami free_tempfile(&artmpfile);
1607c478bd9Sstevel@tonic-gate return (FAILURE);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (cur_filenm != NULL)
1647c478bd9Sstevel@tonic-gate free(cur_filenm);
1655aefb655Srie
1665aefb655Srie len = (strlen(cur_file) + 3 +
1675aefb655Srie strlen(mem_header->ar_name));
1685aefb655Srie
1695aefb655Srie if ((cur_filenm = malloc(len)) == NULL) {
1707c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR,
17157ef7aa9SRod Evans PLAIN_ERROR, NULL, prog);
1727c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate
1755aefb655Srie (void) snprintf(cur_filenm, len, "%s[%s]",
1767c478bd9Sstevel@tonic-gate cur_file, mem_header->ar_name);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate if (elf_kind(elf) == ELF_K_ELF) {
1807c478bd9Sstevel@tonic-gate if ((code = process_file(elf, cur_filenm, cmd_info)) ==
1817c478bd9Sstevel@tonic-gate FAILURE) {
1827c478bd9Sstevel@tonic-gate if (!ar_file) {
1837c478bd9Sstevel@tonic-gate (void) elf_end(arf);
1847c478bd9Sstevel@tonic-gate (void) elf_end(elf);
1857c478bd9Sstevel@tonic-gate (void) close(fd);
1867c478bd9Sstevel@tonic-gate return (FAILURE);
1877c478bd9Sstevel@tonic-gate } else {
1880d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf,
1890d15df17Sab196087 fdartmp, mem_header,
1907c478bd9Sstevel@tonic-gate cur_file, cmd_info);
1917c478bd9Sstevel@tonic-gate error++;
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate } else if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
1947c478bd9Sstevel@tonic-gate if (code == DONT_BUILD)
1950d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf,
1960d15df17Sab196087 fdartmp, mem_header,
1977c478bd9Sstevel@tonic-gate cur_file, cmd_info);
1987c478bd9Sstevel@tonic-gate else
1997c478bd9Sstevel@tonic-gate copy_elf_file_to_temp_ar_file(
2007c478bd9Sstevel@tonic-gate fdartmp, mem_header, cur_file);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate } else {
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate * decide what to do with non-ELF file
2057c478bd9Sstevel@tonic-gate */
2067c478bd9Sstevel@tonic-gate if (!ar_file) {
2070d15df17Sab196087 error_message(FILE_TYPE_ERROR, PLAIN_ERROR,
20857ef7aa9SRod Evans NULL, prog, cur_filenm);
2097c478bd9Sstevel@tonic-gate (void) close(fd);
2107c478bd9Sstevel@tonic-gate return (FAILURE);
2117c478bd9Sstevel@tonic-gate } else {
2127c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, MIGHT_CHG))
2130d15df17Sab196087 copy_non_elf_to_temp_ar(fd, elf,
2140d15df17Sab196087 fdartmp, mem_header,
2157c478bd9Sstevel@tonic-gate cur_file, cmd_info);
2167c478bd9Sstevel@tonic-gate }
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate cmd = elf_next(elf);
2197c478bd9Sstevel@tonic-gate (void) elf_end(elf);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate err = elf_errno();
2237c478bd9Sstevel@tonic-gate if (err != 0) {
2240d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR,
2250d15df17Sab196087 elf_errmsg(err), prog);
22657ef7aa9SRod Evans error_message(NOT_MANIPULATED_ERROR, PLAIN_ERROR, NULL,
2277c478bd9Sstevel@tonic-gate prog, cur_file);
2287c478bd9Sstevel@tonic-gate return (FAILURE);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate (void) elf_end(arf);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
2347c478bd9Sstevel@tonic-gate (void) close(fdartmp); /* done writing to ar_temp_file */
2357c478bd9Sstevel@tonic-gate /* copy ar_temp_file to FILE */
236d1477c77SAli Bahrami copy_file(fd, cur_file, &artmpfile);
2377c478bd9Sstevel@tonic-gate } else if (code != DONT_BUILD && CHK_OPT(cmd_info, MIGHT_CHG))
238d1477c77SAli Bahrami copy_file(fd, cur_file, &elftmpfile);
2397c478bd9Sstevel@tonic-gate (void) close(fd); /* done processing this file */
2407c478bd9Sstevel@tonic-gate return (error);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate static int
process_file(Elf * elf,char * cur_file,Cmd_Info * cmd_info)2447c478bd9Sstevel@tonic-gate process_file(Elf *elf, char *cur_file, Cmd_Info *cmd_info)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate int error = SUCCESS;
2477c478bd9Sstevel@tonic-gate int x;
2487c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr;
2497c478bd9Sstevel@tonic-gate size_t shnum;
2500d15df17Sab196087 file_state_t state;
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate * Initialize
2547c478bd9Sstevel@tonic-gate */
2557c478bd9Sstevel@tonic-gate if (gelf_getehdr(elf, &ehdr) == NULL) {
2560d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
2577c478bd9Sstevel@tonic-gate return (FAILURE);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
26062b628a6SAli Bahrami if (elf_getshdrnum(elf, &shnum) == -1) {
2610d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
2627c478bd9Sstevel@tonic-gate return (FAILURE);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate
2650d15df17Sab196087 /* Initialize per-file state */
2660d15df17Sab196087 state.Sect_exists = 0;
2670d15df17Sab196087 state.notesegndx = -1;
2680d15df17Sab196087 state.notesctndx = -1;
2690d15df17Sab196087 state.b_e_seg_table = NULL;
2700d15df17Sab196087 state.sec_table = NULL;
2710d15df17Sab196087 state.off_table = 0;
2720d15df17Sab196087 state.nobits_table = NULL;
2730d15df17Sab196087 state.new_sec_string = NULL;
2747c478bd9Sstevel@tonic-gate
2750d15df17Sab196087 initialize(shnum, cmd_info, &state);
2767c478bd9Sstevel@tonic-gate
2770d15df17Sab196087 if ((ehdr.e_phnum != 0) &&
2780d15df17Sab196087 (build_segment_table(elf, &ehdr, &state) == FAILURE)) {
2790d15df17Sab196087 x = error = FAILURE;
2800d15df17Sab196087 } else if ((x = traverse_file(elf, &ehdr, cur_file,
2810d15df17Sab196087 cmd_info, &state)) == FAILURE) {
28257ef7aa9SRod Evans error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, NULL,
2837c478bd9Sstevel@tonic-gate prog, cur_file);
2847c478bd9Sstevel@tonic-gate error = FAILURE;
2857c478bd9Sstevel@tonic-gate } else if (x != DONT_BUILD && x != FAILURE) {
2860d15df17Sab196087 post_process(cmd_info, &state);
2870d15df17Sab196087 if (build_file(elf, &ehdr, cmd_info, &state) == FAILURE) {
2880d15df17Sab196087 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR,
28957ef7aa9SRod Evans NULL, prog, cur_file);
2907c478bd9Sstevel@tonic-gate error = FAILURE;
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2940d15df17Sab196087 /* Release any dynamicaly allocated buffers */
2950d15df17Sab196087 if (state.b_e_seg_table != NULL)
2960d15df17Sab196087 free(state.b_e_seg_table);
2970d15df17Sab196087 if (state.sec_table != NULL)
2980d15df17Sab196087 free(state.sec_table);
2990d15df17Sab196087 if (state.off_table != NULL)
3000d15df17Sab196087 free(state.off_table);
3010d15df17Sab196087 if (state.nobits_table != NULL)
3020d15df17Sab196087 free(state.nobits_table);
3030d15df17Sab196087 if (state.new_sec_string != NULL)
3040d15df17Sab196087 free(state.new_sec_string);
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate if (x == DONT_BUILD)
3077c478bd9Sstevel@tonic-gate return (DONT_BUILD);
3087c478bd9Sstevel@tonic-gate else
3097c478bd9Sstevel@tonic-gate return (error);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate static int
traverse_file(Elf * elf,GElf_Ehdr * ehdr,char * cur_file,Cmd_Info * cmd_info,file_state_t * state)3130d15df17Sab196087 traverse_file(Elf *elf, GElf_Ehdr * ehdr, char *cur_file, Cmd_Info *cmd_info,
3140d15df17Sab196087 file_state_t *state)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate Elf_Scn * scn;
3177c478bd9Sstevel@tonic-gate Elf_Scn * temp_scn;
3187c478bd9Sstevel@tonic-gate Elf_Data * data;
3197c478bd9Sstevel@tonic-gate GElf_Shdr * shdr;
3207c478bd9Sstevel@tonic-gate char *temp_name;
3217c478bd9Sstevel@tonic-gate section_info_table * sinfo;
3227c478bd9Sstevel@tonic-gate GElf_Xword x;
3237c478bd9Sstevel@tonic-gate int ret = 0, SYM = 0; /* used by strip command */
3247c478bd9Sstevel@tonic-gate int phnum = ehdr->e_phnum;
3257c478bd9Sstevel@tonic-gate unsigned int i, scn_index;
3267c478bd9Sstevel@tonic-gate size_t shstrndx, shnum;
3277c478bd9Sstevel@tonic-gate
3280d15df17Sab196087 state->Sect_exists = 0;
3297c478bd9Sstevel@tonic-gate
33062b628a6SAli Bahrami if (elf_getshdrnum(elf, &shnum) == -1) {
3310d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
3327c478bd9Sstevel@tonic-gate return (FAILURE);
3337c478bd9Sstevel@tonic-gate }
33462b628a6SAli Bahrami if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
3350d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
3367c478bd9Sstevel@tonic-gate return (FAILURE);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate scn = 0;
3407c478bd9Sstevel@tonic-gate scn_index = 1;
3410d15df17Sab196087 sinfo = &state->sec_table[scn_index];
3427c478bd9Sstevel@tonic-gate while ((scn = elf_nextscn(elf, scn)) != 0) {
3437c478bd9Sstevel@tonic-gate char *name;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate shdr = &(sinfo->shdr);
3467c478bd9Sstevel@tonic-gate if (gelf_getshdr(scn, shdr) == NULL) {
3477c478bd9Sstevel@tonic-gate error_message(NO_SECT_TABLE_ERROR,
3480d15df17Sab196087 LIBelf_ERROR, elf_errmsg(-1), prog, cur_file);
3497c478bd9Sstevel@tonic-gate return (FAILURE);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3520d15df17Sab196087 /*
3530d15df17Sab196087 * Note: If the object has problems, name
3540d15df17Sab196087 * may be set to NULL by the following.
3550d15df17Sab196087 */
3560d15df17Sab196087 name = elf_strptr(elf, shstrndx, (size_t)shdr->sh_name);
3570d15df17Sab196087
3587c478bd9Sstevel@tonic-gate sinfo->scn = scn;
3597c478bd9Sstevel@tonic-gate sinfo->secno = scn_index;
3607c478bd9Sstevel@tonic-gate sinfo->osecno = scn_index;
3617c478bd9Sstevel@tonic-gate SET_ACTION(sinfo->flags, ACT_NOP);
3627c478bd9Sstevel@tonic-gate sinfo->name = name;
3637c478bd9Sstevel@tonic-gate if (ehdr->e_phnum == 0)
3647c478bd9Sstevel@tonic-gate SET_LOC(sinfo->flags, NOSEG);
3657c478bd9Sstevel@tonic-gate else
3660d15df17Sab196087 SET_LOC(sinfo->flags, scn_location(scn, elf, state));
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_GROUP) {
36957ef7aa9SRod Evans if (aplist_append(&cmd_info->sh_groups,
37057ef7aa9SRod Evans sinfo, 10) == NULL) {
3710d15df17Sab196087 error_message(MALLOC_ERROR, PLAIN_ERROR,
37257ef7aa9SRod Evans NULL, prog);
3737c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * If the target section is pointed by a section
3797c478bd9Sstevel@tonic-gate * holding relocation infomation, then the
3807c478bd9Sstevel@tonic-gate * pointing section would be useless if the
3817c478bd9Sstevel@tonic-gate * target section is removed.
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate if ((shdr->sh_type == SHT_REL ||
3847c478bd9Sstevel@tonic-gate shdr->sh_type == SHT_RELA) &&
3857c478bd9Sstevel@tonic-gate (shdr->sh_info != SHN_UNDEF &&
3867c478bd9Sstevel@tonic-gate (temp_scn = elf_getscn(elf, shdr->sh_info)) != 0)) {
3877c478bd9Sstevel@tonic-gate GElf_Shdr tmp_shdr;
3887c478bd9Sstevel@tonic-gate if (gelf_getshdr(temp_scn, &tmp_shdr) != NULL) {
3897c478bd9Sstevel@tonic-gate temp_name = elf_strptr(elf, shstrndx,
3907c478bd9Sstevel@tonic-gate (size_t)tmp_shdr.sh_name);
3917c478bd9Sstevel@tonic-gate sinfo->rel_name = temp_name;
3927c478bd9Sstevel@tonic-gate sinfo->rel_scn_index =
3937c478bd9Sstevel@tonic-gate shdr->sh_info;
3947c478bd9Sstevel@tonic-gate if (phnum == 0)
3957c478bd9Sstevel@tonic-gate sinfo->rel_loc = NOSEG;
3967c478bd9Sstevel@tonic-gate else
3977c478bd9Sstevel@tonic-gate sinfo->rel_loc =
3980d15df17Sab196087 scn_location(temp_scn, elf, state);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate data = 0;
4027c478bd9Sstevel@tonic-gate if ((data = elf_getdata(scn, data)) == NULL) {
4037c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
4047c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
4057c478bd9Sstevel@tonic-gate return (FAILURE);
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate sinfo->data = data;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Check if this section is a candidate for
4117c478bd9Sstevel@tonic-gate * action to be processes.
4127c478bd9Sstevel@tonic-gate */
4130d15df17Sab196087 if ((name != NULL) && (sectcmp(name) == 0)) {
4147c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags);
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate * This flag just shows that there was a
4187c478bd9Sstevel@tonic-gate * candidate.
4197c478bd9Sstevel@tonic-gate */
4200d15df17Sab196087 state->Sect_exists++;
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate * Any of the following section types should
4257c478bd9Sstevel@tonic-gate * also be removed (if possible) if invoked via
4267c478bd9Sstevel@tonic-gate * the 'strip' command.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) &&
4297c478bd9Sstevel@tonic-gate ((shdr->sh_type == SHT_SUNW_DEBUG) ||
4307c478bd9Sstevel@tonic-gate (shdr->sh_type == SHT_SUNW_DEBUGSTR))) {
4317c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags);
4320d15df17Sab196087 state->Sect_exists++;
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate /*
4377c478bd9Sstevel@tonic-gate * Zap this file ?
4387c478bd9Sstevel@tonic-gate */
4397c478bd9Sstevel@tonic-gate if ((cmd_info->flags & zFLAG) &&
4407c478bd9Sstevel@tonic-gate (shdr->sh_type == SHT_PROGBITS)) {
4417c478bd9Sstevel@tonic-gate SET_CANDIDATE(sinfo->flags);
4420d15df17Sab196087 state->Sect_exists++;
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate x = GET_LOC(sinfo->flags);
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate /*
4470d15df17Sab196087 * Remember the note section index so that we can
4480d15df17Sab196087 * reset the NOTE segment offset to point to it. Depending
4490d15df17Sab196087 * on the operation being carried out, the note section may
4500d15df17Sab196087 * be assigned a new location in the resulting ELF
4510d15df17Sab196087 * image, and the program header needs to reflect that.
4527c478bd9Sstevel@tonic-gate *
4530d15df17Sab196087 * There can be multiple contiguous note sections in
4540d15df17Sab196087 * an object, referenced by a single NOTE segment. We
4550d15df17Sab196087 * want to be sure and remember the one referenced by
4560d15df17Sab196087 * the program header, and not one of the others.
4577c478bd9Sstevel@tonic-gate */
4580d15df17Sab196087 if ((shdr->sh_type == SHT_NOTE) && (state->notesctndx == -1) &&
4590d15df17Sab196087 (state->notesegndx != -1) &&
4600d15df17Sab196087 (state->b_e_seg_table[state->notesegndx].p_offset
4610d15df17Sab196087 == shdr->sh_offset))
4620d15df17Sab196087 state->notesctndx = scn_index;
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate if (x == IN || x == PRIOR)
4650d15df17Sab196087 state->off_table[scn_index] = shdr->sh_offset;
4667c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_NOBITS)
4670d15df17Sab196087 state->nobits_table[scn_index] = 1;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * If this section satisfies the condition,
4717c478bd9Sstevel@tonic-gate * apply the actions specified.
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate if (ISCANDIDATE(sinfo->flags)) {
4747c478bd9Sstevel@tonic-gate ret += apply_action(sinfo, cur_file, cmd_info);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate * If I am strip command, determine if symtab can go or not.
4797c478bd9Sstevel@tonic-gate */
4807c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) &&
4817c478bd9Sstevel@tonic-gate (CHK_OPT(cmd_info, xFLAG) == 0) &&
4827c478bd9Sstevel@tonic-gate (CHK_OPT(cmd_info, lFLAG) == 0)) {
4837c478bd9Sstevel@tonic-gate if (shdr->sh_type == SHT_SYMTAB &&
4847c478bd9Sstevel@tonic-gate GET_LOC(sinfo->flags) == AFTER) {
4857c478bd9Sstevel@tonic-gate SYM = scn_index;
4867c478bd9Sstevel@tonic-gate }
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate scn_index++;
4897c478bd9Sstevel@tonic-gate sinfo++;
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate sinfo->scn = (Elf_Scn *) -1;
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate * If there were any errors traversing the file,
4957c478bd9Sstevel@tonic-gate * just return error.
4967c478bd9Sstevel@tonic-gate */
4977c478bd9Sstevel@tonic-gate if (ret != 0)
4987c478bd9Sstevel@tonic-gate return (FAILURE);
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate * Remove symbol table if possible
5027c478bd9Sstevel@tonic-gate */
5037c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, I_AM_STRIP) && SYM != 0) {
5047c478bd9Sstevel@tonic-gate GElf_Shdr tmp_shdr;
5057c478bd9Sstevel@tonic-gate
5060d15df17Sab196087 (void) gelf_getshdr(state->sec_table[SYM].scn, &tmp_shdr);
5070d15df17Sab196087 state->sec_table[SYM].secno = (GElf_Word)DELETED;
5087c478bd9Sstevel@tonic-gate ++(cmd_info->no_of_nulled);
5090d15df17Sab196087 if (state->Sect_exists == 0)
5100d15df17Sab196087 ++state->Sect_exists;
5110d15df17Sab196087 SET_ACTION(state->sec_table[SYM].flags, ACT_DELETE);
5120d15df17Sab196087 state->off_table[SYM] = 0;
5137c478bd9Sstevel@tonic-gate /*
5147c478bd9Sstevel@tonic-gate * Can I remove section header
5157c478bd9Sstevel@tonic-gate * string table ?
5167c478bd9Sstevel@tonic-gate */
5177c478bd9Sstevel@tonic-gate if ((tmp_shdr.sh_link < shnum) &&
5187c478bd9Sstevel@tonic-gate (tmp_shdr.sh_link != SHN_UNDEF) &&
5197c478bd9Sstevel@tonic-gate (tmp_shdr.sh_link != shstrndx) &&
5200d15df17Sab196087 (GET_LOC(state->sec_table[tmp_shdr.sh_link].flags) ==
5210d15df17Sab196087 AFTER)) {
5220d15df17Sab196087 state->sec_table[tmp_shdr.sh_link].secno =
5230d15df17Sab196087 (GElf_Word)DELETED;
5247c478bd9Sstevel@tonic-gate ++(cmd_info->no_of_nulled);
5250d15df17Sab196087 if (state->Sect_exists == 0)
5260d15df17Sab196087 ++state->Sect_exists;
5270d15df17Sab196087 SET_ACTION(state->sec_table[tmp_shdr.sh_link].flags,
5287c478bd9Sstevel@tonic-gate ACT_DELETE);
5290d15df17Sab196087 state->off_table[tmp_shdr.sh_link] = 0;
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate * If I only printed the contents, then
5357c478bd9Sstevel@tonic-gate * just report so.
5367c478bd9Sstevel@tonic-gate */
5377c478bd9Sstevel@tonic-gate if (CHK_OPT(cmd_info, pFLAG) && !CHK_OPT(cmd_info, MIGHT_CHG))
5387c478bd9Sstevel@tonic-gate return (DONT_BUILD); /* don't bother creating a new file */
5397c478bd9Sstevel@tonic-gate /* since the file has not changed */
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate * I might need to add a new section. Check it.
5437c478bd9Sstevel@tonic-gate */
5440d15df17Sab196087 if (state->Sect_exists == 0 && CHK_OPT(cmd_info, aFLAG)) {
5457c478bd9Sstevel@tonic-gate int act = 0;
5460d15df17Sab196087 state->new_sec_string = calloc(1, cmd_info->str_size + 1);
5470d15df17Sab196087 if (state->new_sec_string == NULL)
5487c478bd9Sstevel@tonic-gate return (FAILURE);
5497c478bd9Sstevel@tonic-gate for (act = 0; act < actmax; act++) {
5507c478bd9Sstevel@tonic-gate if (Action[act].a_action == ACT_APPEND) {
5510d15df17Sab196087 (void) strcat(state->new_sec_string,
5527c478bd9Sstevel@tonic-gate Action[act].a_string);
5530d15df17Sab196087 (void) strcat(state->new_sec_string, "\n");
5547c478bd9Sstevel@tonic-gate cmd_info->no_of_append = 1;
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate * If I did not append any new sections, and I did not
5617c478bd9Sstevel@tonic-gate * modify/delete any sections, then just report so.
5627c478bd9Sstevel@tonic-gate */
5630d15df17Sab196087 if ((state->Sect_exists == 0 && cmd_info->no_of_append == 0) ||
5647c478bd9Sstevel@tonic-gate !CHK_OPT(cmd_info, MIGHT_CHG))
5657c478bd9Sstevel@tonic-gate return (DONT_BUILD);
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate * Found at least one section which was processed.
5697c478bd9Sstevel@tonic-gate * Deleted or Appended or Compressed.
5707c478bd9Sstevel@tonic-gate */
5710d15df17Sab196087 if (state->Sect_exists) {
5727c478bd9Sstevel@tonic-gate /*
5737c478bd9Sstevel@tonic-gate * First, handle the deleted sections.
5747c478bd9Sstevel@tonic-gate */
5757c478bd9Sstevel@tonic-gate if (cmd_info->no_of_delete != 0 ||
5767c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled != 0) {
5777c478bd9Sstevel@tonic-gate int acc = 0;
5787c478bd9Sstevel@tonic-gate int rel_idx;
5797c478bd9Sstevel@tonic-gate
5807c478bd9Sstevel@tonic-gate /*
5817c478bd9Sstevel@tonic-gate * Handle relocation/target
5827c478bd9Sstevel@tonic-gate * sections.
5837c478bd9Sstevel@tonic-gate */
5840d15df17Sab196087 sinfo = &(state->sec_table[0]);
5857c478bd9Sstevel@tonic-gate for (i = 1; i < shnum; i++) {
5867c478bd9Sstevel@tonic-gate sinfo++;
5877c478bd9Sstevel@tonic-gate rel_idx = sinfo->rel_scn_index;
5887c478bd9Sstevel@tonic-gate if (rel_idx == 0)
5897c478bd9Sstevel@tonic-gate continue;
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate /*
5927c478bd9Sstevel@tonic-gate * If I am removed, then remove my
5937c478bd9Sstevel@tonic-gate * target section.
5947c478bd9Sstevel@tonic-gate */
5957c478bd9Sstevel@tonic-gate if (((sinfo->secno ==
5967c478bd9Sstevel@tonic-gate (GElf_Word)DELETED) ||
5977c478bd9Sstevel@tonic-gate (sinfo->secno ==
5987c478bd9Sstevel@tonic-gate (GElf_Word)NULLED)) &&
5997c478bd9Sstevel@tonic-gate sinfo->rel_loc != IN) {
6000d15df17Sab196087 if (GET_LOC(state->
6010d15df17Sab196087 sec_table[rel_idx].flags) == PRIOR)
6020d15df17Sab196087 state->sec_table[rel_idx].
6030d15df17Sab196087 secno = (GElf_Word)NULLED;
6047c478bd9Sstevel@tonic-gate else
6050d15df17Sab196087 state->sec_table[rel_idx].
6060d15df17Sab196087 secno = (GElf_Word)DELETED;
6070d15df17Sab196087 SET_ACTION(state->sec_table[rel_idx].
6080d15df17Sab196087 flags, ACT_DELETE);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate * I am not removed. Check if my target is
6137c478bd9Sstevel@tonic-gate * removed or nulled. If so, let me try to
6147c478bd9Sstevel@tonic-gate * remove my self.
6157c478bd9Sstevel@tonic-gate */
6160d15df17Sab196087 if (((state->sec_table[rel_idx].secno ==
6177c478bd9Sstevel@tonic-gate (GElf_Word)DELETED) ||
6180d15df17Sab196087 (state->sec_table[rel_idx].secno ==
6197c478bd9Sstevel@tonic-gate (GElf_Word)NULLED)) &&
6207c478bd9Sstevel@tonic-gate (GET_LOC(sinfo->flags) != IN)) {
6217c478bd9Sstevel@tonic-gate if (GET_LOC(sinfo->flags) ==
6227c478bd9Sstevel@tonic-gate PRIOR)
6237c478bd9Sstevel@tonic-gate sinfo->secno =
6247c478bd9Sstevel@tonic-gate (GElf_Word)NULLED;
6257c478bd9Sstevel@tonic-gate else
6267c478bd9Sstevel@tonic-gate sinfo->secno =
6277c478bd9Sstevel@tonic-gate (GElf_Word)DELETED;
6280d15df17Sab196087 SET_ACTION(sinfo->flags, ACT_DELETE);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * Now, take care of DELETED sections
6347c478bd9Sstevel@tonic-gate */
6350d15df17Sab196087 sinfo = &(state->sec_table[1]);
6367c478bd9Sstevel@tonic-gate for (i = 1; i < shnum; i++) {
6377c478bd9Sstevel@tonic-gate shdr = &(sinfo->shdr);
6387c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED) {
6397c478bd9Sstevel@tonic-gate acc++;
6407c478bd9Sstevel@tonic-gate /*
6410d15df17Sab196087 * The SHT_GROUP section which this
6420d15df17Sab196087 * section is a member may be able
6430d15df17Sab196087 * to be removed. See post_process().
6447c478bd9Sstevel@tonic-gate */
6457c478bd9Sstevel@tonic-gate if (shdr->sh_flags & SHF_GROUP)
6460d15df17Sab196087 cmd_info->flags |=
6470d15df17Sab196087 SHF_GROUP_DEL;
6487c478bd9Sstevel@tonic-gate } else {
6497c478bd9Sstevel@tonic-gate /*
6500d15df17Sab196087 * The data buffer of SHT_GROUP this
6510d15df17Sab196087 * section is a member needs to be
6520d15df17Sab196087 * updated. See post_process().
6537c478bd9Sstevel@tonic-gate */
6547c478bd9Sstevel@tonic-gate sinfo->secno -= acc;
6550d15df17Sab196087 if ((shdr->sh_flags & SHF_GROUP) &&
6560d15df17Sab196087 (acc != 0))
6570d15df17Sab196087 cmd_info->flags |=
6580d15df17Sab196087 SHF_GROUP_MOVE;
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate sinfo++;
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate /*
6667c478bd9Sstevel@tonic-gate * I know that the file has been modified.
6677c478bd9Sstevel@tonic-gate * A new file need to be created.
6687c478bd9Sstevel@tonic-gate */
6697c478bd9Sstevel@tonic-gate return (SUCCESS);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate static int
build_file(Elf * src_elf,GElf_Ehdr * src_ehdr,Cmd_Info * cmd_info,file_state_t * state)6730d15df17Sab196087 build_file(Elf *src_elf, GElf_Ehdr *src_ehdr, Cmd_Info *cmd_info,
6740d15df17Sab196087 file_state_t *state)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate Elf_Scn *src_scn;
6777c478bd9Sstevel@tonic-gate Elf_Scn *dst_scn;
6787c478bd9Sstevel@tonic-gate int new_sh_name = 0; /* to hold the offset for the new */
6797c478bd9Sstevel@tonic-gate /* section's name */
6807c478bd9Sstevel@tonic-gate Elf *dst_elf = 0;
6817c478bd9Sstevel@tonic-gate Elf_Data *elf_data;
6827c478bd9Sstevel@tonic-gate Elf_Data *data;
6837c478bd9Sstevel@tonic-gate int64_t scn_no, x;
6847c478bd9Sstevel@tonic-gate size_t no_of_symbols = 0;
6857c478bd9Sstevel@tonic-gate section_info_table *info;
6867c478bd9Sstevel@tonic-gate unsigned int c = 0;
6877c478bd9Sstevel@tonic-gate int fdtmp;
6887c478bd9Sstevel@tonic-gate GElf_Shdr src_shdr;
6897c478bd9Sstevel@tonic-gate GElf_Shdr dst_shdr;
6907c478bd9Sstevel@tonic-gate GElf_Ehdr dst_ehdr;
6917c478bd9Sstevel@tonic-gate GElf_Off new_offset = 0, r;
6927c478bd9Sstevel@tonic-gate size_t shnum, shstrndx;
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate
69562b628a6SAli Bahrami if (elf_getshdrnum(src_elf, &shnum) == -1) {
6960d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
6977c478bd9Sstevel@tonic-gate return (FAILURE);
6987c478bd9Sstevel@tonic-gate }
69962b628a6SAli Bahrami if (elf_getshdrstrndx(src_elf, &shstrndx) == -1) {
7000d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
7017c478bd9Sstevel@tonic-gate return (FAILURE);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
704d1477c77SAli Bahrami if ((fdtmp = open(elftmpfile.tmp_name, O_RDWR | O_TRUNC | O_CREAT,
7050d15df17Sab196087 (mode_t)0666)) == -1) {
7060d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
707d1477c77SAli Bahrami prog, elftmpfile.tmp_name);
7087c478bd9Sstevel@tonic-gate return (FAILURE);
7097c478bd9Sstevel@tonic-gate }
710d1477c77SAli Bahrami elftmpfile.tmp_unlink = 1;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate if ((dst_elf = elf_begin(fdtmp, ELF_C_WRITE, (Elf *) 0)) == NULL) {
7130d15df17Sab196087 error_message(READ_ERROR, LIBelf_ERROR, elf_errmsg(-1),
714d1477c77SAli Bahrami prog, elftmpfile.tmp_name);
7157c478bd9Sstevel@tonic-gate (void) close(fdtmp);
7167c478bd9Sstevel@tonic-gate return (FAILURE);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate if (gelf_newehdr(dst_elf, gelf_getclass(src_elf)) == NULL) {
7200d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
7217c478bd9Sstevel@tonic-gate return (FAILURE);
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate /* initialize dst_ehdr */
7257c478bd9Sstevel@tonic-gate (void) gelf_getehdr(dst_elf, &dst_ehdr);
7267c478bd9Sstevel@tonic-gate dst_ehdr = *src_ehdr;
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate /*
7292eec250aSab196087 * If we are removing the header string table section,
7302eec250aSab196087 * remove the reference to it from the ELF header.
7312eec250aSab196087 */
7322eec250aSab196087 if ((shstrndx != SHN_UNDEF) &&
7330d15df17Sab196087 (state->sec_table[shstrndx].secno == (GElf_Word)DELETED))
7342eec250aSab196087 dst_ehdr.e_shstrndx = SHN_UNDEF;
7352eec250aSab196087
7362eec250aSab196087 /*
7372eec250aSab196087 * flush the changes to the ehdr so the ident
7382eec250aSab196087 * array and header string table index are filled in.
7397c478bd9Sstevel@tonic-gate */
7407c478bd9Sstevel@tonic-gate (void) gelf_update_ehdr(dst_elf, &dst_ehdr);
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) {
7447c478bd9Sstevel@tonic-gate (void) elf_flagelf(dst_elf, ELF_C_SET, ELF_F_LAYOUT);
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate if (gelf_newphdr(dst_elf, src_ehdr->e_phnum) == NULL) {
7470d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR,
7480d15df17Sab196087 elf_errmsg(-1), prog);
7497c478bd9Sstevel@tonic-gate return (FAILURE);
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate for (x = 0; x < src_ehdr->e_phnum; ++x) {
7537c478bd9Sstevel@tonic-gate GElf_Phdr dst;
7547c478bd9Sstevel@tonic-gate GElf_Phdr src;
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate /* LINTED */
7577c478bd9Sstevel@tonic-gate (void) gelf_getphdr(src_elf, (int)x, &src);
7587c478bd9Sstevel@tonic-gate /* LINTED */
7597c478bd9Sstevel@tonic-gate (void) gelf_getphdr(dst_elf, (int)x, &dst);
7607c478bd9Sstevel@tonic-gate (void) memcpy(&dst, &src, sizeof (GElf_Phdr));
7617c478bd9Sstevel@tonic-gate /* LINTED */
7627c478bd9Sstevel@tonic-gate (void) gelf_update_phdr(dst_elf, (int)x, &dst);
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate
7650d15df17Sab196087 x = location(dst_ehdr.e_phoff, 0, src_elf, state);
7667c478bd9Sstevel@tonic-gate if (x == AFTER)
7677c478bd9Sstevel@tonic-gate new_offset = (GElf_Off)src_ehdr->e_ehsize;
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate scn_no = 1;
7710d15df17Sab196087 while ((src_scn = state->sec_table[scn_no].scn) != (Elf_Scn *) -1) {
7720d15df17Sab196087 info = &state->sec_table[scn_no];
7737c478bd9Sstevel@tonic-gate /* If section should be copied to new file NOW */
7747c478bd9Sstevel@tonic-gate if ((info->secno != (GElf_Word)DELETED) &&
7757c478bd9Sstevel@tonic-gate info->secno <= scn_no) {
7767c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
7777c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
7787c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
7797c478bd9Sstevel@tonic-gate return (FAILURE);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate (void) gelf_getshdr(dst_scn, &dst_shdr);
7827c478bd9Sstevel@tonic-gate (void) gelf_getshdr(info->scn, &src_shdr);
7837c478bd9Sstevel@tonic-gate (void) memcpy(&dst_shdr, &src_shdr, sizeof (GElf_Shdr));
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate /*
7867c478bd9Sstevel@tonic-gate * Update link and info fields
7877c478bd9Sstevel@tonic-gate * The sh_link field may have special values so
7887c478bd9Sstevel@tonic-gate * check them first.
7897c478bd9Sstevel@tonic-gate */
7907c478bd9Sstevel@tonic-gate if ((src_shdr.sh_link >= shnum) ||
7917c478bd9Sstevel@tonic-gate (src_shdr.sh_link == 0))
7927c478bd9Sstevel@tonic-gate dst_shdr.sh_link = src_shdr.sh_link;
7930d15df17Sab196087 else if ((int)state->sec_table[src_shdr.sh_link].secno <
7940d15df17Sab196087 0)
7957c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 0;
7967c478bd9Sstevel@tonic-gate else
7977c478bd9Sstevel@tonic-gate dst_shdr.sh_link =
7980d15df17Sab196087 state->sec_table[src_shdr.sh_link].secno;
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate if ((src_shdr.sh_type == SHT_REL) ||
8017c478bd9Sstevel@tonic-gate (src_shdr.sh_type == SHT_RELA)) {
8027c478bd9Sstevel@tonic-gate if ((src_shdr.sh_info >= shnum) ||
8030d15df17Sab196087 ((int)state->sec_table[src_shdr.
8047c478bd9Sstevel@tonic-gate sh_info].secno < 0))
8057c478bd9Sstevel@tonic-gate dst_shdr.sh_info = 0;
8067c478bd9Sstevel@tonic-gate else
8070d15df17Sab196087 dst_shdr.sh_info = state->
8087c478bd9Sstevel@tonic-gate sec_table[src_shdr.sh_info].secno;
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
8110d15df17Sab196087 data = state->sec_table[scn_no].data;
8127c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) {
8137c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
8147c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
8157c478bd9Sstevel@tonic-gate return (FAILURE);
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate *elf_data = *data;
8187c478bd9Sstevel@tonic-gate
8197a5d89c4Sab196087 /*
8207a5d89c4Sab196087 * SHT_{DYNSYM, SYMTAB} might need some change, as
8217a5d89c4Sab196087 * they may contain section symbols that reference
8227a5d89c4Sab196087 * removed sections. SHT_SUNW_LDYNSYM does not
8237a5d89c4Sab196087 * contain section symbols, and therefore does not
8247a5d89c4Sab196087 * have this issue.
8257a5d89c4Sab196087 */
8267c478bd9Sstevel@tonic-gate if (((src_shdr.sh_type == SHT_SYMTAB) ||
8277c478bd9Sstevel@tonic-gate (src_shdr.sh_type == SHT_DYNSYM)) &&
8287c478bd9Sstevel@tonic-gate src_shdr.sh_entsize != 0 &&
8297c478bd9Sstevel@tonic-gate (cmd_info->no_of_delete != 0 ||
8307c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled != 0)) {
8317c478bd9Sstevel@tonic-gate char *new_sym;
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate no_of_symbols = src_shdr.sh_size /
8347c478bd9Sstevel@tonic-gate src_shdr.sh_entsize;
8357c478bd9Sstevel@tonic-gate new_sym = malloc(no_of_symbols *
8367c478bd9Sstevel@tonic-gate src_shdr.sh_entsize);
8377c478bd9Sstevel@tonic-gate if (new_sym == NULL) {
8387c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR,
83957ef7aa9SRod Evans PLAIN_ERROR, NULL, prog);
8407c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /* CSTYLED */
8447c478bd9Sstevel@tonic-gate elf_data->d_buf = (void *) new_sym;
8457c478bd9Sstevel@tonic-gate for (c = 0; c < no_of_symbols; c++) {
8467c478bd9Sstevel@tonic-gate GElf_Sym csym;
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate (void) gelf_getsym(data, c, &csym);
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate if ((csym.st_shndx < SHN_LORESERVE) &&
8517c478bd9Sstevel@tonic-gate (csym.st_shndx != SHN_UNDEF)) {
8527c478bd9Sstevel@tonic-gate section_info_table *i;
8530d15df17Sab196087 i = &state->
8540d15df17Sab196087 sec_table[csym.st_shndx];
8557c478bd9Sstevel@tonic-gate if (((int)i->secno !=
8567c478bd9Sstevel@tonic-gate DELETED) &&
8570d15df17Sab196087 ((int)i->secno != NULLED)) {
8587c478bd9Sstevel@tonic-gate csym.st_shndx =
8597c478bd9Sstevel@tonic-gate i->secno;
8600d15df17Sab196087 } else {
8610d15df17Sab196087 /* BEGIN CSTYLED */
8627c478bd9Sstevel@tonic-gate if (src_shdr.sh_type ==
8630d15df17Sab196087 SHT_SYMTAB) {
8647c478bd9Sstevel@tonic-gate /*
8657c478bd9Sstevel@tonic-gate * The section which
8667c478bd9Sstevel@tonic-gate * this * symbol relates
8677c478bd9Sstevel@tonic-gate * to is removed.
8687c478bd9Sstevel@tonic-gate * There is no way to
8697c478bd9Sstevel@tonic-gate * specify this fact,
8707c478bd9Sstevel@tonic-gate * just change the shndx
8717c478bd9Sstevel@tonic-gate * to 1.
8727c478bd9Sstevel@tonic-gate */
8737c478bd9Sstevel@tonic-gate csym.st_shndx = 1;
8740d15df17Sab196087 } else {
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate * If this is in a
8777c478bd9Sstevel@tonic-gate * .dynsym, NULL it out.
8787c478bd9Sstevel@tonic-gate */
8797c478bd9Sstevel@tonic-gate csym.st_shndx = 0;
8807c478bd9Sstevel@tonic-gate csym.st_name = 0;
8817c478bd9Sstevel@tonic-gate csym.st_value = 0;
8827c478bd9Sstevel@tonic-gate csym.st_size = 0;
8837c478bd9Sstevel@tonic-gate csym.st_info = 0;
8847c478bd9Sstevel@tonic-gate csym.st_other = 0;
8857c478bd9Sstevel@tonic-gate csym.st_shndx = 0;
8867c478bd9Sstevel@tonic-gate }
8870d15df17Sab196087 /* END CSTYLED */
8887c478bd9Sstevel@tonic-gate }
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate (void) gelf_update_sym(elf_data, c,
8927c478bd9Sstevel@tonic-gate &csym);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate }
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate /* update SHT_SYMTAB_SHNDX */
8977c478bd9Sstevel@tonic-gate if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
8987c478bd9Sstevel@tonic-gate (src_shdr.sh_entsize != 0) &&
8997c478bd9Sstevel@tonic-gate ((cmd_info->no_of_delete != 0) ||
9007c478bd9Sstevel@tonic-gate (cmd_info->no_of_nulled != 0))) {
9017c478bd9Sstevel@tonic-gate GElf_Word *oldshndx;
9027c478bd9Sstevel@tonic-gate GElf_Word *newshndx;
9037c478bd9Sstevel@tonic-gate uint_t entcnt;
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate entcnt = src_shdr.sh_size /
9067c478bd9Sstevel@tonic-gate src_shdr.sh_entsize;
9077c478bd9Sstevel@tonic-gate oldshndx = data->d_buf;
9080d15df17Sab196087 newshndx = malloc(entcnt * src_shdr.sh_entsize);
9097c478bd9Sstevel@tonic-gate if (newshndx == NULL) {
9107c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR,
91157ef7aa9SRod Evans PLAIN_ERROR, NULL, prog);
9127c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate elf_data->d_buf = (void *)newshndx;
9157c478bd9Sstevel@tonic-gate for (c = 0; c < entcnt; c++) {
9167c478bd9Sstevel@tonic-gate if (oldshndx[c] != SHN_UNDEF) {
9177c478bd9Sstevel@tonic-gate section_info_table *i;
9180d15df17Sab196087 i = &state->
9190d15df17Sab196087 sec_table[oldshndx[c]];
9207c478bd9Sstevel@tonic-gate if (((int)i->secno !=
9217c478bd9Sstevel@tonic-gate DELETED) &&
9227c478bd9Sstevel@tonic-gate ((int)i->secno != NULLED))
9237c478bd9Sstevel@tonic-gate newshndx[c] = i->secno;
9247c478bd9Sstevel@tonic-gate else
9257c478bd9Sstevel@tonic-gate newshndx[c] =
9267c478bd9Sstevel@tonic-gate oldshndx[c];
9277c478bd9Sstevel@tonic-gate } else
9287c478bd9Sstevel@tonic-gate newshndx[c] =
9297c478bd9Sstevel@tonic-gate oldshndx[c];
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate * If the section is to be updated,
9357c478bd9Sstevel@tonic-gate * do so.
9367c478bd9Sstevel@tonic-gate */
9377c478bd9Sstevel@tonic-gate if (ISCANDIDATE(info->flags)) {
9387c478bd9Sstevel@tonic-gate if ((GET_LOC(info->flags) == PRIOR) &&
9397c478bd9Sstevel@tonic-gate (((int)info->secno == NULLED) ||
9407c478bd9Sstevel@tonic-gate ((int)info->secno == EXPANDED) ||
9417c478bd9Sstevel@tonic-gate ((int)info->secno == SHRUNK))) {
9427c478bd9Sstevel@tonic-gate /*
9437c478bd9Sstevel@tonic-gate * The section is updated,
9447c478bd9Sstevel@tonic-gate * but the position is not too
9457c478bd9Sstevel@tonic-gate * good. Need to NULL this out.
9467c478bd9Sstevel@tonic-gate */
9477c478bd9Sstevel@tonic-gate dst_shdr.sh_name = 0;
9487c478bd9Sstevel@tonic-gate dst_shdr.sh_type = SHT_PROGBITS;
9497c478bd9Sstevel@tonic-gate if ((int)info->secno != NULLED) {
9507c478bd9Sstevel@tonic-gate (cmd_info->no_of_moved)++;
9517c478bd9Sstevel@tonic-gate SET_MOVING(info->flags);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate } else {
9547c478bd9Sstevel@tonic-gate /*
9557c478bd9Sstevel@tonic-gate * The section is positioned AFTER,
9567c478bd9Sstevel@tonic-gate * or there are no segments.
9577c478bd9Sstevel@tonic-gate * It is safe to update this section.
9587c478bd9Sstevel@tonic-gate */
9590d15df17Sab196087 data = state->sec_table[scn_no].mdata;
9607c478bd9Sstevel@tonic-gate *elf_data = *data;
9617c478bd9Sstevel@tonic-gate dst_shdr.sh_size = elf_data->d_size;
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate /* add new section name to shstrtab? */
9650d15df17Sab196087 else if (!state->Sect_exists &&
9660d15df17Sab196087 (state->new_sec_string != NULL) &&
9677c478bd9Sstevel@tonic-gate (scn_no == shstrndx) &&
9687c478bd9Sstevel@tonic-gate (dst_shdr.sh_type == SHT_STRTAB) &&
9697c478bd9Sstevel@tonic-gate ((src_ehdr->e_phnum == 0) ||
9700d15df17Sab196087 ((x = scn_location(dst_scn, dst_elf, state))
9710d15df17Sab196087 != IN) ||
9727c478bd9Sstevel@tonic-gate (x != PRIOR))) {
9737c478bd9Sstevel@tonic-gate size_t sect_len;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate sect_len = strlen(SECT_NAME);
9767c478bd9Sstevel@tonic-gate if ((elf_data->d_buf =
9777c478bd9Sstevel@tonic-gate malloc((dst_shdr.sh_size +
9787c478bd9Sstevel@tonic-gate sect_len + 1))) == NULL) {
9797c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR,
98057ef7aa9SRod Evans PLAIN_ERROR, NULL, prog);
9817c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate /* put original data plus new data in section */
9847c478bd9Sstevel@tonic-gate (void) memcpy(elf_data->d_buf,
9857c478bd9Sstevel@tonic-gate data->d_buf, data->d_size);
9867c478bd9Sstevel@tonic-gate (void) memcpy(&((char *)elf_data->d_buf)
9870d15df17Sab196087 [data->d_size], SECT_NAME, sect_len + 1);
9887c478bd9Sstevel@tonic-gate /* LINTED */
9897c478bd9Sstevel@tonic-gate new_sh_name = (int)dst_shdr.sh_size;
9907c478bd9Sstevel@tonic-gate dst_shdr.sh_size += sect_len + 1;
9917c478bd9Sstevel@tonic-gate elf_data->d_size += sect_len + 1;
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate /*
9957c478bd9Sstevel@tonic-gate * Compute offsets.
9967c478bd9Sstevel@tonic-gate */
9977c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) {
9987c478bd9Sstevel@tonic-gate /*
9997c478bd9Sstevel@tonic-gate * Compute section offset.
10007c478bd9Sstevel@tonic-gate */
10010d15df17Sab196087 if (state->off_table[scn_no] == 0) {
10027c478bd9Sstevel@tonic-gate if (dst_shdr.sh_addralign != 0) {
10037c478bd9Sstevel@tonic-gate r = new_offset %
10047c478bd9Sstevel@tonic-gate dst_shdr.sh_addralign;
10057c478bd9Sstevel@tonic-gate if (r)
10067c478bd9Sstevel@tonic-gate new_offset +=
10070d15df17Sab196087 dst_shdr.
10080d15df17Sab196087 sh_addralign - r;
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset;
10117c478bd9Sstevel@tonic-gate elf_data->d_off = 0;
10127c478bd9Sstevel@tonic-gate } else {
10130d15df17Sab196087 if (state->nobits_table[scn_no] == 0)
10140d15df17Sab196087 new_offset =
10150d15df17Sab196087 state->off_table[scn_no];
10167c478bd9Sstevel@tonic-gate }
10170d15df17Sab196087 if (state->nobits_table[scn_no] == 0)
10187c478bd9Sstevel@tonic-gate new_offset += dst_shdr.sh_size;
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate
10212eec250aSab196087 /* flush changes */
10222eec250aSab196087 (void) gelf_update_shdr(dst_scn, &dst_shdr);
10232eec250aSab196087 }
10247c478bd9Sstevel@tonic-gate scn_no++;
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate /*
10287c478bd9Sstevel@tonic-gate * This is the real new section.
10297c478bd9Sstevel@tonic-gate */
10300d15df17Sab196087 if (!state->Sect_exists && state->new_sec_string != NULL) {
10317c478bd9Sstevel@tonic-gate size_t string_size;
10320d15df17Sab196087 string_size = strlen(state->new_sec_string) + 1;
10337c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
10347c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
10357c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
10367c478bd9Sstevel@tonic-gate return (FAILURE);
10377c478bd9Sstevel@tonic-gate }
10387c478bd9Sstevel@tonic-gate (void) gelf_getshdr(dst_scn, &dst_shdr);
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate dst_shdr.sh_name = new_sh_name;
10417c478bd9Sstevel@tonic-gate dst_shdr.sh_type = SHT_PROGBITS;
10427c478bd9Sstevel@tonic-gate dst_shdr.sh_flags = 0;
10437c478bd9Sstevel@tonic-gate dst_shdr.sh_addr = 0;
10447c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != NULL)
10457c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset;
10467c478bd9Sstevel@tonic-gate else
10477c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = 0;
10487c478bd9Sstevel@tonic-gate dst_shdr.sh_size = string_size + 1;
10497c478bd9Sstevel@tonic-gate dst_shdr.sh_link = 0;
10507c478bd9Sstevel@tonic-gate dst_shdr.sh_info = 0;
10517c478bd9Sstevel@tonic-gate dst_shdr.sh_addralign = 1;
10527c478bd9Sstevel@tonic-gate dst_shdr.sh_entsize = 0;
10537c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) {
10567c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
10577c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
10587c478bd9Sstevel@tonic-gate return (FAILURE);
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate elf_data->d_size = string_size + 1;
10617c478bd9Sstevel@tonic-gate if ((elf_data->d_buf = (char *)
10627c478bd9Sstevel@tonic-gate calloc(1, string_size + 1)) == NULL) {
10637c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR,
106457ef7aa9SRod Evans PLAIN_ERROR, NULL, prog);
10657c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate (void) memcpy(&((char *)elf_data->d_buf)[1],
10680d15df17Sab196087 state->new_sec_string, string_size);
10697c478bd9Sstevel@tonic-gate elf_data->d_align = 1;
10707c478bd9Sstevel@tonic-gate new_offset += string_size + 1;
10717c478bd9Sstevel@tonic-gate }
10727c478bd9Sstevel@tonic-gate
10737c478bd9Sstevel@tonic-gate /*
10747c478bd9Sstevel@tonic-gate * If there are sections which needed to be moved,
10757c478bd9Sstevel@tonic-gate * then do it here.
10767c478bd9Sstevel@tonic-gate */
10777c478bd9Sstevel@tonic-gate if (cmd_info->no_of_moved != 0) {
10787c478bd9Sstevel@tonic-gate int cnt;
10790d15df17Sab196087 info = &state->sec_table[0];
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < shnum; cnt++, info++) {
10827c478bd9Sstevel@tonic-gate if ((GET_MOVING(info->flags)) == 0)
10837c478bd9Sstevel@tonic-gate continue;
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate if ((src_scn = elf_getscn(src_elf, info->osecno)) ==
10867c478bd9Sstevel@tonic-gate NULL) {
10877c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
10887c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
10897c478bd9Sstevel@tonic-gate return (FAILURE);
10907c478bd9Sstevel@tonic-gate }
10917c478bd9Sstevel@tonic-gate if (gelf_getshdr(src_scn, &src_shdr) == NULL) {
10927c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
10937c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
10947c478bd9Sstevel@tonic-gate return (FAILURE);
10957c478bd9Sstevel@tonic-gate }
10967c478bd9Sstevel@tonic-gate if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
10977c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
10987c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
10997c478bd9Sstevel@tonic-gate return (FAILURE);
11007c478bd9Sstevel@tonic-gate }
11017c478bd9Sstevel@tonic-gate if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) {
11027c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
11037c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
11047c478bd9Sstevel@tonic-gate return (FAILURE);
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate dst_shdr = src_shdr;
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate data = info->mdata;
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate dst_shdr.sh_offset = new_offset; /* UPDATE fields */
11117c478bd9Sstevel@tonic-gate dst_shdr.sh_size = data->d_size;
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate if ((shnum >= src_shdr.sh_link) ||
11147c478bd9Sstevel@tonic-gate (src_shdr.sh_link == 0))
11157c478bd9Sstevel@tonic-gate dst_shdr.sh_link = src_shdr.sh_link;
11167c478bd9Sstevel@tonic-gate else
11177c478bd9Sstevel@tonic-gate dst_shdr.sh_link =
11180d15df17Sab196087 state->sec_table[src_shdr.sh_link].osecno;
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate if ((shnum >= src_shdr.sh_info) ||
11217c478bd9Sstevel@tonic-gate (src_shdr.sh_info == 0))
11227c478bd9Sstevel@tonic-gate dst_shdr.sh_info = src_shdr.sh_info;
11237c478bd9Sstevel@tonic-gate else
11247c478bd9Sstevel@tonic-gate dst_shdr.sh_info =
11250d15df17Sab196087 state->sec_table[src_shdr.sh_info].osecno;
11267c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(dst_scn, &dst_shdr);
11277c478bd9Sstevel@tonic-gate if ((elf_data = elf_newdata(dst_scn)) == NULL) {
11287c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
11297c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
11307c478bd9Sstevel@tonic-gate return (FAILURE);
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate (void) memcpy(elf_data, data, sizeof (Elf_Data));
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate new_offset += data->d_size;
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate /*
11397c478bd9Sstevel@tonic-gate * In the event that the position of the sting table has changed,
11407c478bd9Sstevel@tonic-gate * as a result of deleted sections, update the ehdr->e_shstrndx.
11417c478bd9Sstevel@tonic-gate */
11420bc07c75Srie if ((shstrndx > 0) && (shnum > 0) &&
11430d15df17Sab196087 (state->sec_table[shstrndx].secno < shnum)) {
11440d15df17Sab196087 if (state->sec_table[shstrndx].secno < SHN_LORESERVE) {
11457c478bd9Sstevel@tonic-gate dst_ehdr.e_shstrndx =
11460d15df17Sab196087 state->sec_table[dst_ehdr.e_shstrndx].secno;
11477c478bd9Sstevel@tonic-gate } else {
11487c478bd9Sstevel@tonic-gate Elf_Scn *_scn;
11497c478bd9Sstevel@tonic-gate GElf_Shdr shdr0;
11500bc07c75Srie
11517c478bd9Sstevel@tonic-gate /*
11527c478bd9Sstevel@tonic-gate * If shstrndx requires 'Extended ELF Sections'
11537c478bd9Sstevel@tonic-gate * then it is stored in shdr[0].sh_link
11547c478bd9Sstevel@tonic-gate */
11557c478bd9Sstevel@tonic-gate dst_ehdr.e_shstrndx = SHN_XINDEX;
11567c478bd9Sstevel@tonic-gate if ((_scn = elf_getscn(dst_elf, 0)) == NULL) {
11577c478bd9Sstevel@tonic-gate error_message(LIBELF_ERROR,
11587c478bd9Sstevel@tonic-gate LIBelf_ERROR, elf_errmsg(-1), prog);
11597c478bd9Sstevel@tonic-gate return (FAILURE);
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate (void) gelf_getshdr(_scn, &shdr0);
11620d15df17Sab196087 shdr0.sh_link = state->sec_table[shstrndx].secno;
11637c478bd9Sstevel@tonic-gate (void) gelf_update_shdr(_scn, &shdr0);
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate if (src_ehdr->e_phnum != 0) {
11687c478bd9Sstevel@tonic-gate size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT);
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate /* UPDATE location of program header table */
11710d15df17Sab196087 if (location(dst_ehdr.e_phoff, 0, dst_elf, state) == AFTER) {
11727c478bd9Sstevel@tonic-gate r = new_offset % align;
11737c478bd9Sstevel@tonic-gate if (r)
11747c478bd9Sstevel@tonic-gate new_offset += align - r;
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate dst_ehdr.e_phoff = new_offset;
11770d15df17Sab196087 new_offset += dst_ehdr.e_phnum * dst_ehdr.e_phentsize;
11787c478bd9Sstevel@tonic-gate }
11797c478bd9Sstevel@tonic-gate /* UPDATE location of section header table */
11800d15df17Sab196087 if ((location(dst_ehdr.e_shoff, 0, src_elf, state) == AFTER) ||
11810d15df17Sab196087 ((location(dst_ehdr.e_shoff, 0, src_elf, state) == PRIOR) &&
11820d15df17Sab196087 (!state->Sect_exists && state->new_sec_string != NULL))) {
11837c478bd9Sstevel@tonic-gate r = new_offset % align;
11847c478bd9Sstevel@tonic-gate if (r)
11857c478bd9Sstevel@tonic-gate new_offset += align - r;
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate dst_ehdr.e_shoff = new_offset;
11887c478bd9Sstevel@tonic-gate }
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate /*
11917c478bd9Sstevel@tonic-gate * The NOTE segment is the one segment whos
11927c478bd9Sstevel@tonic-gate * sections might get moved by mcs processing.
11937c478bd9Sstevel@tonic-gate * Make sure that the NOTE segments offset points
11947c478bd9Sstevel@tonic-gate * to the .note section.
11957c478bd9Sstevel@tonic-gate */
11960d15df17Sab196087 if ((state->notesegndx != -1) && (state->notesctndx != -1) &&
11970d15df17Sab196087 (state->sec_table[state->notesctndx].secno)) {
11987c478bd9Sstevel@tonic-gate Elf_Scn * notescn;
11997c478bd9Sstevel@tonic-gate GElf_Shdr nshdr;
12007c478bd9Sstevel@tonic-gate
12017c478bd9Sstevel@tonic-gate notescn = elf_getscn(dst_elf,
12020d15df17Sab196087 state->sec_table[state->notesctndx].secno);
12037c478bd9Sstevel@tonic-gate (void) gelf_getshdr(notescn, &nshdr);
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate if (gelf_getclass(dst_elf) == ELFCLASS32) {
12067c478bd9Sstevel@tonic-gate Elf32_Phdr * ph = elf32_getphdr(dst_elf) +
12070d15df17Sab196087 state->notesegndx;
12087c478bd9Sstevel@tonic-gate /* LINTED */
12097c478bd9Sstevel@tonic-gate ph->p_offset = (Elf32_Off)nshdr.sh_offset;
12107c478bd9Sstevel@tonic-gate } else {
12117c478bd9Sstevel@tonic-gate Elf64_Phdr * ph = elf64_getphdr(dst_elf) +
12120d15df17Sab196087 state->notesegndx;
12137c478bd9Sstevel@tonic-gate ph->p_offset = (Elf64_Off)nshdr.sh_offset;
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate /* copy ehdr changes back into real ehdr */
12197c478bd9Sstevel@tonic-gate (void) gelf_update_ehdr(dst_elf, &dst_ehdr);
12207c478bd9Sstevel@tonic-gate if (elf_update(dst_elf, ELF_C_WRITE) < 0) {
12210d15df17Sab196087 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
12227c478bd9Sstevel@tonic-gate return (FAILURE);
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate (void) elf_end(dst_elf);
12267c478bd9Sstevel@tonic-gate (void) close(fdtmp);
12277c478bd9Sstevel@tonic-gate return (SUCCESS);
12287c478bd9Sstevel@tonic-gate }
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gate /*
12317c478bd9Sstevel@tonic-gate * Search through PHT saving the beginning and ending segment offsets
12327c478bd9Sstevel@tonic-gate */
12337c478bd9Sstevel@tonic-gate static int
build_segment_table(Elf * elf,GElf_Ehdr * ehdr,file_state_t * state)12340d15df17Sab196087 build_segment_table(Elf * elf, GElf_Ehdr * ehdr, file_state_t *state)
12357c478bd9Sstevel@tonic-gate {
12367c478bd9Sstevel@tonic-gate unsigned int i;
12377c478bd9Sstevel@tonic-gate
12380d15df17Sab196087 state->b_e_seg_table = (Seg_Table *)
12390d15df17Sab196087 calloc(ehdr->e_phnum, sizeof (Seg_Table));
12400d15df17Sab196087 if (state->b_e_seg_table == NULL) {
124157ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
12427c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
12437c478bd9Sstevel@tonic-gate }
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr->e_phnum; i++) {
12467c478bd9Sstevel@tonic-gate GElf_Phdr ph;
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate (void) gelf_getphdr(elf, i, &ph);
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate /*
12517c478bd9Sstevel@tonic-gate * remember the note SEGMENTS index so that we can
12527c478bd9Sstevel@tonic-gate * re-set it's p_offset later if needed.
12537c478bd9Sstevel@tonic-gate */
12547c478bd9Sstevel@tonic-gate if (ph.p_type == PT_NOTE)
12550d15df17Sab196087 state->notesegndx = i;
12567c478bd9Sstevel@tonic-gate
12570d15df17Sab196087 state->b_e_seg_table[i].p_offset = ph.p_offset;
12580d15df17Sab196087 state->b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz;
12590d15df17Sab196087 state->b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz;
12607c478bd9Sstevel@tonic-gate }
12617c478bd9Sstevel@tonic-gate return (SUCCESS);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate static void
copy_elf_file_to_temp_ar_file(int fdartmp,Elf_Arhdr * mem_header,char * cur_file)12667c478bd9Sstevel@tonic-gate copy_elf_file_to_temp_ar_file(
12677c478bd9Sstevel@tonic-gate int fdartmp,
12687c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header,
12697c478bd9Sstevel@tonic-gate char *cur_file)
12707c478bd9Sstevel@tonic-gate {
12717c478bd9Sstevel@tonic-gate char *buf;
12727c478bd9Sstevel@tonic-gate char mem_header_buf[sizeof (struct ar_hdr) + 1];
12737c478bd9Sstevel@tonic-gate int fdtmp3;
12747c478bd9Sstevel@tonic-gate struct stat stbuf;
12757c478bd9Sstevel@tonic-gate
1276d1477c77SAli Bahrami if ((fdtmp3 = open(elftmpfile.tmp_name, O_RDONLY)) == -1) {
12770d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
1278d1477c77SAli Bahrami prog, elftmpfile.tmp_name);
12797c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
12807c478bd9Sstevel@tonic-gate }
12817c478bd9Sstevel@tonic-gate
1282d1477c77SAli Bahrami (void) stat(elftmpfile.tmp_name, &stbuf); /* for size of file */
12837c478bd9Sstevel@tonic-gate
12847c478bd9Sstevel@tonic-gate if ((buf =
12857c478bd9Sstevel@tonic-gate malloc(ROUNDUP(stbuf.st_size))) == NULL) {
128657ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
12877c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
12887c478bd9Sstevel@tonic-gate }
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) {
12910d15df17Sab196087 error_message(READ_MANI_ERROR, SYSTEM_ERROR, strerror(errno),
1292d1477c77SAli Bahrami prog, elftmpfile.tmp_name, cur_file);
12937c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
12947c478bd9Sstevel@tonic-gate }
12957c478bd9Sstevel@tonic-gate
12960d15df17Sab196087 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname,
12970d15df17Sab196087 mem_header->ar_date, (unsigned)mem_header->ar_uid,
12980d15df17Sab196087 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode,
12997c478bd9Sstevel@tonic-gate stbuf.st_size, ARFMAG);
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate if (write(fdartmp, mem_header_buf,
13027c478bd9Sstevel@tonic-gate (unsigned)sizeof (struct ar_hdr)) !=
13037c478bd9Sstevel@tonic-gate (unsigned)sizeof (struct ar_hdr)) {
13040d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, strerror(errno),
1305d1477c77SAli Bahrami prog, elftmpfile.tmp_name, cur_file);
13067c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate if (stbuf.st_size & 0x1) {
13107c478bd9Sstevel@tonic-gate buf[stbuf.st_size] = '\n';
13117c478bd9Sstevel@tonic-gate if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) !=
13127c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(stbuf.st_size)) {
13130d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1314d1477c77SAli Bahrami strerror(errno), prog, elftmpfile.tmp_name,
1315d1477c77SAli Bahrami cur_file);
13167c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13177c478bd9Sstevel@tonic-gate }
13187c478bd9Sstevel@tonic-gate } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) {
13190d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1320d1477c77SAli Bahrami strerror(errno), prog, elftmpfile.tmp_name,
1321d1477c77SAli Bahrami cur_file);
13227c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13237c478bd9Sstevel@tonic-gate }
13247c478bd9Sstevel@tonic-gate free(buf);
13257c478bd9Sstevel@tonic-gate (void) close(fdtmp3);
13267c478bd9Sstevel@tonic-gate }
13277c478bd9Sstevel@tonic-gate
13287c478bd9Sstevel@tonic-gate static void
copy_non_elf_to_temp_ar(int fd,Elf * elf,int fdartmp,Elf_Arhdr * mem_header,char * cur_file,Cmd_Info * cmd_info)13297c478bd9Sstevel@tonic-gate copy_non_elf_to_temp_ar(
13307c478bd9Sstevel@tonic-gate int fd,
13317c478bd9Sstevel@tonic-gate Elf *elf,
13327c478bd9Sstevel@tonic-gate int fdartmp,
13337c478bd9Sstevel@tonic-gate Elf_Arhdr *mem_header,
13347c478bd9Sstevel@tonic-gate char *cur_file,
13357c478bd9Sstevel@tonic-gate Cmd_Info *cmd_info)
13367c478bd9Sstevel@tonic-gate {
13377c478bd9Sstevel@tonic-gate char mem_header_buf[sizeof (struct ar_hdr) + 1];
13387c478bd9Sstevel@tonic-gate char *file_buf;
13397c478bd9Sstevel@tonic-gate
1340*ba7866cdSAli Bahrami if ((strcmp(mem_header->ar_name, "/") != 0) &&
1341*ba7866cdSAli Bahrami (strcmp(mem_header->ar_name, "/SYM64/") != 0)) {
13420d15df17Sab196087 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname,
13430d15df17Sab196087 mem_header->ar_date, (unsigned)mem_header->ar_uid,
13440d15df17Sab196087 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode,
13457c478bd9Sstevel@tonic-gate mem_header->ar_size, ARFMAG);
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) !=
13487c478bd9Sstevel@tonic-gate sizeof (struct ar_hdr)) {
13490d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
13500d15df17Sab196087 strerror(errno), prog, cur_file);
13517c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate if ((file_buf =
13547c478bd9Sstevel@tonic-gate malloc(ROUNDUP(mem_header->ar_size))) == NULL) {
135557ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
13567c478bd9Sstevel@tonic-gate prog);
13577c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) {
13610d15df17Sab196087 error_message(WRITE_MANI_ERROR, prog, cur_file);
13627c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13637c478bd9Sstevel@tonic-gate }
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate if (read(fd, file_buf,
13667c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) !=
13677c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) {
13680d15df17Sab196087 error_message(READ_MANI_ERROR, SYSTEM_ERROR,
13690d15df17Sab196087 strerror(errno), prog, cur_file);
13707c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate if (write(fdartmp,
13737c478bd9Sstevel@tonic-gate file_buf,
13747c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) !=
13757c478bd9Sstevel@tonic-gate (size_t)ROUNDUP(mem_header->ar_size)) {
13760d15df17Sab196087 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
13770d15df17Sab196087 strerror(errno), prog, cur_file);
13787c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
13797c478bd9Sstevel@tonic-gate }
13807c478bd9Sstevel@tonic-gate free(file_buf);
13817c478bd9Sstevel@tonic-gate } else if (CHK_OPT(cmd_info, MIGHT_CHG)) {
138257ef7aa9SRod Evans error_message(SYM_TAB_AR_ERROR, PLAIN_ERROR, NULL,
13837c478bd9Sstevel@tonic-gate prog, cur_file);
138457ef7aa9SRod Evans error_message(EXEC_AR_ERROR, PLAIN_ERROR, NULL, cur_file);
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate
1388d1477c77SAli Bahrami /*
1389d1477c77SAli Bahrami * Replace contents of file
1390d1477c77SAli Bahrami *
1391d1477c77SAli Bahrami * entry:
1392d1477c77SAli Bahrami * ofd - Open file descriptor for file fname
1393d1477c77SAli Bahrami * fname - Name of file being processed
1394d1477c77SAli Bahrami * temp_file_name - Address of pointer to temporary
1395d1477c77SAli Bahrami * file containing new contents for fname.
1396d1477c77SAli Bahrami *
1397d1477c77SAli Bahrami * exit:
1398d1477c77SAli Bahrami * The contents of the file given by temp_file->tmp_name are
1399d1477c77SAli Bahrami * copied to the file fname. The temporary file is
1400d1477c77SAli Bahrami * unlinked, and temp_file reset.
1401d1477c77SAli Bahrami */
14027c478bd9Sstevel@tonic-gate static void
copy_file(int ofd,char * fname,Tmp_File * temp_file)1403d1477c77SAli Bahrami copy_file(int ofd, char *fname, Tmp_File *temp_file)
14047c478bd9Sstevel@tonic-gate {
14050d15df17Sab196087 enum { MMAP_USED, MMAP_UNUSED } mmap_status;
14067c478bd9Sstevel@tonic-gate int i;
14077c478bd9Sstevel@tonic-gate int fdtmp2;
14087c478bd9Sstevel@tonic-gate struct stat stbuf;
14097c478bd9Sstevel@tonic-gate char *buf;
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */
14127c478bd9Sstevel@tonic-gate (void) signal(signum[i], SIG_IGN);
14137c478bd9Sstevel@tonic-gate
1414d1477c77SAli Bahrami if ((fdtmp2 = open(temp_file->tmp_name, O_RDONLY)) == -1) {
14150d15df17Sab196087 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
1416d1477c77SAli Bahrami prog, temp_file->tmp_name);
14177c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate
1420d1477c77SAli Bahrami (void) stat(temp_file->tmp_name, &stbuf); /* for size of file */
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate /*
14237c478bd9Sstevel@tonic-gate * Get the contents of the updated file.
14247c478bd9Sstevel@tonic-gate * First try mmap()'ing. If mmap() fails,
14257c478bd9Sstevel@tonic-gate * then use the malloc() and read().
14267c478bd9Sstevel@tonic-gate */
14270d15df17Sab196087 mmap_status = MMAP_USED;
14280d15df17Sab196087 buf = (char *)mmap(0, stbuf.st_size, PROT_READ, MAP_SHARED, fdtmp2, 0);
14290d15df17Sab196087 if (buf == (caddr_t)-1) {
14307c478bd9Sstevel@tonic-gate if ((buf =
14317c478bd9Sstevel@tonic-gate malloc(stbuf.st_size * sizeof (char))) == NULL) {
143257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
14337c478bd9Sstevel@tonic-gate prog);
14347c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) {
14380d15df17Sab196087 error_message(READ_SYS_ERROR, SYSTEM_ERROR,
1439d1477c77SAli Bahrami strerror(errno), prog, temp_file->tmp_name);
14407c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14417c478bd9Sstevel@tonic-gate }
14420d15df17Sab196087 mmap_status = MMAP_UNUSED;
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate if (ftruncate(ofd, 0) == -1) {
14460d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
14477c478bd9Sstevel@tonic-gate prog, fname);
14487c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate if (lseek(ofd, 0, SEEK_SET) == -1) {
14510d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
14527c478bd9Sstevel@tonic-gate prog, fname);
14537c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14547c478bd9Sstevel@tonic-gate }
14557c478bd9Sstevel@tonic-gate if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) {
14560d15df17Sab196087 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
14577c478bd9Sstevel@tonic-gate prog, fname);
14587c478bd9Sstevel@tonic-gate mcs_exit(FAILURE);
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate /*
14627c478bd9Sstevel@tonic-gate * clean
14637c478bd9Sstevel@tonic-gate */
14640d15df17Sab196087 if (mmap_status == MMAP_USED)
14657c478bd9Sstevel@tonic-gate (void) munmap(buf, stbuf.st_size);
14667c478bd9Sstevel@tonic-gate else
14677c478bd9Sstevel@tonic-gate free(buf);
14687c478bd9Sstevel@tonic-gate (void) close(fdtmp2);
1469d1477c77SAli Bahrami free_tempfile(temp_file);
14707c478bd9Sstevel@tonic-gate }
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate static uint64_t
location(int64_t offset,int mem_search,Elf * elf,file_state_t * state)14730d15df17Sab196087 location(int64_t offset, int mem_search, Elf * elf, file_state_t *state)
14747c478bd9Sstevel@tonic-gate {
14757c478bd9Sstevel@tonic-gate int i;
14767c478bd9Sstevel@tonic-gate uint64_t upper;
14777c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr;
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate (void) gelf_getehdr(elf, &ehdr);
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate for (i = 0; i < ehdr.e_phnum; i++) {
14827c478bd9Sstevel@tonic-gate if (mem_search)
14830d15df17Sab196087 upper = state->b_e_seg_table[i].p_memsz;
14847c478bd9Sstevel@tonic-gate else
14850d15df17Sab196087 upper = state->b_e_seg_table[i].p_filesz;
14860d15df17Sab196087 if ((offset >= state->b_e_seg_table[i].p_offset) &&
14877c478bd9Sstevel@tonic-gate (offset <= upper))
14887c478bd9Sstevel@tonic-gate return (IN);
14890d15df17Sab196087 else if (offset < state->b_e_seg_table[i].p_offset)
14907c478bd9Sstevel@tonic-gate return (PRIOR);
14917c478bd9Sstevel@tonic-gate }
14927c478bd9Sstevel@tonic-gate return (AFTER);
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate static uint64_t
scn_location(Elf_Scn * scn,Elf * elf,file_state_t * state)14960d15df17Sab196087 scn_location(Elf_Scn * scn, Elf * elf, file_state_t *state)
14977c478bd9Sstevel@tonic-gate {
14987c478bd9Sstevel@tonic-gate GElf_Shdr shdr;
14997c478bd9Sstevel@tonic-gate
15007c478bd9Sstevel@tonic-gate (void) gelf_getshdr(scn, &shdr);
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate /*
15037c478bd9Sstevel@tonic-gate * If the section is not a NOTE section and it has no
15047c478bd9Sstevel@tonic-gate * virtual address then it is not part of a mapped segment.
15057c478bd9Sstevel@tonic-gate */
15067c478bd9Sstevel@tonic-gate if (shdr.sh_addr == 0)
15070d15df17Sab196087 return (location(shdr.sh_offset + shdr.sh_size, 0, elf, state));
15087c478bd9Sstevel@tonic-gate
15090d15df17Sab196087 return (location(shdr.sh_offset + shdr.sh_size, 1, elf, state));
15107c478bd9Sstevel@tonic-gate }
15117c478bd9Sstevel@tonic-gate
15127c478bd9Sstevel@tonic-gate static void
initialize(int shnum,Cmd_Info * cmd_info,file_state_t * state)15130d15df17Sab196087 initialize(int shnum, Cmd_Info *cmd_info, file_state_t *state)
15147c478bd9Sstevel@tonic-gate {
15157c478bd9Sstevel@tonic-gate /*
15167c478bd9Sstevel@tonic-gate * Initialize command info
15177c478bd9Sstevel@tonic-gate */
15187c478bd9Sstevel@tonic-gate cmd_info->no_of_append = cmd_info->no_of_delete =
15197c478bd9Sstevel@tonic-gate cmd_info->no_of_nulled = cmd_info->no_of_compressed =
15207c478bd9Sstevel@tonic-gate cmd_info->no_of_moved = 0;
152157ef7aa9SRod Evans cmd_info->sh_groups = NULL;
15227c478bd9Sstevel@tonic-gate
15230d15df17Sab196087 state->sec_table = (section_info_table *)
15240d15df17Sab196087 calloc(shnum + 1, sizeof (section_info_table));
15250d15df17Sab196087 if (state->sec_table == NULL) {
152657ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1527d1477c77SAli Bahrami mcs_exit(FAILURE);
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate
15300d15df17Sab196087 state->off_table = (int64_t *)calloc(shnum, sizeof (int64_t));
15310d15df17Sab196087 if (state->off_table == NULL) {
153257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1533d1477c77SAli Bahrami mcs_exit(FAILURE);
15347c478bd9Sstevel@tonic-gate }
15357c478bd9Sstevel@tonic-gate
15360d15df17Sab196087 state->nobits_table = (int64_t *)calloc(shnum, sizeof (int64_t));
15370d15df17Sab196087 if (state->nobits_table == NULL) {
153857ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1539d1477c77SAli Bahrami mcs_exit(FAILURE);
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate }
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate /*
15447c478bd9Sstevel@tonic-gate * Update the contents of SHT_GROUP if needed
15457c478bd9Sstevel@tonic-gate */
15460d15df17Sab196087 static void
post_process(Cmd_Info * cmd_info,file_state_t * state)15470d15df17Sab196087 post_process(Cmd_Info *cmd_info, file_state_t *state)
15487c478bd9Sstevel@tonic-gate {
154957ef7aa9SRod Evans Aliste idx;
15507c478bd9Sstevel@tonic-gate section_info_table *sinfo;
15517c478bd9Sstevel@tonic-gate Word *grpdata, *ngrpdata;
15527c478bd9Sstevel@tonic-gate int64_t sno, sno2;
15537c478bd9Sstevel@tonic-gate Word i, j, num;
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate /*
15567c478bd9Sstevel@tonic-gate * If no change is required, then return.
15577c478bd9Sstevel@tonic-gate */
15587c478bd9Sstevel@tonic-gate if ((cmd_info->flags & (SHF_GROUP_MOVE|SHF_GROUP_DEL)) == 0)
15597c478bd9Sstevel@tonic-gate return;
15607c478bd9Sstevel@tonic-gate
15617c478bd9Sstevel@tonic-gate /*
15627c478bd9Sstevel@tonic-gate * If SHF_GROUP sections were removed, we might need to
15637c478bd9Sstevel@tonic-gate * remove SHT_GROUP sections.
15647c478bd9Sstevel@tonic-gate */
15657c478bd9Sstevel@tonic-gate if (cmd_info->flags & SHF_GROUP_DEL) {
15667c478bd9Sstevel@tonic-gate Word grpcnt;
15677c478bd9Sstevel@tonic-gate int deleted = 0;
15687c478bd9Sstevel@tonic-gate
156957ef7aa9SRod Evans for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) {
15707c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED)
15717c478bd9Sstevel@tonic-gate continue;
15727c478bd9Sstevel@tonic-gate num = (sinfo->shdr).sh_size/sizeof (Word);
15737c478bd9Sstevel@tonic-gate grpcnt = 0;
15747c478bd9Sstevel@tonic-gate grpdata = (Word *)(sinfo->data->d_buf);
15757c478bd9Sstevel@tonic-gate for (i = 1; i < num; i++) {
15760d15df17Sab196087 if (state->sec_table[grpdata[i]].secno !=
15775aefb655Srie (GElf_Word)DELETED)
15787c478bd9Sstevel@tonic-gate grpcnt++;
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate /*
15827c478bd9Sstevel@tonic-gate * All members in this SHT_GROUP were removed.
15837c478bd9Sstevel@tonic-gate * We can remove this SHT_GROUP.
15847c478bd9Sstevel@tonic-gate */
15857c478bd9Sstevel@tonic-gate if (grpcnt == 0) {
15867c478bd9Sstevel@tonic-gate sinfo->secno = (GElf_Word)DELETED;
15877c478bd9Sstevel@tonic-gate (cmd_info->no_of_delete)++;
15887c478bd9Sstevel@tonic-gate deleted = 1;
15897c478bd9Sstevel@tonic-gate }
15907c478bd9Sstevel@tonic-gate }
15917c478bd9Sstevel@tonic-gate
15927c478bd9Sstevel@tonic-gate /*
15937c478bd9Sstevel@tonic-gate * If we deleted a SHT_GROUP section,
15947c478bd9Sstevel@tonic-gate * we need to reasign section numbers.
15957c478bd9Sstevel@tonic-gate */
15967c478bd9Sstevel@tonic-gate if (deleted) {
15977c478bd9Sstevel@tonic-gate section_info_table *sinfo;
15987c478bd9Sstevel@tonic-gate
15997c478bd9Sstevel@tonic-gate sno = 1;
16007c478bd9Sstevel@tonic-gate sno2 = 1;
16010d15df17Sab196087 while (state->sec_table[sno].scn != (Elf_Scn *)-1) {
16020d15df17Sab196087 sinfo = &state->sec_table[sno];
16037c478bd9Sstevel@tonic-gate if (sinfo->secno != (GElf_Word) DELETED)
16047c478bd9Sstevel@tonic-gate sinfo->secno = sno2++;
16057c478bd9Sstevel@tonic-gate sno++;
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate }
16097c478bd9Sstevel@tonic-gate
16107c478bd9Sstevel@tonic-gate /*
161157ef7aa9SRod Evans * Now we can update data buffers of the SHT_GROUP sections.
16127c478bd9Sstevel@tonic-gate */
161357ef7aa9SRod Evans for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) {
16147c478bd9Sstevel@tonic-gate if (sinfo->secno == (GElf_Word)DELETED)
16157c478bd9Sstevel@tonic-gate continue;
16167c478bd9Sstevel@tonic-gate num = (sinfo->shdr).sh_size/sizeof (Word);
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate /*
16197c478bd9Sstevel@tonic-gate * Need to generate the updated data buffer
16207c478bd9Sstevel@tonic-gate */
16217c478bd9Sstevel@tonic-gate if ((sinfo->mdata = malloc(sizeof (Elf_Data))) == NULL) {
162257ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
16237c478bd9Sstevel@tonic-gate prog);
1624d1477c77SAli Bahrami mcs_exit(FAILURE);
16257c478bd9Sstevel@tonic-gate }
16267c478bd9Sstevel@tonic-gate *(sinfo->mdata) = *(sinfo->data);
16277c478bd9Sstevel@tonic-gate if ((ngrpdata = sinfo->mdata->d_buf =
16287c478bd9Sstevel@tonic-gate malloc(sinfo->data->d_size)) == NULL) {
162957ef7aa9SRod Evans error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
16307c478bd9Sstevel@tonic-gate prog);
1631d1477c77SAli Bahrami mcs_exit(FAILURE);
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate grpdata = (Word *)(sinfo->data->d_buf);
16357c478bd9Sstevel@tonic-gate ngrpdata[0] = grpdata[0];
16367c478bd9Sstevel@tonic-gate j = 1;
16377c478bd9Sstevel@tonic-gate for (i = 1; i < num; i++) {
16380d15df17Sab196087 if (state->sec_table[grpdata[i]].secno !=
16390d15df17Sab196087 (GElf_Word)DELETED) {
16400d15df17Sab196087 ngrpdata[j++] =
16410d15df17Sab196087 state->sec_table[grpdata[i]].secno;
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate }
16447c478bd9Sstevel@tonic-gate sinfo->mdata->d_size = j * sizeof (Word);
16457c478bd9Sstevel@tonic-gate sinfo->data = sinfo->mdata;
16467c478bd9Sstevel@tonic-gate }
164757ef7aa9SRod Evans free(cmd_info->sh_groups);
164857ef7aa9SRod Evans cmd_info->sh_groups = NULL;
16497c478bd9Sstevel@tonic-gate }
1650