diff options
| author | Paul Eggert | 2013-05-05 21:52:00 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-05-05 21:52:00 -0700 |
| commit | 5ee94506f6ee4f5142bfeabc9409f95e370d38e3 (patch) | |
| tree | 929f38ea53bd29b1b3141a5d09bfcafa0bb1e8f7 /src | |
| parent | dc4a2ee0efe25b03973ea5feb5de9e46560a8127 (diff) | |
| download | emacs-5ee94506f6ee4f5142bfeabc9409f95e370d38e3.tar.gz emacs-5ee94506f6ee4f5142bfeabc9409f95e370d38e3.zip | |
* unexelf.c: Fix some 32-bit integer problems, notably when debugging.
Include <limits.h>, <stdbool.h>, <intprops.h>, <verify.h>.
Verify that ElfW (Half) fits in int.
(fatal): Use same signature as lisp.h.
(UNEXELF_DEBUG): New macro, replacing DEBUG, so that people can
configure and build with -DUNEXELF_DEBUG without worrying about
other modules that use DEBUG.
(DEBUG_LOG) [UNEXELF_DEBUG]: New macro. All debug code that prints
possibly-wide integers now uses it instead of plain fprintf.
(entry_address): New function, which avoids problems with 32-bit
overflow on 64-bit hosts.
(OLD_SECTION_H, NEW_SECTION_H, NEW_PROGRAM_H): Use it.
(round_up): Don't assume the remainder fits in int.
(find_section): Use bool for boolean. Simplify debug code.
(unexec): Don't assume file sizes fit in int or size_t.
Omit unnecessary trailing newline in 'fatal' format.
Use strerror rather than outputting decimal error number.
Remove unused code when emacs is not defined;
this file relies on Emacs now.
Don't assume e_phnum and e_shnum are positive.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 21 | ||||
| -rw-r--r-- | src/unexelf.c | 175 |
2 files changed, 115 insertions, 81 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 648a33a6fa1..b6ae117c8b2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,26 @@ | |||
| 1 | 2013-05-06 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2013-05-06 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | * unexelf.c: Fix some 32-bit integer problems, notably when debugging. | ||
| 4 | Include <limits.h>, <stdbool.h>, <intprops.h>, <verify.h>. | ||
| 5 | Verify that ElfW (Half) fits in int. | ||
| 6 | (fatal): Use same signature as lisp.h. | ||
| 7 | (UNEXELF_DEBUG): New macro, replacing DEBUG, so that people can | ||
| 8 | configure and build with -DUNEXELF_DEBUG without worrying about | ||
| 9 | other modules that use DEBUG. | ||
| 10 | (DEBUG_LOG) [UNEXELF_DEBUG]: New macro. All debug code that prints | ||
| 11 | possibly-wide integers now uses it instead of plain fprintf. | ||
| 12 | (entry_address): New function, which avoids problems with 32-bit | ||
| 13 | overflow on 64-bit hosts. | ||
| 14 | (OLD_SECTION_H, NEW_SECTION_H, NEW_PROGRAM_H): Use it. | ||
| 15 | (round_up): Don't assume the remainder fits in int. | ||
| 16 | (find_section): Use bool for boolean. Simplify debug code. | ||
| 17 | (unexec): Don't assume file sizes fit in int or size_t. | ||
| 18 | Omit unnecessary trailing newline in 'fatal' format. | ||
| 19 | Use strerror rather than outputting decimal error number. | ||
| 20 | Remove unused code when emacs is not defined; | ||
| 21 | this file relies on Emacs now. | ||
| 22 | Don't assume e_phnum and e_shnum are positive. | ||
| 23 | |||
| 3 | * regex.c: Fix problems when DEBUG is defined. | 24 | * regex.c: Fix problems when DEBUG is defined. |
| 4 | (extract_number, extract_number_and_incr): Define regardless of | 25 | (extract_number, extract_number_and_incr): Define regardless of |
| 5 | whether DEBUG is defined; that's simpler and makes the code less | 26 | whether DEBUG is defined; that's simpler and makes the code less |
diff --git a/src/unexelf.c b/src/unexelf.c index d3659404f9c..b2a9878b5e9 100644 --- a/src/unexelf.c +++ b/src/unexelf.c | |||
| @@ -388,16 +388,19 @@ temacs: | |||
| 388 | #include <config.h> | 388 | #include <config.h> |
| 389 | #include <unexec.h> | 389 | #include <unexec.h> |
| 390 | 390 | ||
| 391 | extern void fatal (const char *msgid, ...); | 391 | extern _Noreturn void fatal (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2); |
| 392 | 392 | ||
| 393 | #include <sys/types.h> | 393 | #include <errno.h> |
| 394 | #include <fcntl.h> | ||
| 395 | #include <limits.h> | ||
| 396 | #include <memory.h> | ||
| 397 | #include <stdbool.h> | ||
| 394 | #include <stdint.h> | 398 | #include <stdint.h> |
| 395 | #include <stdio.h> | 399 | #include <stdio.h> |
| 396 | #include <sys/stat.h> | 400 | #include <sys/stat.h> |
| 397 | #include <memory.h> | 401 | #include <sys/types.h> |
| 398 | #include <errno.h> | ||
| 399 | #include <unistd.h> | 402 | #include <unistd.h> |
| 400 | #include <fcntl.h> | 403 | |
| 401 | #if !defined (__NetBSD__) && !defined (__OpenBSD__) | 404 | #if !defined (__NetBSD__) && !defined (__OpenBSD__) |
| 402 | #include <elf.h> | 405 | #include <elf.h> |
| 403 | #endif /* not __NetBSD__ and not __OpenBSD__ */ | 406 | #endif /* not __NetBSD__ and not __OpenBSD__ */ |
| @@ -519,6 +522,17 @@ typedef struct { | |||
| 519 | # define ElfW(type) ElfExpandBitsW (ELFSIZE, type) | 522 | # define ElfW(type) ElfExpandBitsW (ELFSIZE, type) |
| 520 | #endif | 523 | #endif |
| 521 | 524 | ||
| 525 | /* The code often converts ElfW (Half) values like e_shentsize to int; | ||
| 526 | check that this doesn't lose information. */ | ||
| 527 | #include <intprops.h> | ||
| 528 | #include <verify.h> | ||
| 529 | verify ((! TYPE_SIGNED (ElfW (Half)) || INT_MIN <= TYPE_MINIMUM (ElfW (Half))) | ||
| 530 | && TYPE_MAXIMUM (ElfW (Half)) <= INT_MAX); | ||
| 531 | |||
| 532 | #ifdef UNEXELF_DEBUG | ||
| 533 | # define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr)) | ||
| 534 | #endif | ||
| 535 | |||
| 522 | /* Get the address of a particular section or program header entry, | 536 | /* Get the address of a particular section or program header entry, |
| 523 | * accounting for the size of the entries. | 537 | * accounting for the size of the entries. |
| 524 | */ | 538 | */ |
| @@ -546,17 +560,25 @@ typedef struct { | |||
| 546 | Apr 23, 1996 | 560 | Apr 23, 1996 |
| 547 | */ | 561 | */ |
| 548 | 562 | ||
| 563 | static void * | ||
| 564 | entry_address (void *section_h, int idx, int num, int entsize) | ||
| 565 | { | ||
| 566 | char *h = section_h; | ||
| 567 | ptrdiff_t n = idx; | ||
| 568 | return h + entsize * n; | ||
| 569 | } | ||
| 570 | |||
| 549 | #define OLD_SECTION_H(n) \ | 571 | #define OLD_SECTION_H(n) \ |
| 550 | (*(ElfW (Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) | 572 | (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shnum, \ |
| 573 | old_file_h->e_shentsize)) | ||
| 551 | #define NEW_SECTION_H(n) \ | 574 | #define NEW_SECTION_H(n) \ |
| 552 | (*(ElfW (Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) | 575 | (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shnum, \ |
| 576 | new_file_h->e_shentsize)) | ||
| 553 | #define NEW_PROGRAM_H(n) \ | 577 | #define NEW_PROGRAM_H(n) \ |
| 554 | (*(ElfW (Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) | 578 | (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phnum, \ |
| 579 | new_file_h->e_phentsize)) | ||
| 555 | 580 | ||
| 556 | #define PATCH_INDEX(n) \ | 581 | #define PATCH_INDEX(n) ((n) += old_bss_index <= (n)) |
| 557 | do { \ | ||
| 558 | if ((int) (n) >= old_bss_index) \ | ||
| 559 | (n)++; } while (0) | ||
| 560 | typedef unsigned char byte; | 582 | typedef unsigned char byte; |
| 561 | 583 | ||
| 562 | /* Round X up to a multiple of Y. */ | 584 | /* Round X up to a multiple of Y. */ |
| @@ -564,7 +586,7 @@ typedef unsigned char byte; | |||
| 564 | static ElfW (Addr) | 586 | static ElfW (Addr) |
| 565 | round_up (ElfW (Addr) x, ElfW (Addr) y) | 587 | round_up (ElfW (Addr) x, ElfW (Addr) y) |
| 566 | { | 588 | { |
| 567 | int rem = x % y; | 589 | ElfW (Addr) rem = x % y; |
| 568 | if (rem == 0) | 590 | if (rem == 0) |
| 569 | return x; | 591 | return x; |
| 570 | return x - rem + y; | 592 | return x - rem + y; |
| @@ -575,33 +597,28 @@ round_up (ElfW (Addr) x, ElfW (Addr) y) | |||
| 575 | about the file we are looking in. | 597 | about the file we are looking in. |
| 576 | 598 | ||
| 577 | If we don't find the section NAME, that is a fatal error | 599 | If we don't find the section NAME, that is a fatal error |
| 578 | if NOERROR is 0; we return -1 if NOERROR is nonzero. */ | 600 | if NOERROR is false; return -1 if NOERROR is true. */ |
| 579 | 601 | ||
| 580 | static int | 602 | static int |
| 581 | find_section (const char *name, const char *section_names, const char *file_name, | 603 | find_section (const char *name, const char *section_names, const char *file_name, |
| 582 | ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h, int noerror) | 604 | ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h, |
| 605 | bool noerror) | ||
| 583 | { | 606 | { |
| 584 | int idx; | 607 | int idx; |
| 585 | 608 | ||
| 586 | for (idx = 1; idx < old_file_h->e_shnum; idx++) | 609 | for (idx = 1; idx < old_file_h->e_shnum; idx++) |
| 587 | { | 610 | { |
| 588 | #ifdef DEBUG | 611 | char const *found_name = section_names + OLD_SECTION_H (idx).sh_name; |
| 589 | fprintf (stderr, "Looking for %s - found %s\n", name, | 612 | #ifdef UNEXELF_DEBUG |
| 590 | section_names + OLD_SECTION_H (idx).sh_name); | 613 | fprintf (stderr, "Looking for %s - found %s\n", name, found_name); |
| 591 | #endif | 614 | #endif |
| 592 | if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name, | 615 | if (strcmp (name, found_name) == 0) |
| 593 | name)) | 616 | return idx; |
| 594 | break; | ||
| 595 | } | ||
| 596 | if (idx == old_file_h->e_shnum) | ||
| 597 | { | ||
| 598 | if (noerror) | ||
| 599 | return -1; | ||
| 600 | else | ||
| 601 | fatal ("Can't find %s in %s.\n", name, file_name); | ||
| 602 | } | 617 | } |
| 603 | 618 | ||
| 604 | return idx; | 619 | if (! noerror) |
| 620 | fatal ("Can't find %s in %s", name, file_name); | ||
| 621 | return -1; | ||
| 605 | } | 622 | } |
| 606 | 623 | ||
| 607 | /* **************************************************************** | 624 | /* **************************************************************** |
| @@ -616,11 +633,9 @@ find_section (const char *name, const char *section_names, const char *file_name | |||
| 616 | void | 633 | void |
| 617 | unexec (const char *new_name, const char *old_name) | 634 | unexec (const char *new_name, const char *old_name) |
| 618 | { | 635 | { |
| 619 | int new_file, old_file, new_file_size; | 636 | int new_file, old_file; |
| 620 | 637 | off_t new_file_size; | |
| 621 | #if defined (emacs) || !defined (DEBUG) | ||
| 622 | void *new_break; | 638 | void *new_break; |
| 623 | #endif | ||
| 624 | 639 | ||
| 625 | /* Pointers to the base of the image of the two files. */ | 640 | /* Pointers to the base of the image of the two files. */ |
| 626 | caddr_t old_base, new_base; | 641 | caddr_t old_base, new_base; |
| @@ -654,7 +669,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 654 | int old_mdebug_index; | 669 | int old_mdebug_index; |
| 655 | #endif | 670 | #endif |
| 656 | struct stat stat_buf; | 671 | struct stat stat_buf; |
| 657 | int old_file_size; | 672 | off_t old_file_size; |
| 658 | 673 | ||
| 659 | /* Open the old file, allocate a buffer of the right size, and read | 674 | /* Open the old file, allocate a buffer of the right size, and read |
| 660 | in the file contents. */ | 675 | in the file contents. */ |
| @@ -662,15 +677,15 @@ unexec (const char *new_name, const char *old_name) | |||
| 662 | old_file = open (old_name, O_RDONLY); | 677 | old_file = open (old_name, O_RDONLY); |
| 663 | 678 | ||
| 664 | if (old_file < 0) | 679 | if (old_file < 0) |
| 665 | fatal ("Can't open %s for reading: errno %d\n", old_name, errno); | 680 | fatal ("Can't open %s for reading: %s", old_name, strerror (errno)); |
| 666 | 681 | ||
| 667 | if (fstat (old_file, &stat_buf) == -1) | 682 | if (fstat (old_file, &stat_buf) != 0) |
| 668 | fatal ("Can't fstat (%s): errno %d\n", old_name, errno); | 683 | fatal ("Can't fstat (%s): %s", old_name, strerror (errno)); |
| 669 | 684 | ||
| 670 | #if MAP_ANON == 0 | 685 | #if MAP_ANON == 0 |
| 671 | mmap_fd = open ("/dev/zero", O_RDONLY); | 686 | mmap_fd = open ("/dev/zero", O_RDONLY); |
| 672 | if (mmap_fd < 0) | 687 | if (mmap_fd < 0) |
| 673 | fatal ("Can't open /dev/zero for reading: errno %d\n", errno, 0); | 688 | fatal ("Can't open /dev/zero for reading: %s", strerror (errno)); |
| 674 | #endif | 689 | #endif |
| 675 | 690 | ||
| 676 | /* We cannot use malloc here because that may use sbrk. If it does, | 691 | /* We cannot use malloc here because that may use sbrk. If it does, |
| @@ -678,13 +693,15 @@ unexec (const char *new_name, const char *old_name) | |||
| 678 | extra careful to use the correct value of sbrk(0) after | 693 | extra careful to use the correct value of sbrk(0) after |
| 679 | allocating all buffers in the code below, which we aren't. */ | 694 | allocating all buffers in the code below, which we aren't. */ |
| 680 | old_file_size = stat_buf.st_size; | 695 | old_file_size = stat_buf.st_size; |
| 696 | if (! (0 <= old_file_size && old_file_size <= SIZE_MAX)) | ||
| 697 | fatal ("File size out of range"); | ||
| 681 | old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE, | 698 | old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE, |
| 682 | MAP_ANON | MAP_PRIVATE, mmap_fd, 0); | 699 | MAP_ANON | MAP_PRIVATE, mmap_fd, 0); |
| 683 | if (old_base == MAP_FAILED) | 700 | if (old_base == MAP_FAILED) |
| 684 | fatal ("Can't allocate buffer for %s\n", old_name, 0); | 701 | fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno)); |
| 685 | 702 | ||
| 686 | if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size) | 703 | if (read (old_file, old_base, old_file_size) != old_file_size) |
| 687 | fatal ("Didn't read all of %s: errno %d\n", old_name, errno); | 704 | fatal ("Didn't read all of %s: %s", old_name, strerror (errno)); |
| 688 | 705 | ||
| 689 | /* Get pointers to headers & section names */ | 706 | /* Get pointers to headers & section names */ |
| 690 | 707 | ||
| @@ -755,12 +772,8 @@ unexec (const char *new_name, const char *old_name) | |||
| 755 | old_data_index = find_section (".data", old_section_names, | 772 | old_data_index = find_section (".data", old_section_names, |
| 756 | old_name, old_file_h, old_section_h, 0); | 773 | old_name, old_file_h, old_section_h, 0); |
| 757 | 774 | ||
| 758 | #if defined (emacs) || !defined (DEBUG) | ||
| 759 | new_break = sbrk (0); | 775 | new_break = sbrk (0); |
| 760 | new_bss_addr = (ElfW (Addr)) new_break; | 776 | new_bss_addr = (ElfW (Addr)) new_break; |
| 761 | #else | ||
| 762 | new_bss_addr = old_bss_addr + old_bss_size + 0x1234; | ||
| 763 | #endif | ||
| 764 | new_data2_addr = old_bss_addr; | 777 | new_data2_addr = old_bss_addr; |
| 765 | new_data2_size = new_bss_addr - old_bss_addr; | 778 | new_data2_size = new_bss_addr - old_bss_addr; |
| 766 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset | 779 | new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset |
| @@ -771,38 +784,38 @@ unexec (const char *new_name, const char *old_name) | |||
| 771 | section) was unaligned. */ | 784 | section) was unaligned. */ |
| 772 | new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); | 785 | new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); |
| 773 | 786 | ||
| 774 | #ifdef DEBUG | 787 | #ifdef UNEXELF_DEBUG |
| 775 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); | 788 | fprintf (stderr, "old_bss_index %d\n", old_bss_index); |
| 776 | fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); | 789 | DEBUG_LOG (old_bss_addr); |
| 777 | fprintf (stderr, "old_bss_size %x\n", old_bss_size); | 790 | DEBUG_LOG (old_bss_size); |
| 778 | fprintf (stderr, "old_bss_offset %x\n", old_bss_offset); | 791 | DEBUG_LOG (old_bss_offset); |
| 779 | fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); | 792 | DEBUG_LOG (new_bss_addr); |
| 780 | fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); | 793 | DEBUG_LOG (new_data2_addr); |
| 781 | fprintf (stderr, "new_data2_size %x\n", new_data2_size); | 794 | DEBUG_LOG (new_data2_size); |
| 782 | fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); | 795 | DEBUG_LOG (new_data2_offset); |
| 783 | fprintf (stderr, "new_data2_incr %x\n", new_data2_incr); | 796 | DEBUG_LOG (new_data2_incr); |
| 784 | #endif | 797 | #endif |
| 785 | 798 | ||
| 786 | if ((uintptr_t) new_bss_addr < (uintptr_t) old_bss_addr + old_bss_size) | 799 | if (new_bss_addr < old_bss_addr + old_bss_size) |
| 787 | fatal (".bss shrank when undumping???\n", 0, 0); | 800 | fatal (".bss shrank when undumping"); |
| 788 | 801 | ||
| 789 | /* Set the output file to the right size. Allocate a buffer to hold | 802 | /* Set the output file to the right size. Allocate a buffer to hold |
| 790 | the image of the new file. Set pointers to various interesting | 803 | the image of the new file. Set pointers to various interesting |
| 791 | objects. stat_buf still has old_file data. */ | 804 | objects. */ |
| 792 | 805 | ||
| 793 | new_file = open (new_name, O_RDWR | O_CREAT, 0666); | 806 | new_file = open (new_name, O_RDWR | O_CREAT, 0666); |
| 794 | if (new_file < 0) | 807 | if (new_file < 0) |
| 795 | fatal ("Can't creat (%s): errno %d\n", new_name, errno); | 808 | fatal ("Can't creat (%s): %s", new_name, strerror (errno)); |
| 796 | 809 | ||
| 797 | new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_incr; | 810 | new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr; |
| 798 | 811 | ||
| 799 | if (ftruncate (new_file, new_file_size)) | 812 | if (ftruncate (new_file, new_file_size)) |
| 800 | fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); | 813 | fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno)); |
| 801 | 814 | ||
| 802 | new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE, | 815 | new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE, |
| 803 | MAP_ANON | MAP_PRIVATE, mmap_fd, 0); | 816 | MAP_ANON | MAP_PRIVATE, mmap_fd, 0); |
| 804 | if (new_base == MAP_FAILED) | 817 | if (new_base == MAP_FAILED) |
| 805 | fatal ("Can't allocate buffer for %s\n", old_name, 0); | 818 | fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno)); |
| 806 | 819 | ||
| 807 | new_file_h = (ElfW (Ehdr) *) new_base; | 820 | new_file_h = (ElfW (Ehdr) *) new_base; |
| 808 | new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff); | 821 | new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff); |
| @@ -825,10 +838,10 @@ unexec (const char *new_name, const char *old_name) | |||
| 825 | new_file_h->e_shoff += new_data2_incr; | 838 | new_file_h->e_shoff += new_data2_incr; |
| 826 | new_file_h->e_shnum += 1; | 839 | new_file_h->e_shnum += 1; |
| 827 | 840 | ||
| 828 | #ifdef DEBUG | 841 | #ifdef UNEXELF_DEBUG |
| 829 | fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); | 842 | DEBUG_LOG (old_file_h->e_shoff); |
| 830 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); | 843 | fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); |
| 831 | fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); | 844 | DEBUG_LOG (new_file_h->e_shoff); |
| 832 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); | 845 | fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); |
| 833 | #endif | 846 | #endif |
| 834 | 847 | ||
| @@ -839,7 +852,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 839 | to adjust the offset and address of any segment that is above | 852 | to adjust the offset and address of any segment that is above |
| 840 | data2, just in case we decide to allow this later. */ | 853 | data2, just in case we decide to allow this later. */ |
| 841 | 854 | ||
| 842 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 855 | for (n = new_file_h->e_phnum; --n >= 0; ) |
| 843 | { | 856 | { |
| 844 | /* Compute maximum of all requirements for alignment of section. */ | 857 | /* Compute maximum of all requirements for alignment of section. */ |
| 845 | ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align; | 858 | ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align; |
| @@ -857,7 +870,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 857 | > (old_sbss_index == -1 | 870 | > (old_sbss_index == -1 |
| 858 | ? old_bss_addr | 871 | ? old_bss_addr |
| 859 | : round_up (old_bss_addr, alignment))) | 872 | : round_up (old_bss_addr, alignment))) |
| 860 | fatal ("Program segment above .bss in %s\n", old_name, 0); | 873 | fatal ("Program segment above .bss in %s", old_name); |
| 861 | 874 | ||
| 862 | if (NEW_PROGRAM_H (n).p_type == PT_LOAD | 875 | if (NEW_PROGRAM_H (n).p_type == PT_LOAD |
| 863 | && (round_up ((NEW_PROGRAM_H (n)).p_vaddr | 876 | && (round_up ((NEW_PROGRAM_H (n)).p_vaddr |
| @@ -867,7 +880,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 867 | break; | 880 | break; |
| 868 | } | 881 | } |
| 869 | if (n < 0) | 882 | if (n < 0) |
| 870 | fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); | 883 | fatal ("Couldn't find segment next to .bss in %s", old_name); |
| 871 | 884 | ||
| 872 | /* Make sure that the size includes any padding before the old .bss | 885 | /* Make sure that the size includes any padding before the old .bss |
| 873 | section. */ | 886 | section. */ |
| @@ -875,7 +888,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 875 | NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; | 888 | NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; |
| 876 | 889 | ||
| 877 | #if 0 /* Maybe allow section after data2 - does this ever happen? */ | 890 | #if 0 /* Maybe allow section after data2 - does this ever happen? */ |
| 878 | for (n = new_file_h->e_phnum - 1; n >= 0; n--) | 891 | for (n = new_file_h->e_phnum; --n >= 0; ) |
| 879 | { | 892 | { |
| 880 | if (NEW_PROGRAM_H (n).p_vaddr | 893 | if (NEW_PROGRAM_H (n).p_vaddr |
| 881 | && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) | 894 | && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) |
| @@ -894,7 +907,7 @@ unexec (const char *new_name, const char *old_name) | |||
| 894 | 907 | ||
| 895 | /* Walk through all section headers, insert the new data2 section right | 908 | /* Walk through all section headers, insert the new data2 section right |
| 896 | before the new bss section. */ | 909 | before the new bss section. */ |
| 897 | for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) | 910 | for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++) |
| 898 | { | 911 | { |
| 899 | caddr_t src; | 912 | caddr_t src; |
| 900 | /* If it is (s)bss section, insert the new data2 section before it. */ | 913 | /* If it is (s)bss section, insert the new data2 section before it. */ |
| @@ -1173,7 +1186,7 @@ temacs: | |||
| 1173 | } | 1186 | } |
| 1174 | 1187 | ||
| 1175 | /* Update the symbol values of _edata and _end. */ | 1188 | /* Update the symbol values of _edata and _end. */ |
| 1176 | for (n = new_file_h->e_shnum - 1; n; n--) | 1189 | for (n = new_file_h->e_shnum; 0 < --n; ) |
| 1177 | { | 1190 | { |
| 1178 | byte *symnames; | 1191 | byte *symnames; |
| 1179 | ElfW (Sym) *symp, *symendp; | 1192 | ElfW (Sym) *symp, *symendp; |
| @@ -1233,7 +1246,7 @@ temacs: | |||
| 1233 | 1246 | ||
| 1234 | /* This loop seeks out relocation sections for the data section, so | 1247 | /* This loop seeks out relocation sections for the data section, so |
| 1235 | that it can undo relocations performed by the runtime linker. */ | 1248 | that it can undo relocations performed by the runtime linker. */ |
| 1236 | for (n = new_file_h->e_shnum - 1; n; n--) | 1249 | for (n = new_file_h->e_shnum; 0 < --n; ) |
| 1237 | { | 1250 | { |
| 1238 | ElfW (Shdr) section = NEW_SECTION_H (n); | 1251 | ElfW (Shdr) section = NEW_SECTION_H (n); |
| 1239 | 1252 | ||
| @@ -1293,8 +1306,8 @@ temacs: | |||
| 1293 | /* Write out new_file, and free the buffers. */ | 1306 | /* Write out new_file, and free the buffers. */ |
| 1294 | 1307 | ||
| 1295 | if (write (new_file, new_base, new_file_size) != new_file_size) | 1308 | if (write (new_file, new_base, new_file_size) != new_file_size) |
| 1296 | fatal ("Didn't write %d bytes to %s: errno %d\n", | 1309 | fatal ("Didn't write %lu bytes to %s: %s", |
| 1297 | new_file_size, new_name, errno); | 1310 | (unsigned long) new_file_size, new_name, strerror (errno)); |
| 1298 | munmap (old_base, old_file_size); | 1311 | munmap (old_base, old_file_size); |
| 1299 | munmap (new_base, new_file_size); | 1312 | munmap (new_base, new_file_size); |
| 1300 | 1313 | ||
| @@ -1304,18 +1317,18 @@ temacs: | |||
| 1304 | close (mmap_fd); | 1317 | close (mmap_fd); |
| 1305 | #endif | 1318 | #endif |
| 1306 | 1319 | ||
| 1307 | if (close (old_file)) | 1320 | if (close (old_file) != 0) |
| 1308 | fatal ("Can't close (%s): errno %d\n", old_name, errno); | 1321 | fatal ("Can't close (%s): %s", old_name, strerror (errno)); |
| 1309 | 1322 | ||
| 1310 | if (close (new_file)) | 1323 | if (close (new_file) != 0) |
| 1311 | fatal ("Can't close (%s): errno %d\n", new_name, errno); | 1324 | fatal ("Can't close (%s): %s", new_name, strerror (errno)); |
| 1312 | 1325 | ||
| 1313 | if (stat (new_name, &stat_buf) == -1) | 1326 | if (stat (new_name, &stat_buf) != 0) |
| 1314 | fatal ("Can't stat (%s): errno %d\n", new_name, errno); | 1327 | fatal ("Can't stat (%s): %s", new_name, strerror (errno)); |
| 1315 | 1328 | ||
| 1316 | n = umask (777); | 1329 | n = umask (777); |
| 1317 | umask (n); | 1330 | umask (n); |
| 1318 | stat_buf.st_mode |= 0111 & ~n; | 1331 | stat_buf.st_mode |= 0111 & ~n; |
| 1319 | if (chmod (new_name, stat_buf.st_mode) == -1) | 1332 | if (chmod (new_name, stat_buf.st_mode) != 0) |
| 1320 | fatal ("Can't chmod (%s): errno %d\n", new_name, errno); | 1333 | fatal ("Can't chmod (%s): %s", new_name, strerror (errno)); |
| 1321 | } | 1334 | } |