aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/unexelf.c360
1 files changed, 221 insertions, 139 deletions
diff --git a/src/unexelf.c b/src/unexelf.c
index 784fab1e7ff..b37e09da2f9 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -1,101 +1,19 @@
1/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. 1/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
2 2 Free Software Foundation, Inc.
3 NO WARRANTY
4
5 BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
6NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
7WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
8RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
9WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
10BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
11FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
12AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
13DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
14CORRECTION.
15
16 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
17STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
18WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
19LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
20OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
21USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
22DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
23A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
24PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
25DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
26
27 GENERAL PUBLIC LICENSE TO COPY
28
29 1. You may copy and distribute verbatim copies of this source file
30as you receive it, in any medium, provided that you conspicuously and
31appropriately publish on each copy a valid copyright notice "Copyright
32(C) 1987 Free Software Foundation, Inc."; and include following the
33copyright notice a verbatim copy of the above disclaimer of warranty
34and of this License. You may charge a distribution fee for the
35physical act of transferring a copy.
36
37 2. You may modify your copy or copies of this source file or
38any portion of it, and copy and distribute such modifications under
39the terms of Paragraph 1 above, provided that you also do the following:
40
41 a) cause the modified files to carry prominent notices stating
42 that you changed the files and the date of any change; and
43
44 b) cause the whole of any work that you distribute or publish,
45 that in whole or in part contains or is a derivative of this
46 program or any part thereof, to be licensed at no charge to all
47 third parties on terms identical to those contained in this
48 License Agreement (except that you may choose to grant more extensive
49 warranty protection to some or all third parties, at your option).
50
51 c) You may charge a distribution fee for the physical act of
52 transferring a copy, and you may at your option offer warranty
53 protection in exchange for a fee.
54
55Mere aggregation of another unrelated program with this program (or its
56derivative) on a volume of a storage or distribution medium does not bring
57the other program under the scope of these terms.
58
59 3. You may copy and distribute this program (or a portion or derivative
60of it, under Paragraph 2) in object code or executable form under the terms
61of Paragraphs 1 and 2 above provided that you also do one of the following:
62
63 a) accompany it with the complete corresponding machine-readable
64 source code, which must be distributed under the terms of
65 Paragraphs 1 and 2 above; or,
66
67 b) accompany it with a written offer, valid for at least three
68 years, to give any third party free (except for a nominal
69 shipping charge) a complete machine-readable copy of the
70 corresponding source code, to be distributed under the terms of
71 Paragraphs 1 and 2 above; or,
72
73 c) accompany it with the information you received as to where the
74 corresponding source code may be obtained. (This alternative is
75 allowed only for noncommercial distribution and only if you
76 received the program in object code or executable form alone.)
77
78For an executable file, complete source code means all the source code for
79all modules it contains; but, as a special exception, it need not include
80source code for modules which are standard libraries that accompany the
81operating system on which the executable file runs.
82
83 4. You may not copy, sublicense, distribute or transfer this program
84except as expressly provided under this License Agreement. Any attempt
85otherwise to copy, sublicense, distribute or transfer this program is void and
86your rights to use the program under this License agreement shall be
87automatically terminated. However, parties who have received computer
88software programs from you with this License Agreement will not have
89their licenses terminated so long as such parties remain in full compliance.
90
91 5. If you wish to incorporate parts of this program into other free
92programs whose distribution conditions are different, write to the Free
93Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
94worked out a simple rule that can be stated here, but we will often permit
95this. We will be guided by the two goals of preserving the free status of
96all derivatives of our free software and of promoting the sharing and reuse of
97software.
98 3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
99 17
100In other words, you are welcome to use, share and improve this program. 18In other words, you are welcome to use, share and improve this program.
101You are forbidden to forbid anyone else to use, share and improve 19You are forbidden to forbid anyone else to use, share and improve
@@ -397,7 +315,100 @@ Filesz Memsz Flags Align
397 315
398 316
399 */ 317 */
318
319/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
320 *
321 * The above mechanism does not work if the unexeced ELF file is being
322 * re-layout by other applications (such as `strip'). All the applications
323 * that re-layout the internal of ELF will layout all sections in ascending
324 * order of their file offsets. After the re-layout, the data2 section will
325 * still be the LAST section in the section header vector, but its file offset
326 * is now being pushed far away down, and causes part of it not to be mapped
327 * in (ie. not covered by the load segment entry in PHDR vector), therefore
328 * causes the new binary to fail.
329 *
330 * The solution is to modify the unexec algorithm to insert the new data2
331 * section header right before the new bss section header, so their file
332 * offsets will be in the ascending order. Since some of the section's (all
333 * sections AFTER the bss section) indexes are now changed, we also need to
334 * modify some fields to make them point to the right sections. This is done
335 * by macro PATCH_INDEX. All the fields that need to be patched are:
336 *
337 * 1. ELF header e_shstrndx field.
338 * 2. section header sh_link and sh_info field.
339 * 3. symbol table entry st_shndx field.
340 *
341 * The above example now should look like:
342
343 **** SECTION HEADER TABLE ****
344[No] Type Flags Addr Offset Size Name
345 Link Info Adralgn Entsize
346
347[1] 1 2 0x80480d4 0xd4 0x13 .interp
348 0 0 0x1 0
400 349
350[2] 5 2 0x80480e8 0xe8 0x388 .hash
351 3 0 0x4 0x4
352
353[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
354 4 1 0x4 0x10
355
356[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
357 0 0 0x1 0
358
359[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
360 3 7 0x4 0x8
361
362[6] 1 6 0x8049348 0x1348 0x3 .init
363 0 0 0x4 0
364
365[7] 1 6 0x804934c 0x134c 0x680 .plt
366 0 0 0x4 0x4
367
368[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
369 0 0 0x4 0
370
371[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
372 0 0 0x4 0
373
374[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
375 0 0 0x4 0
376
377[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
378 0 0 0x4 0
379
380[12] 1 3 0x8088330 0x3f330 0x20afc .data
381 0 0 0x4 0
382
383[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
384 0 0 0x4 0
385
386[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
387 0 0 0x4 0x4
388
389[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
390 4 0 0x4 0x8
391
392[16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
393 0 0 0x4 0
394
395[17] 8 3 0x80c6800 0x7d800 0 .bss
396 0 0 0x4 0
397
398[18] 2 0 0 0x7d800 0x9b90 .symtab
399 19 371 0x4 0x10
400
401[19] 3 0 0 0x87390 0x8526 .strtab
402 0 0 0x1 0
403
404[20] 3 0 0 0x8f8b6 0x93 .shstrtab
405 0 0 0x1 0
406
407[21] 1 0 0 0x8f949 0x68b7 .comment
408 0 0 0x1 0
409
410 */
411
401#include <sys/types.h> 412#include <sys/types.h>
402#include <stdio.h> 413#include <stdio.h>
403#include <sys/stat.h> 414#include <sys/stat.h>
@@ -428,8 +439,24 @@ extern void fatal(char *, ...);
428#define NEW_PROGRAM_H(n) \ 439#define NEW_PROGRAM_H(n) \
429 (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) 440 (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
430 441
442#define PATCH_INDEX(n) \
443 do { \
444 if ((n) >= old_bss_index) \
445 (n)++; } while (0)
431typedef unsigned char byte; 446typedef unsigned char byte;
432 447
448/* Round X up to a multiple of Y. */
449
450int
451round_up (x, y)
452 int x, y;
453{
454 int rem = x % y;
455 if (rem == 0)
456 return x;
457 return x - rem + y;
458}
459
433/* **************************************************************** 460/* ****************************************************************
434 * unexec 461 * unexec
435 * 462 *
@@ -465,7 +492,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
465 Elf32_Off new_data2_offset; 492 Elf32_Off new_data2_offset;
466 Elf32_Addr new_data2_addr; 493 Elf32_Addr new_data2_addr;
467 494
468 int n, old_bss_index, old_data_index, new_data2_index; 495 int n, nn, old_bss_index, old_data_index, new_data2_index;
469 struct stat stat_buf; 496 struct stat stat_buf;
470 497
471 /* Open the old file & map it into the address space. */ 498 /* Open the old file & map it into the address space. */
@@ -570,8 +597,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
570 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize); 597 memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
571 memcpy (new_program_h, old_program_h, 598 memcpy (new_program_h, old_program_h,
572 old_file_h->e_phnum * old_file_h->e_phentsize); 599 old_file_h->e_phnum * old_file_h->e_phentsize);
573 memcpy (new_section_h, old_section_h, 600
574 old_file_h->e_shnum * old_file_h->e_shentsize); 601 /* Modify the e_shstrndx if necessary. */
602 PATCH_INDEX (new_file_h->e_shstrndx);
575 603
576 /* Fix up file header. We'll add one section. Section header is 604 /* Fix up file header. We'll add one section. Section header is
577 * further away now. 605 * further away now.
@@ -597,12 +625,19 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
597 625
598 for (n = new_file_h->e_phnum - 1; n >= 0; n--) 626 for (n = new_file_h->e_phnum - 1; n >= 0; n--)
599 { 627 {
628 /* Compute maximum of all requirements for alignment of section. */
629 int alignment = (NEW_PROGRAM_H (n)).p_align;
630 if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
631 alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
632
600 if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr) 633 if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)
601 fatal ("Program segment above .bss in %s\n", old_name, 0); 634 fatal ("Program segment above .bss in %s\n", old_name, 0);
602 635
603 if (NEW_PROGRAM_H(n).p_type == PT_LOAD 636 if (NEW_PROGRAM_H(n).p_type == PT_LOAD
604 && (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz 637 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
605 == old_bss_addr)) 638 + (NEW_PROGRAM_H (n)).p_filesz,
639 alignment)
640 == round_up (old_bss_addr, alignment)))
606 break; 641 break;
607 } 642 }
608 if (n < 0) 643 if (n < 0)
@@ -629,19 +664,6 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
629 * is set. data2 section header gets added by copying the existing 664 * is set. data2 section header gets added by copying the existing
630 * .data header and modifying the offset, address and size. 665 * .data header and modifying the offset, address and size.
631 */ 666 */
632
633 for (n = 1; n < new_file_h->e_shnum; n++)
634 {
635 if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
636 NEW_SECTION_H(n).sh_offset += new_data2_size;
637
638 if (NEW_SECTION_H(n).sh_addr
639 && NEW_SECTION_H(n).sh_addr >= new_data2_addr)
640 NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;
641 }
642
643 new_data2_index = old_file_h->e_shnum;
644
645 for (old_data_index = 1; old_data_index < old_file_h->e_shnum; 667 for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
646 old_data_index++) 668 old_data_index++)
647 if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name, 669 if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
@@ -650,38 +672,98 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
650 if (old_data_index == old_file_h->e_shnum) 672 if (old_data_index == old_file_h->e_shnum)
651 fatal ("Can't find .data in %s.\n", old_name, 0); 673 fatal ("Can't find .data in %s.\n", old_name, 0);
652 674
653 memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index), 675 /* Walk through all section headers, insert the new data2 section right
654 new_file_h->e_shentsize); 676 before the new bss section. */
655 677 for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
656 NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;
657 NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;
658 NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;
659
660 NEW_SECTION_H(old_bss_index).sh_size = 0;
661 NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;
662
663 /* Write out the sections. .data and .data1 (and data2, called
664 * ".data" in the strings table) get copied from the current process
665 * instead of the old file.
666 */
667
668 for (n = new_file_h->e_shnum - 1; n; n--)
669 { 678 {
670 caddr_t src; 679 caddr_t src;
671 680 /* If it is bss section, insert the new data2 section before it. */
672 if (NEW_SECTION_H(n).sh_type == SHT_NULL 681 if (n == old_bss_index)
673 || NEW_SECTION_H(n).sh_type == SHT_NOBITS) 682 {
683 /* Steal the data section header for this data2 section. */
684 memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(old_data_index),
685 new_file_h->e_shentsize);
686
687 NEW_SECTION_H(nn).sh_addr = new_data2_addr;
688 NEW_SECTION_H(nn).sh_offset = new_data2_offset;
689 NEW_SECTION_H(nn).sh_size = new_data2_size;
690 /* Use the bss section's alignment. This will assure that the
691 new data2 section always be placed in the same spot as the old
692 bss section by any other application. */
693 NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(n).sh_addralign;
694
695 /* Now copy over what we have in the memory now. */
696 memcpy (NEW_SECTION_H(nn).sh_offset + new_base,
697 (caddr_t) OLD_SECTION_H(n).sh_addr,
698 new_data2_size);
699 nn++;
700 }
701
702 memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(n),
703 old_file_h->e_shentsize);
704
705 /* The new bss section's size is zero, and its file offset and virtual
706 address should be off by NEW_DATA2_SIZE. */
707 if (n == old_bss_index)
708 {
709 /* NN should be `old_bss_index + 1' at this point. */
710 NEW_SECTION_H(nn).sh_offset += new_data2_size;
711 NEW_SECTION_H(nn).sh_addr += new_data2_size;
712 /* Let the new bss section address alignment be the same as the
713 section address alignment followed the old bss section, so
714 this section will be placed in exactly the same place. */
715 NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(nn).sh_addralign;
716 NEW_SECTION_H(nn).sh_size = 0;
717 }
718 /* Any section that was original placed AFTER the bss section should now
719 be off by NEW_DATA2_SIZE. */
720 else if (NEW_SECTION_H(nn).sh_offset >= new_data2_offset)
721 NEW_SECTION_H(nn).sh_offset += new_data2_size;
722
723 /* If any section hdr refers to the section after the new .data
724 section, make it refer to next one because we have inserted
725 a new section in between. */
726
727 PATCH_INDEX(NEW_SECTION_H(nn).sh_link);
728 PATCH_INDEX(NEW_SECTION_H(nn).sh_info);
729
730 /* Now, start to copy the content of sections. */
731 if (NEW_SECTION_H(nn).sh_type == SHT_NULL
732 || NEW_SECTION_H(nn).sh_type == SHT_NOBITS)
674 continue; 733 continue;
675 734
735 /* Write out the sections. .data and .data1 (and data2, called
736 * ".data" in the strings table) get copied from the current process
737 * instead of the old file.
738 */
676 if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data") 739 if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
677 || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name), 740 || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
678 ".data1")) 741 ".data1"))
679 src = (caddr_t) NEW_SECTION_H(n).sh_addr; 742 src = (caddr_t) OLD_SECTION_H(n).sh_addr;
680 else 743 else
681 src = old_base + OLD_SECTION_H(n).sh_offset; 744 src = old_base + OLD_SECTION_H(n).sh_offset;
682 745
683 memcpy (NEW_SECTION_H(n).sh_offset + new_base, src, 746 memcpy (NEW_SECTION_H(nn).sh_offset + new_base, src,
684 NEW_SECTION_H(n).sh_size); 747 NEW_SECTION_H(nn).sh_size);
748
749 /* If it is the symbol table, its st_shndx field needs to be patched. */
750 if (NEW_SECTION_H(nn).sh_type == SHT_SYMTAB
751 || NEW_SECTION_H(nn).sh_type == SHT_DYNSYM)
752 {
753 Elf32_Shdr *spt = &NEW_SECTION_H(nn);
754 unsigned int num = spt->sh_size / spt->sh_entsize;
755 Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H(nn).sh_offset +
756 new_base);
757 for (; num--; sym++)
758 {
759 if ((sym->st_shndx == SHN_UNDEF)
760 || (sym->st_shndx == SHN_ABS)
761 || (sym->st_shndx == SHN_COMMON))
762 continue;
763
764 PATCH_INDEX(sym->st_shndx);
765 }
766 }
685 } 767 }
686 768
687 /* Close the files and make the new file executable */ 769 /* Close the files and make the new file executable */