dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / mcs / common / file.c
blobdd2fc367006cb325802f6e773498d9a44a7f34ac
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
26 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
29 #include <errno.h>
30 #include "alist.h"
31 #include "mcs.h"
32 #include "extern.h"
33 #include "gelf.h"
36 * Type used to pass state information for the current
37 * file between routines.
39 typedef struct {
40 int Sect_exists;
41 int notesegndx;
42 int notesctndx;
43 Seg_Table *b_e_seg_table;
44 section_info_table *sec_table;
45 int64_t *off_table; /* maintains section's offset; set to */
46 /* retain old offset, else 0 */
47 int64_t *nobits_table; /* maintains NOBITS sections */
48 char *new_sec_string;
49 } file_state_t;
53 * Function prototypes.
55 static void copy_file(int, char *, Tmp_File *);
56 static void
57 copy_non_elf_to_temp_ar(int, Elf *, int, Elf_Arhdr *, char *, Cmd_Info *);
58 static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *);
59 static int process_file(Elf *, char *, Cmd_Info *);
60 static void initialize(int shnum, Cmd_Info *, file_state_t *);
61 static int build_segment_table(Elf*, GElf_Ehdr *, file_state_t *);
62 static int traverse_file(Elf *, GElf_Ehdr *, char *, Cmd_Info *,
63 file_state_t *);
64 static uint64_t location(int64_t, int, Elf *, file_state_t *);
65 static uint64_t scn_location(Elf_Scn *, Elf *, file_state_t *);
66 static int build_file(Elf *, GElf_Ehdr *, Cmd_Info *, file_state_t *);
67 static void post_process(Cmd_Info *, file_state_t *);
71 int
72 each_file(char *cur_file, Cmd_Info *cmd_info)
74 Elf *elf = 0;
75 Elf_Cmd cmd;
76 Elf *arf = 0;
77 Elf_Arhdr *mem_header;
78 char *cur_filenm = NULL;
79 int code = 0;
80 int error = 0, err = 0;
81 int ar_file = 0;
82 int fdartmp;
83 int fd;
84 int oflag;
86 if (cmd_info->flags & MIGHT_CHG)
87 oflag = O_RDWR;
88 else
89 oflag = O_RDONLY;
91 if ((fd = open(cur_file, oflag)) == -1) {
92 error_message(OPEN_ERROR, SYSTEM_ERROR, strerror(errno),
93 prog, cur_file);
94 return (FAILURE);
98 * Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect.
99 * libelf does not allow elf_begin() with ELF_C_RDWR when processing
100 * archive file members. Because we are limited to ELF_C_READ use, any
101 * ELF data modification must be provided by updating a copy of
102 * the data, rather than updating the original file data.
104 cmd = ELF_C_READ;
105 if ((arf = elf_begin(fd, cmd, NULL)) == NULL) {
106 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
107 (void) elf_end(arf);
108 (void) close(fd); /* done processing this file */
109 return (FAILURE);
112 if ((elf_kind(arf) == ELF_K_AR)) {
113 ar_file = 1;
114 if (CHK_OPT(cmd_info, MIGHT_CHG)) {
115 artmpfile.tmp_name = tempnam(TMPDIR, "mcs2");
116 if ((fdartmp = open(artmpfile.tmp_name,
117 O_WRONLY | O_APPEND | O_CREAT,
118 (mode_t)0666)) == -1) {
119 error_message(OPEN_TEMP_ERROR,
120 SYSTEM_ERROR, strerror(errno),
121 prog, artmpfile);
122 (void) elf_end(arf);
123 (void) close(fd);
124 mcs_exit(FAILURE);
126 artmpfile.tmp_unlink = 1;
127 /* write magic string to artmpfile */
128 if ((write(fdartmp, ARMAG, SARMAG)) != SARMAG) {
129 error_message(WRITE_ERROR,
130 SYSTEM_ERROR, strerror(errno),
131 prog, artmpfile.tmp_name, cur_file);
132 mcs_exit(FAILURE);
135 } else {
136 ar_file = 0;
137 cur_filenm = cur_file;
141 * Holds temporary file;
142 * if archive, holds the current member file if it has an ehdr,
143 * and there were no errors in
144 * processing the object file.
146 elftmpfile.tmp_name = tempnam(TMPDIR, "mcs1");
148 while ((elf = elf_begin(fd, cmd, arf)) != 0) {
149 if (ar_file) /* get header info */ {
150 size_t len;
152 if ((mem_header = elf_getarhdr(elf)) == NULL) {
153 error_message(GETARHDR_ERROR, LIBelf_ERROR,
154 elf_errmsg(-1), prog, cur_file,
155 elf_getbase(elf));
156 (void) elf_end(elf);
157 (void) elf_end(arf);
158 (void) close(fd);
159 free_tempfile(&artmpfile);
160 return (FAILURE);
163 free(cur_filenm);
165 len = (strlen(cur_file) + 3 +
166 strlen(mem_header->ar_name));
168 if ((cur_filenm = malloc(len)) == NULL) {
169 error_message(MALLOC_ERROR,
170 PLAIN_ERROR, NULL, prog);
171 mcs_exit(FAILURE);
174 (void) snprintf(cur_filenm, len, "%s[%s]",
175 cur_file, mem_header->ar_name);
178 if (elf_kind(elf) == ELF_K_ELF) {
179 if ((code = process_file(elf, cur_filenm, cmd_info)) ==
180 FAILURE) {
181 if (!ar_file) {
182 (void) elf_end(arf);
183 (void) elf_end(elf);
184 (void) close(fd);
185 return (FAILURE);
186 } else {
187 copy_non_elf_to_temp_ar(fd, elf,
188 fdartmp, mem_header,
189 cur_file, cmd_info);
190 error++;
192 } else if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
193 if (code == DONT_BUILD)
194 copy_non_elf_to_temp_ar(fd, elf,
195 fdartmp, mem_header,
196 cur_file, cmd_info);
197 else
198 copy_elf_file_to_temp_ar_file(
199 fdartmp, mem_header, cur_file);
201 } else {
203 * decide what to do with non-ELF file
205 if (!ar_file) {
206 error_message(FILE_TYPE_ERROR, PLAIN_ERROR,
207 NULL, prog, cur_filenm);
208 (void) close(fd);
209 return (FAILURE);
210 } else {
211 if (CHK_OPT(cmd_info, MIGHT_CHG))
212 copy_non_elf_to_temp_ar(fd, elf,
213 fdartmp, mem_header,
214 cur_file, cmd_info);
217 cmd = elf_next(elf);
218 (void) elf_end(elf);
221 err = elf_errno();
222 if (err != 0) {
223 error_message(LIBELF_ERROR, LIBelf_ERROR,
224 elf_errmsg(err), prog);
225 error_message(NOT_MANIPULATED_ERROR, PLAIN_ERROR, NULL,
226 prog, cur_file);
227 return (FAILURE);
230 (void) elf_end(arf);
232 if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
233 (void) close(fdartmp); /* done writing to ar_temp_file */
234 /* copy ar_temp_file to FILE */
235 copy_file(fd, cur_file, &artmpfile);
236 } else if (code != DONT_BUILD && CHK_OPT(cmd_info, MIGHT_CHG))
237 copy_file(fd, cur_file, &elftmpfile);
238 (void) close(fd); /* done processing this file */
239 return (error);
242 static int
243 process_file(Elf *elf, char *cur_file, Cmd_Info *cmd_info)
245 int error = SUCCESS;
246 int x;
247 GElf_Ehdr ehdr;
248 size_t shnum;
249 file_state_t state;
252 * Initialize
254 if (gelf_getehdr(elf, &ehdr) == NULL) {
255 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
256 return (FAILURE);
259 if (elf_getshdrnum(elf, &shnum) == -1) {
260 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
261 return (FAILURE);
264 /* Initialize per-file state */
265 state.Sect_exists = 0;
266 state.notesegndx = -1;
267 state.notesctndx = -1;
268 state.b_e_seg_table = NULL;
269 state.sec_table = NULL;
270 state.off_table = 0;
271 state.nobits_table = NULL;
272 state.new_sec_string = NULL;
274 initialize(shnum, cmd_info, &state);
276 if ((ehdr.e_phnum != 0) &&
277 (build_segment_table(elf, &ehdr, &state) == FAILURE)) {
278 x = error = FAILURE;
279 } else if ((x = traverse_file(elf, &ehdr, cur_file,
280 cmd_info, &state)) == FAILURE) {
281 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR, NULL,
282 prog, cur_file);
283 error = FAILURE;
284 } else if (x != DONT_BUILD && x != FAILURE) {
285 post_process(cmd_info, &state);
286 if (build_file(elf, &ehdr, cmd_info, &state) == FAILURE) {
287 error_message(WRN_MANIPULATED_ERROR, PLAIN_ERROR,
288 NULL, prog, cur_file);
289 error = FAILURE;
293 /* Release any dynamicaly allocated buffers */
294 free(state.b_e_seg_table);
295 free(state.sec_table);
296 free(state.off_table);
297 free(state.nobits_table);
298 free(state.new_sec_string);
300 if (x == DONT_BUILD)
301 return (DONT_BUILD);
302 else
303 return (error);
306 static int
307 traverse_file(Elf *elf, GElf_Ehdr * ehdr, char *cur_file, Cmd_Info *cmd_info,
308 file_state_t *state)
310 Elf_Scn * scn;
311 Elf_Scn * temp_scn;
312 Elf_Data * data;
313 GElf_Shdr * shdr;
314 char *temp_name;
315 section_info_table * sinfo;
316 GElf_Xword x;
317 int ret = 0, SYM = 0; /* used by strip command */
318 int phnum = ehdr->e_phnum;
319 unsigned int i, scn_index;
320 size_t shstrndx, shnum;
322 state->Sect_exists = 0;
324 if (elf_getshdrnum(elf, &shnum) == -1) {
325 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
326 return (FAILURE);
328 if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
329 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
330 return (FAILURE);
333 scn = 0;
334 scn_index = 1;
335 sinfo = &state->sec_table[scn_index];
336 while ((scn = elf_nextscn(elf, scn)) != 0) {
337 char *name;
339 shdr = &(sinfo->shdr);
340 if (gelf_getshdr(scn, shdr) == NULL) {
341 error_message(NO_SECT_TABLE_ERROR,
342 LIBelf_ERROR, elf_errmsg(-1), prog, cur_file);
343 return (FAILURE);
347 * Note: If the object has problems, name
348 * may be set to NULL by the following.
350 name = elf_strptr(elf, shstrndx, (size_t)shdr->sh_name);
352 sinfo->scn = scn;
353 sinfo->secno = scn_index;
354 sinfo->osecno = scn_index;
355 SET_ACTION(sinfo->flags, ACT_NOP);
356 sinfo->name = name;
357 if (ehdr->e_phnum == 0)
358 SET_LOC(sinfo->flags, NOSEG);
359 else
360 SET_LOC(sinfo->flags, scn_location(scn, elf, state));
362 if (shdr->sh_type == SHT_GROUP) {
363 if (aplist_append(&cmd_info->sh_groups,
364 sinfo, 10) == NULL) {
365 error_message(MALLOC_ERROR, PLAIN_ERROR,
366 NULL, prog);
367 mcs_exit(FAILURE);
372 * If the target section is pointed by a section
373 * holding relocation infomation, then the
374 * pointing section would be useless if the
375 * target section is removed.
377 if ((shdr->sh_type == SHT_REL ||
378 shdr->sh_type == SHT_RELA) &&
379 (shdr->sh_info != SHN_UNDEF &&
380 (temp_scn = elf_getscn(elf, shdr->sh_info)) != 0)) {
381 GElf_Shdr tmp_shdr;
382 if (gelf_getshdr(temp_scn, &tmp_shdr) != NULL) {
383 temp_name = elf_strptr(elf, shstrndx,
384 (size_t)tmp_shdr.sh_name);
385 sinfo->rel_name = temp_name;
386 sinfo->rel_scn_index =
387 shdr->sh_info;
388 if (phnum == 0)
389 sinfo->rel_loc = NOSEG;
390 else
391 sinfo->rel_loc =
392 scn_location(temp_scn, elf, state);
395 data = 0;
396 if ((data = elf_getdata(scn, data)) == NULL) {
397 error_message(LIBELF_ERROR,
398 LIBelf_ERROR, elf_errmsg(-1), prog);
399 return (FAILURE);
401 sinfo->data = data;
404 * Check if this section is a candidate for
405 * action to be processes.
407 if ((name != NULL) && (sectcmp(name) == 0)) {
408 SET_CANDIDATE(sinfo->flags);
411 * This flag just shows that there was a
412 * candidate.
414 state->Sect_exists++;
418 * Any of the following section types should
419 * also be removed (if possible) if invoked via
420 * the 'strip' command.
422 if (CHK_OPT(cmd_info, I_AM_STRIP) &&
423 ((shdr->sh_type == SHT_SUNW_DEBUG) ||
424 (shdr->sh_type == SHT_SUNW_DEBUGSTR))) {
425 SET_CANDIDATE(sinfo->flags);
426 state->Sect_exists++;
431 * Zap this file ?
433 if ((cmd_info->flags & zFLAG) &&
434 (shdr->sh_type == SHT_PROGBITS)) {
435 SET_CANDIDATE(sinfo->flags);
436 state->Sect_exists++;
438 x = GET_LOC(sinfo->flags);
441 * Remember the note section index so that we can
442 * reset the NOTE segment offset to point to it. Depending
443 * on the operation being carried out, the note section may
444 * be assigned a new location in the resulting ELF
445 * image, and the program header needs to reflect that.
447 * There can be multiple contiguous note sections in
448 * an object, referenced by a single NOTE segment. We
449 * want to be sure and remember the one referenced by
450 * the program header, and not one of the others.
452 if ((shdr->sh_type == SHT_NOTE) && (state->notesctndx == -1) &&
453 (state->notesegndx != -1) &&
454 (state->b_e_seg_table[state->notesegndx].p_offset
455 == shdr->sh_offset))
456 state->notesctndx = scn_index;
458 if (x == IN || x == PRIOR)
459 state->off_table[scn_index] = shdr->sh_offset;
460 if (shdr->sh_type == SHT_NOBITS)
461 state->nobits_table[scn_index] = 1;
464 * If this section satisfies the condition,
465 * apply the actions specified.
467 if (ISCANDIDATE(sinfo->flags)) {
468 ret += apply_action(sinfo, cur_file, cmd_info);
472 * If I am strip command, determine if symtab can go or not.
474 if (CHK_OPT(cmd_info, I_AM_STRIP) &&
475 (CHK_OPT(cmd_info, xFLAG) == 0) &&
476 (CHK_OPT(cmd_info, lFLAG) == 0)) {
477 if (shdr->sh_type == SHT_SYMTAB &&
478 GET_LOC(sinfo->flags) == AFTER) {
479 SYM = scn_index;
482 scn_index++;
483 sinfo++;
485 sinfo->scn = (Elf_Scn *) -1;
488 * If there were any errors traversing the file,
489 * just return error.
491 if (ret != 0)
492 return (FAILURE);
495 * Remove symbol table if possible
497 if (CHK_OPT(cmd_info, I_AM_STRIP) && SYM != 0) {
498 GElf_Shdr tmp_shdr;
500 (void) gelf_getshdr(state->sec_table[SYM].scn, &tmp_shdr);
501 state->sec_table[SYM].secno = (GElf_Word)DELETED;
502 ++(cmd_info->no_of_nulled);
503 if (state->Sect_exists == 0)
504 ++state->Sect_exists;
505 SET_ACTION(state->sec_table[SYM].flags, ACT_DELETE);
506 state->off_table[SYM] = 0;
508 * Can I remove section header
509 * string table ?
511 if ((tmp_shdr.sh_link < shnum) &&
512 (tmp_shdr.sh_link != SHN_UNDEF) &&
513 (tmp_shdr.sh_link != shstrndx) &&
514 (GET_LOC(state->sec_table[tmp_shdr.sh_link].flags) ==
515 AFTER)) {
516 state->sec_table[tmp_shdr.sh_link].secno =
517 (GElf_Word)DELETED;
518 ++(cmd_info->no_of_nulled);
519 if (state->Sect_exists == 0)
520 ++state->Sect_exists;
521 SET_ACTION(state->sec_table[tmp_shdr.sh_link].flags,
522 ACT_DELETE);
523 state->off_table[tmp_shdr.sh_link] = 0;
528 * If I only printed the contents, then
529 * just report so.
531 if (CHK_OPT(cmd_info, pFLAG) && !CHK_OPT(cmd_info, MIGHT_CHG))
532 return (DONT_BUILD); /* don't bother creating a new file */
533 /* since the file has not changed */
536 * I might need to add a new section. Check it.
538 if (state->Sect_exists == 0 && CHK_OPT(cmd_info, aFLAG)) {
539 int act = 0;
540 state->new_sec_string = calloc(1, cmd_info->str_size + 1);
541 if (state->new_sec_string == NULL)
542 return (FAILURE);
543 for (act = 0; act < actmax; act++) {
544 if (Action[act].a_action == ACT_APPEND) {
545 (void) strcat(state->new_sec_string,
546 Action[act].a_string);
547 (void) strcat(state->new_sec_string, "\n");
548 cmd_info->no_of_append = 1;
554 * If I did not append any new sections, and I did not
555 * modify/delete any sections, then just report so.
557 if ((state->Sect_exists == 0 && cmd_info->no_of_append == 0) ||
558 !CHK_OPT(cmd_info, MIGHT_CHG))
559 return (DONT_BUILD);
562 * Found at least one section which was processed.
563 * Deleted or Appended or Compressed.
565 if (state->Sect_exists) {
567 * First, handle the deleted sections.
569 if (cmd_info->no_of_delete != 0 ||
570 cmd_info->no_of_nulled != 0) {
571 int acc = 0;
572 int rel_idx;
575 * Handle relocation/target
576 * sections.
578 sinfo = &(state->sec_table[0]);
579 for (i = 1; i < shnum; i++) {
580 sinfo++;
581 rel_idx = sinfo->rel_scn_index;
582 if (rel_idx == 0)
583 continue;
586 * If I am removed, then remove my
587 * target section.
589 if (((sinfo->secno ==
590 (GElf_Word)DELETED) ||
591 (sinfo->secno ==
592 (GElf_Word)NULLED)) &&
593 sinfo->rel_loc != IN) {
594 if (GET_LOC(state->
595 sec_table[rel_idx].flags) == PRIOR)
596 state->sec_table[rel_idx].
597 secno = (GElf_Word)NULLED;
598 else
599 state->sec_table[rel_idx].
600 secno = (GElf_Word)DELETED;
601 SET_ACTION(state->sec_table[rel_idx].
602 flags, ACT_DELETE);
606 * I am not removed. Check if my target is
607 * removed or nulled. If so, let me try to
608 * remove my self.
610 if (((state->sec_table[rel_idx].secno ==
611 (GElf_Word)DELETED) ||
612 (state->sec_table[rel_idx].secno ==
613 (GElf_Word)NULLED)) &&
614 (GET_LOC(sinfo->flags) != IN)) {
615 if (GET_LOC(sinfo->flags) ==
616 PRIOR)
617 sinfo->secno =
618 (GElf_Word)NULLED;
619 else
620 sinfo->secno =
621 (GElf_Word)DELETED;
622 SET_ACTION(sinfo->flags, ACT_DELETE);
627 * Now, take care of DELETED sections
629 sinfo = &(state->sec_table[1]);
630 for (i = 1; i < shnum; i++) {
631 shdr = &(sinfo->shdr);
632 if (sinfo->secno == (GElf_Word)DELETED) {
633 acc++;
635 * The SHT_GROUP section which this
636 * section is a member may be able
637 * to be removed. See post_process().
639 if (shdr->sh_flags & SHF_GROUP)
640 cmd_info->flags |=
641 SHF_GROUP_DEL;
642 } else {
644 * The data buffer of SHT_GROUP this
645 * section is a member needs to be
646 * updated. See post_process().
648 sinfo->secno -= acc;
649 if ((shdr->sh_flags & SHF_GROUP) &&
650 (acc != 0))
651 cmd_info->flags |=
652 SHF_GROUP_MOVE;
654 sinfo++;
660 * I know that the file has been modified.
661 * A new file need to be created.
663 return (SUCCESS);
666 static int
667 build_file(Elf *src_elf, GElf_Ehdr *src_ehdr, Cmd_Info *cmd_info,
668 file_state_t *state)
670 Elf_Scn *src_scn;
671 Elf_Scn *dst_scn;
672 int new_sh_name = 0; /* to hold the offset for the new */
673 /* section's name */
674 Elf *dst_elf = 0;
675 Elf_Data *elf_data;
676 Elf_Data *data;
677 int64_t scn_no, x;
678 size_t no_of_symbols = 0;
679 section_info_table *info;
680 unsigned int c = 0;
681 int fdtmp;
682 GElf_Shdr src_shdr;
683 GElf_Shdr dst_shdr;
684 GElf_Ehdr dst_ehdr;
685 GElf_Off new_offset = 0, r;
686 size_t shnum, shstrndx;
689 if (elf_getshdrnum(src_elf, &shnum) == -1) {
690 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
691 return (FAILURE);
693 if (elf_getshdrstrndx(src_elf, &shstrndx) == -1) {
694 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
695 return (FAILURE);
698 if ((fdtmp = open(elftmpfile.tmp_name, O_RDWR | O_TRUNC | O_CREAT,
699 (mode_t)0666)) == -1) {
700 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
701 prog, elftmpfile.tmp_name);
702 return (FAILURE);
704 elftmpfile.tmp_unlink = 1;
706 if ((dst_elf = elf_begin(fdtmp, ELF_C_WRITE, (Elf *) 0)) == NULL) {
707 error_message(READ_ERROR, LIBelf_ERROR, elf_errmsg(-1),
708 prog, elftmpfile.tmp_name);
709 (void) close(fdtmp);
710 return (FAILURE);
713 if (gelf_newehdr(dst_elf, gelf_getclass(src_elf)) == 0) {
714 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
715 return (FAILURE);
718 /* initialize dst_ehdr */
719 (void) gelf_getehdr(dst_elf, &dst_ehdr);
720 dst_ehdr = *src_ehdr;
723 * If we are removing the header string table section,
724 * remove the reference to it from the ELF header.
726 if ((shstrndx != SHN_UNDEF) &&
727 (state->sec_table[shstrndx].secno == (GElf_Word)DELETED))
728 dst_ehdr.e_shstrndx = SHN_UNDEF;
731 * flush the changes to the ehdr so the ident
732 * array and header string table index are filled in.
734 (void) gelf_update_ehdr(dst_elf, &dst_ehdr);
737 if (src_ehdr->e_phnum != 0) {
738 (void) elf_flagelf(dst_elf, ELF_C_SET, ELF_F_LAYOUT);
740 if (gelf_newphdr(dst_elf, src_ehdr->e_phnum) == 0) {
741 error_message(LIBELF_ERROR, LIBelf_ERROR,
742 elf_errmsg(-1), prog);
743 return (FAILURE);
746 for (x = 0; x < src_ehdr->e_phnum; ++x) {
747 GElf_Phdr dst;
748 GElf_Phdr src;
750 /* LINTED */
751 (void) gelf_getphdr(src_elf, (int)x, &src);
752 /* LINTED */
753 (void) gelf_getphdr(dst_elf, (int)x, &dst);
754 (void) memcpy(&dst, &src, sizeof (GElf_Phdr));
755 /* LINTED */
756 (void) gelf_update_phdr(dst_elf, (int)x, &dst);
759 x = location(dst_ehdr.e_phoff, 0, src_elf, state);
760 if (x == AFTER)
761 new_offset = (GElf_Off)src_ehdr->e_ehsize;
764 scn_no = 1;
765 while ((src_scn = state->sec_table[scn_no].scn) != (Elf_Scn *) -1) {
766 info = &state->sec_table[scn_no];
767 /* If section should be copied to new file NOW */
768 if ((info->secno != (GElf_Word)DELETED) &&
769 info->secno <= scn_no) {
770 if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
771 error_message(LIBELF_ERROR,
772 LIBelf_ERROR, elf_errmsg(-1), prog);
773 return (FAILURE);
775 (void) gelf_getshdr(dst_scn, &dst_shdr);
776 (void) gelf_getshdr(info->scn, &src_shdr);
777 (void) memcpy(&dst_shdr, &src_shdr, sizeof (GElf_Shdr));
780 * Update link and info fields
781 * The sh_link field may have special values so
782 * check them first.
784 if ((src_shdr.sh_link >= shnum) ||
785 (src_shdr.sh_link == 0))
786 dst_shdr.sh_link = src_shdr.sh_link;
787 else if ((int)state->sec_table[src_shdr.sh_link].secno <
789 dst_shdr.sh_link = 0;
790 else
791 dst_shdr.sh_link =
792 state->sec_table[src_shdr.sh_link].secno;
794 if ((src_shdr.sh_type == SHT_REL) ||
795 (src_shdr.sh_type == SHT_RELA)) {
796 if ((src_shdr.sh_info >= shnum) ||
797 ((int)state->sec_table[src_shdr.
798 sh_info].secno < 0))
799 dst_shdr.sh_info = 0;
800 else
801 dst_shdr.sh_info = state->
802 sec_table[src_shdr.sh_info].secno;
805 data = state->sec_table[scn_no].data;
806 if ((elf_data = elf_newdata(dst_scn)) == NULL) {
807 error_message(LIBELF_ERROR,
808 LIBelf_ERROR, elf_errmsg(-1), prog);
809 return (FAILURE);
811 *elf_data = *data;
814 * SHT_{DYNSYM, SYMTAB} might need some change, as
815 * they may contain section symbols that reference
816 * removed sections. SHT_SUNW_LDYNSYM does not
817 * contain section symbols, and therefore does not
818 * have this issue.
820 if (((src_shdr.sh_type == SHT_SYMTAB) ||
821 (src_shdr.sh_type == SHT_DYNSYM)) &&
822 src_shdr.sh_entsize != 0 &&
823 (cmd_info->no_of_delete != 0 ||
824 cmd_info->no_of_nulled != 0)) {
825 char *new_sym;
827 no_of_symbols = src_shdr.sh_size /
828 src_shdr.sh_entsize;
829 new_sym = malloc(no_of_symbols *
830 src_shdr.sh_entsize);
831 if (new_sym == NULL) {
832 error_message(MALLOC_ERROR,
833 PLAIN_ERROR, NULL, prog);
834 mcs_exit(FAILURE);
837 /* CSTYLED */
838 elf_data->d_buf = (void *) new_sym;
839 for (c = 0; c < no_of_symbols; c++) {
840 GElf_Sym csym;
842 (void) gelf_getsym(data, c, &csym);
844 if ((csym.st_shndx < SHN_LORESERVE) &&
845 (csym.st_shndx != SHN_UNDEF)) {
846 section_info_table *i;
847 i = &state->
848 sec_table[csym.st_shndx];
849 if (((int)i->secno !=
850 DELETED) &&
851 ((int)i->secno != NULLED)) {
852 csym.st_shndx =
853 i->secno;
854 } else {
855 /* BEGIN CSTYLED */
856 if (src_shdr.sh_type ==
857 SHT_SYMTAB) {
859 * The section which
860 * this * symbol relates
861 * to is removed.
862 * There is no way to
863 * specify this fact,
864 * just change the shndx
865 * to 1.
867 csym.st_shndx = 1;
868 } else {
870 * If this is in a
871 * .dynsym, NULL it out.
873 csym.st_shndx = 0;
874 csym.st_name = 0;
875 csym.st_value = 0;
876 csym.st_size = 0;
877 csym.st_info = 0;
878 csym.st_other = 0;
879 csym.st_shndx = 0;
881 /* END CSTYLED */
885 (void) gelf_update_sym(elf_data, c,
886 &csym);
890 /* update SHT_SYMTAB_SHNDX */
891 if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) &&
892 (src_shdr.sh_entsize != 0) &&
893 ((cmd_info->no_of_delete != 0) ||
894 (cmd_info->no_of_nulled != 0))) {
895 GElf_Word *oldshndx;
896 GElf_Word *newshndx;
897 uint_t entcnt;
899 entcnt = src_shdr.sh_size /
900 src_shdr.sh_entsize;
901 oldshndx = data->d_buf;
902 newshndx = malloc(entcnt * src_shdr.sh_entsize);
903 if (newshndx == NULL) {
904 error_message(MALLOC_ERROR,
905 PLAIN_ERROR, NULL, prog);
906 mcs_exit(FAILURE);
908 elf_data->d_buf = (void *)newshndx;
909 for (c = 0; c < entcnt; c++) {
910 if (oldshndx[c] != SHN_UNDEF) {
911 section_info_table *i;
912 i = &state->
913 sec_table[oldshndx[c]];
914 if (((int)i->secno !=
915 DELETED) &&
916 ((int)i->secno != NULLED))
917 newshndx[c] = i->secno;
918 else
919 newshndx[c] =
920 oldshndx[c];
921 } else
922 newshndx[c] =
923 oldshndx[c];
928 * If the section is to be updated,
929 * do so.
931 if (ISCANDIDATE(info->flags)) {
932 if ((GET_LOC(info->flags) == PRIOR) &&
933 (((int)info->secno == NULLED) ||
934 ((int)info->secno == EXPANDED) ||
935 ((int)info->secno == SHRUNK))) {
937 * The section is updated,
938 * but the position is not too
939 * good. Need to NULL this out.
941 dst_shdr.sh_name = 0;
942 dst_shdr.sh_type = SHT_PROGBITS;
943 if ((int)info->secno != NULLED) {
944 (cmd_info->no_of_moved)++;
945 SET_MOVING(info->flags);
947 } else {
949 * The section is positioned AFTER,
950 * or there are no segments.
951 * It is safe to update this section.
953 data = state->sec_table[scn_no].mdata;
954 *elf_data = *data;
955 dst_shdr.sh_size = elf_data->d_size;
958 /* add new section name to shstrtab? */
959 else if (!state->Sect_exists &&
960 (state->new_sec_string != NULL) &&
961 (scn_no == shstrndx) &&
962 (dst_shdr.sh_type == SHT_STRTAB) &&
963 ((src_ehdr->e_phnum == 0) ||
964 ((x = scn_location(dst_scn, dst_elf, state))
965 != IN) ||
966 (x != PRIOR))) {
967 size_t sect_len;
969 sect_len = strlen(SECT_NAME);
970 if ((elf_data->d_buf =
971 malloc((dst_shdr.sh_size +
972 sect_len + 1))) == NULL) {
973 error_message(MALLOC_ERROR,
974 PLAIN_ERROR, NULL, prog);
975 mcs_exit(FAILURE);
977 /* put original data plus new data in section */
978 (void) memcpy(elf_data->d_buf,
979 data->d_buf, data->d_size);
980 (void) memcpy(&((char *)elf_data->d_buf)
981 [data->d_size], SECT_NAME, sect_len + 1);
982 /* LINTED */
983 new_sh_name = (int)dst_shdr.sh_size;
984 dst_shdr.sh_size += sect_len + 1;
985 elf_data->d_size += sect_len + 1;
989 * Compute offsets.
991 if (src_ehdr->e_phnum != 0) {
993 * Compute section offset.
995 if (state->off_table[scn_no] == 0) {
996 if (dst_shdr.sh_addralign != 0) {
997 r = new_offset %
998 dst_shdr.sh_addralign;
999 if (r)
1000 new_offset +=
1001 dst_shdr.
1002 sh_addralign - r;
1004 dst_shdr.sh_offset = new_offset;
1005 elf_data->d_off = 0;
1006 } else {
1007 if (state->nobits_table[scn_no] == 0)
1008 new_offset =
1009 state->off_table[scn_no];
1011 if (state->nobits_table[scn_no] == 0)
1012 new_offset += dst_shdr.sh_size;
1015 /* flush changes */
1016 (void) gelf_update_shdr(dst_scn, &dst_shdr);
1018 scn_no++;
1022 * This is the real new section.
1024 if (!state->Sect_exists && state->new_sec_string != NULL) {
1025 size_t string_size;
1026 string_size = strlen(state->new_sec_string) + 1;
1027 if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
1028 error_message(LIBELF_ERROR,
1029 LIBelf_ERROR, elf_errmsg(-1), prog);
1030 return (FAILURE);
1032 (void) gelf_getshdr(dst_scn, &dst_shdr);
1034 dst_shdr.sh_name = new_sh_name;
1035 dst_shdr.sh_type = SHT_PROGBITS;
1036 dst_shdr.sh_flags = 0;
1037 dst_shdr.sh_addr = 0;
1038 if (src_ehdr->e_phnum != 0)
1039 dst_shdr.sh_offset = new_offset;
1040 else
1041 dst_shdr.sh_offset = 0;
1042 dst_shdr.sh_size = string_size + 1;
1043 dst_shdr.sh_link = 0;
1044 dst_shdr.sh_info = 0;
1045 dst_shdr.sh_addralign = 1;
1046 dst_shdr.sh_entsize = 0;
1047 (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */
1049 if ((elf_data = elf_newdata(dst_scn)) == NULL) {
1050 error_message(LIBELF_ERROR,
1051 LIBelf_ERROR, elf_errmsg(-1), prog);
1052 return (FAILURE);
1054 elf_data->d_size = string_size + 1;
1055 if ((elf_data->d_buf = (char *)
1056 calloc(1, string_size + 1)) == NULL) {
1057 error_message(MALLOC_ERROR,
1058 PLAIN_ERROR, NULL, prog);
1059 mcs_exit(FAILURE);
1061 (void) memcpy(&((char *)elf_data->d_buf)[1],
1062 state->new_sec_string, string_size);
1063 elf_data->d_align = 1;
1064 new_offset += string_size + 1;
1068 * If there are sections which needed to be moved,
1069 * then do it here.
1071 if (cmd_info->no_of_moved != 0) {
1072 int cnt;
1073 info = &state->sec_table[0];
1075 for (cnt = 0; cnt < shnum; cnt++, info++) {
1076 if ((GET_MOVING(info->flags)) == 0)
1077 continue;
1079 if ((src_scn = elf_getscn(src_elf, info->osecno)) ==
1080 NULL) {
1081 error_message(LIBELF_ERROR,
1082 LIBelf_ERROR, elf_errmsg(-1), prog);
1083 return (FAILURE);
1085 if (gelf_getshdr(src_scn, &src_shdr) == NULL) {
1086 error_message(LIBELF_ERROR,
1087 LIBelf_ERROR, elf_errmsg(-1), prog);
1088 return (FAILURE);
1090 if ((dst_scn = elf_newscn(dst_elf)) == NULL) {
1091 error_message(LIBELF_ERROR,
1092 LIBelf_ERROR, elf_errmsg(-1), prog);
1093 return (FAILURE);
1095 if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) {
1096 error_message(LIBELF_ERROR,
1097 LIBelf_ERROR, elf_errmsg(-1), prog);
1098 return (FAILURE);
1100 dst_shdr = src_shdr;
1102 data = info->mdata;
1104 dst_shdr.sh_offset = new_offset; /* UPDATE fields */
1105 dst_shdr.sh_size = data->d_size;
1107 if ((shnum >= src_shdr.sh_link) ||
1108 (src_shdr.sh_link == 0))
1109 dst_shdr.sh_link = src_shdr.sh_link;
1110 else
1111 dst_shdr.sh_link =
1112 state->sec_table[src_shdr.sh_link].osecno;
1114 if ((shnum >= src_shdr.sh_info) ||
1115 (src_shdr.sh_info == 0))
1116 dst_shdr.sh_info = src_shdr.sh_info;
1117 else
1118 dst_shdr.sh_info =
1119 state->sec_table[src_shdr.sh_info].osecno;
1120 (void) gelf_update_shdr(dst_scn, &dst_shdr);
1121 if ((elf_data = elf_newdata(dst_scn)) == NULL) {
1122 error_message(LIBELF_ERROR,
1123 LIBelf_ERROR, elf_errmsg(-1), prog);
1124 return (FAILURE);
1126 (void) memcpy(elf_data, data, sizeof (Elf_Data));
1128 new_offset += data->d_size;
1133 * In the event that the position of the sting table has changed,
1134 * as a result of deleted sections, update the ehdr->e_shstrndx.
1136 if ((shstrndx > 0) && (shnum > 0) &&
1137 (state->sec_table[shstrndx].secno < shnum)) {
1138 if (state->sec_table[shstrndx].secno < SHN_LORESERVE) {
1139 dst_ehdr.e_shstrndx =
1140 state->sec_table[dst_ehdr.e_shstrndx].secno;
1141 } else {
1142 Elf_Scn *_scn;
1143 GElf_Shdr shdr0;
1146 * If shstrndx requires 'Extended ELF Sections'
1147 * then it is stored in shdr[0].sh_link
1149 dst_ehdr.e_shstrndx = SHN_XINDEX;
1150 if ((_scn = elf_getscn(dst_elf, 0)) == NULL) {
1151 error_message(LIBELF_ERROR,
1152 LIBelf_ERROR, elf_errmsg(-1), prog);
1153 return (FAILURE);
1155 (void) gelf_getshdr(_scn, &shdr0);
1156 shdr0.sh_link = state->sec_table[shstrndx].secno;
1157 (void) gelf_update_shdr(_scn, &shdr0);
1161 if (src_ehdr->e_phnum != 0) {
1162 size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT);
1164 /* UPDATE location of program header table */
1165 if (location(dst_ehdr.e_phoff, 0, dst_elf, state) == AFTER) {
1166 r = new_offset % align;
1167 if (r)
1168 new_offset += align - r;
1170 dst_ehdr.e_phoff = new_offset;
1171 new_offset += dst_ehdr.e_phnum * dst_ehdr.e_phentsize;
1173 /* UPDATE location of section header table */
1174 if ((location(dst_ehdr.e_shoff, 0, src_elf, state) == AFTER) ||
1175 ((location(dst_ehdr.e_shoff, 0, src_elf, state) == PRIOR) &&
1176 (!state->Sect_exists && state->new_sec_string != NULL))) {
1177 r = new_offset % align;
1178 if (r)
1179 new_offset += align - r;
1181 dst_ehdr.e_shoff = new_offset;
1185 * The NOTE segment is the one segment whos
1186 * sections might get moved by mcs processing.
1187 * Make sure that the NOTE segments offset points
1188 * to the .note section.
1190 if ((state->notesegndx != -1) && (state->notesctndx != -1) &&
1191 (state->sec_table[state->notesctndx].secno)) {
1192 Elf_Scn * notescn;
1193 GElf_Shdr nshdr;
1195 notescn = elf_getscn(dst_elf,
1196 state->sec_table[state->notesctndx].secno);
1197 (void) gelf_getshdr(notescn, &nshdr);
1199 if (gelf_getclass(dst_elf) == ELFCLASS32) {
1200 Elf32_Phdr * ph = elf32_getphdr(dst_elf) +
1201 state->notesegndx;
1202 /* LINTED */
1203 ph->p_offset = (Elf32_Off)nshdr.sh_offset;
1204 } else {
1205 Elf64_Phdr * ph = elf64_getphdr(dst_elf) +
1206 state->notesegndx;
1207 ph->p_offset = (Elf64_Off)nshdr.sh_offset;
1212 /* copy ehdr changes back into real ehdr */
1213 (void) gelf_update_ehdr(dst_elf, &dst_ehdr);
1214 if (elf_update(dst_elf, ELF_C_WRITE) < 0) {
1215 error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog);
1216 return (FAILURE);
1219 (void) elf_end(dst_elf);
1220 (void) close(fdtmp);
1221 return (SUCCESS);
1225 * Search through PHT saving the beginning and ending segment offsets
1227 static int
1228 build_segment_table(Elf * elf, GElf_Ehdr * ehdr, file_state_t *state)
1230 unsigned int i;
1232 state->b_e_seg_table = (Seg_Table *)
1233 calloc(ehdr->e_phnum, sizeof (Seg_Table));
1234 if (state->b_e_seg_table == NULL) {
1235 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1236 mcs_exit(FAILURE);
1239 for (i = 0; i < ehdr->e_phnum; i++) {
1240 GElf_Phdr ph;
1242 (void) gelf_getphdr(elf, i, &ph);
1245 * remember the note SEGMENTS index so that we can
1246 * re-set it's p_offset later if needed.
1248 if (ph.p_type == PT_NOTE)
1249 state->notesegndx = i;
1251 state->b_e_seg_table[i].p_offset = ph.p_offset;
1252 state->b_e_seg_table[i].p_memsz = ph.p_offset + ph.p_memsz;
1253 state->b_e_seg_table[i].p_filesz = ph.p_offset + ph.p_filesz;
1255 return (SUCCESS);
1259 static void
1260 copy_elf_file_to_temp_ar_file(
1261 int fdartmp,
1262 Elf_Arhdr *mem_header,
1263 char *cur_file)
1265 char *buf;
1266 char mem_header_buf[sizeof (struct ar_hdr) + 1];
1267 int fdtmp3;
1268 struct stat stbuf;
1270 if ((fdtmp3 = open(elftmpfile.tmp_name, O_RDONLY)) == -1) {
1271 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
1272 prog, elftmpfile.tmp_name);
1273 mcs_exit(FAILURE);
1276 (void) stat(elftmpfile.tmp_name, &stbuf); /* for size of file */
1278 if ((buf =
1279 malloc(ROUNDUP(stbuf.st_size))) == NULL) {
1280 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1281 mcs_exit(FAILURE);
1284 if (read(fdtmp3, buf, stbuf.st_size) != stbuf.st_size) {
1285 error_message(READ_MANI_ERROR, SYSTEM_ERROR, strerror(errno),
1286 prog, elftmpfile.tmp_name, cur_file);
1287 mcs_exit(FAILURE);
1290 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname,
1291 mem_header->ar_date, (unsigned)mem_header->ar_uid,
1292 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode,
1293 stbuf.st_size, ARFMAG);
1295 if (write(fdartmp, mem_header_buf,
1296 (unsigned)sizeof (struct ar_hdr)) !=
1297 (unsigned)sizeof (struct ar_hdr)) {
1298 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR, strerror(errno),
1299 prog, elftmpfile.tmp_name, cur_file);
1300 mcs_exit(FAILURE);
1303 if (stbuf.st_size & 0x1) {
1304 buf[stbuf.st_size] = '\n';
1305 if (write(fdartmp, buf, (size_t)ROUNDUP(stbuf.st_size)) !=
1306 (size_t)ROUNDUP(stbuf.st_size)) {
1307 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1308 strerror(errno), prog, elftmpfile.tmp_name,
1309 cur_file);
1310 mcs_exit(FAILURE);
1312 } else if (write(fdartmp, buf, stbuf.st_size) != stbuf.st_size) {
1313 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1314 strerror(errno), prog, elftmpfile.tmp_name,
1315 cur_file);
1316 mcs_exit(FAILURE);
1318 free(buf);
1319 (void) close(fdtmp3);
1322 static void
1323 copy_non_elf_to_temp_ar(
1324 int fd,
1325 Elf *elf,
1326 int fdartmp,
1327 Elf_Arhdr *mem_header,
1328 char *cur_file,
1329 Cmd_Info *cmd_info)
1331 char mem_header_buf[sizeof (struct ar_hdr) + 1];
1332 char *file_buf;
1334 if ((strcmp(mem_header->ar_name, "/") != 0) &&
1335 (strcmp(mem_header->ar_name, "/SYM64/") != 0)) {
1336 (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname,
1337 mem_header->ar_date, (unsigned)mem_header->ar_uid,
1338 (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode,
1339 mem_header->ar_size, ARFMAG);
1341 if (write(fdartmp, mem_header_buf, sizeof (struct ar_hdr)) !=
1342 sizeof (struct ar_hdr)) {
1343 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1344 strerror(errno), prog, cur_file);
1345 mcs_exit(FAILURE);
1347 if ((file_buf =
1348 malloc(ROUNDUP(mem_header->ar_size))) == NULL) {
1349 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
1350 prog);
1351 mcs_exit(FAILURE);
1354 if (lseek(fd, elf_getbase(elf), 0) != elf_getbase(elf)) {
1355 error_message(WRITE_MANI_ERROR, prog, cur_file);
1356 mcs_exit(FAILURE);
1359 if (read(fd, file_buf,
1360 (size_t)ROUNDUP(mem_header->ar_size)) !=
1361 (size_t)ROUNDUP(mem_header->ar_size)) {
1362 error_message(READ_MANI_ERROR, SYSTEM_ERROR,
1363 strerror(errno), prog, cur_file);
1364 mcs_exit(FAILURE);
1366 if (write(fdartmp,
1367 file_buf,
1368 (size_t)ROUNDUP(mem_header->ar_size)) !=
1369 (size_t)ROUNDUP(mem_header->ar_size)) {
1370 error_message(WRITE_MANI_ERROR, SYSTEM_ERROR,
1371 strerror(errno), prog, cur_file);
1372 mcs_exit(FAILURE);
1374 free(file_buf);
1375 } else if (CHK_OPT(cmd_info, MIGHT_CHG)) {
1376 error_message(SYM_TAB_AR_ERROR, PLAIN_ERROR, NULL,
1377 prog, cur_file);
1378 error_message(EXEC_AR_ERROR, PLAIN_ERROR, NULL, cur_file);
1383 * Replace contents of file
1385 * entry:
1386 * ofd - Open file descriptor for file fname
1387 * fname - Name of file being processed
1388 * temp_file_name - Address of pointer to temporary
1389 * file containing new contents for fname.
1391 * exit:
1392 * The contents of the file given by temp_file->tmp_name are
1393 * copied to the file fname. The temporary file is
1394 * unlinked, and temp_file reset.
1396 static void
1397 copy_file(int ofd, char *fname, Tmp_File *temp_file)
1399 enum { MMAP_USED, MMAP_UNUSED } mmap_status;
1400 int i;
1401 int fdtmp2;
1402 struct stat stbuf;
1403 char *buf;
1405 for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */
1406 (void) signal(signum[i], SIG_IGN);
1408 if ((fdtmp2 = open(temp_file->tmp_name, O_RDONLY)) == -1) {
1409 error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno),
1410 prog, temp_file->tmp_name);
1411 mcs_exit(FAILURE);
1414 (void) stat(temp_file->tmp_name, &stbuf); /* for size of file */
1417 * Get the contents of the updated file.
1418 * First try mmap()'ing. If mmap() fails,
1419 * then use the malloc() and read().
1421 mmap_status = MMAP_USED;
1422 buf = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED, fdtmp2, 0);
1423 if (buf == (caddr_t)-1) {
1424 if ((buf =
1425 malloc(stbuf.st_size * sizeof (char))) == NULL) {
1426 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
1427 prog);
1428 mcs_exit(FAILURE);
1431 if (read(fdtmp2, buf, stbuf.st_size) != stbuf.st_size) {
1432 error_message(READ_SYS_ERROR, SYSTEM_ERROR,
1433 strerror(errno), prog, temp_file->tmp_name);
1434 mcs_exit(FAILURE);
1436 mmap_status = MMAP_UNUSED;
1439 if (ftruncate(ofd, 0) == -1) {
1440 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
1441 prog, fname);
1442 mcs_exit(FAILURE);
1444 if (lseek(ofd, 0, SEEK_SET) == -1) {
1445 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
1446 prog, fname);
1447 mcs_exit(FAILURE);
1449 if ((write(ofd, buf, stbuf.st_size)) != stbuf.st_size) {
1450 error_message(WRITE_MANI_ERROR2, SYSTEM_ERROR, strerror(errno),
1451 prog, fname);
1452 mcs_exit(FAILURE);
1456 * clean
1458 if (mmap_status == MMAP_USED)
1459 (void) munmap(buf, stbuf.st_size);
1460 else
1461 free(buf);
1462 (void) close(fdtmp2);
1463 free_tempfile(temp_file);
1466 static uint64_t
1467 location(int64_t offset, int mem_search, Elf * elf, file_state_t *state)
1469 int i;
1470 uint64_t upper;
1471 GElf_Ehdr ehdr;
1473 (void) gelf_getehdr(elf, &ehdr);
1475 for (i = 0; i < ehdr.e_phnum; i++) {
1476 if (mem_search)
1477 upper = state->b_e_seg_table[i].p_memsz;
1478 else
1479 upper = state->b_e_seg_table[i].p_filesz;
1480 if ((offset >= state->b_e_seg_table[i].p_offset) &&
1481 (offset <= upper))
1482 return (IN);
1483 else if (offset < state->b_e_seg_table[i].p_offset)
1484 return (PRIOR);
1486 return (AFTER);
1489 static uint64_t
1490 scn_location(Elf_Scn * scn, Elf * elf, file_state_t *state)
1492 GElf_Shdr shdr;
1494 (void) gelf_getshdr(scn, &shdr);
1497 * If the section is not a NOTE section and it has no
1498 * virtual address then it is not part of a mapped segment.
1500 if (shdr.sh_addr == 0)
1501 return (location(shdr.sh_offset + shdr.sh_size, 0, elf, state));
1503 return (location(shdr.sh_offset + shdr.sh_size, 1, elf, state));
1506 static void
1507 initialize(int shnum, Cmd_Info *cmd_info, file_state_t *state)
1510 * Initialize command info
1512 cmd_info->no_of_append = cmd_info->no_of_delete =
1513 cmd_info->no_of_nulled = cmd_info->no_of_compressed =
1514 cmd_info->no_of_moved = 0;
1515 cmd_info->sh_groups = NULL;
1517 state->sec_table = (section_info_table *)
1518 calloc(shnum + 1, sizeof (section_info_table));
1519 if (state->sec_table == NULL) {
1520 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1521 mcs_exit(FAILURE);
1524 state->off_table = (int64_t *)calloc(shnum, sizeof (int64_t));
1525 if (state->off_table == NULL) {
1526 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1527 mcs_exit(FAILURE);
1530 state->nobits_table = (int64_t *)calloc(shnum, sizeof (int64_t));
1531 if (state->nobits_table == NULL) {
1532 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL, prog);
1533 mcs_exit(FAILURE);
1538 * Update the contents of SHT_GROUP if needed
1540 static void
1541 post_process(Cmd_Info *cmd_info, file_state_t *state)
1543 Aliste idx;
1544 section_info_table *sinfo;
1545 Word *grpdata, *ngrpdata;
1546 int64_t sno, sno2;
1547 Word i, j, num;
1550 * If no change is required, then return.
1552 if ((cmd_info->flags & (SHF_GROUP_MOVE|SHF_GROUP_DEL)) == 0)
1553 return;
1556 * If SHF_GROUP sections were removed, we might need to
1557 * remove SHT_GROUP sections.
1559 if (cmd_info->flags & SHF_GROUP_DEL) {
1560 Word grpcnt;
1561 int deleted = 0;
1563 for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) {
1564 if (sinfo->secno == (GElf_Word)DELETED)
1565 continue;
1566 num = (sinfo->shdr).sh_size/sizeof (Word);
1567 grpcnt = 0;
1568 grpdata = (Word *)(sinfo->data->d_buf);
1569 for (i = 1; i < num; i++) {
1570 if (state->sec_table[grpdata[i]].secno !=
1571 (GElf_Word)DELETED)
1572 grpcnt++;
1576 * All members in this SHT_GROUP were removed.
1577 * We can remove this SHT_GROUP.
1579 if (grpcnt == 0) {
1580 sinfo->secno = (GElf_Word)DELETED;
1581 (cmd_info->no_of_delete)++;
1582 deleted = 1;
1587 * If we deleted a SHT_GROUP section,
1588 * we need to reasign section numbers.
1590 if (deleted) {
1591 section_info_table *sinfo;
1593 sno = 1;
1594 sno2 = 1;
1595 while (state->sec_table[sno].scn != (Elf_Scn *)-1) {
1596 sinfo = &state->sec_table[sno];
1597 if (sinfo->secno != (GElf_Word) DELETED)
1598 sinfo->secno = sno2++;
1599 sno++;
1605 * Now we can update data buffers of the SHT_GROUP sections.
1607 for (APLIST_TRAVERSE(cmd_info->sh_groups, idx, sinfo)) {
1608 if (sinfo->secno == (GElf_Word)DELETED)
1609 continue;
1610 num = (sinfo->shdr).sh_size/sizeof (Word);
1613 * Need to generate the updated data buffer
1615 if ((sinfo->mdata = malloc(sizeof (Elf_Data))) == NULL) {
1616 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
1617 prog);
1618 mcs_exit(FAILURE);
1620 *(sinfo->mdata) = *(sinfo->data);
1621 if ((ngrpdata = sinfo->mdata->d_buf =
1622 malloc(sinfo->data->d_size)) == NULL) {
1623 error_message(MALLOC_ERROR, PLAIN_ERROR, NULL,
1624 prog);
1625 mcs_exit(FAILURE);
1628 grpdata = (Word *)(sinfo->data->d_buf);
1629 ngrpdata[0] = grpdata[0];
1630 j = 1;
1631 for (i = 1; i < num; i++) {
1632 if (state->sec_table[grpdata[i]].secno !=
1633 (GElf_Word)DELETED) {
1634 ngrpdata[j++] =
1635 state->sec_table[grpdata[i]].secno;
1638 sinfo->mdata->d_size = j * sizeof (Word);
1639 sinfo->data = sinfo->mdata;
1641 free(cmd_info->sh_groups);
1642 cmd_info->sh_groups = NULL;