diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexmacosx.c | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 9db9622f6f5..43e1f5e805c 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c | |||
| @@ -174,7 +174,7 @@ off_t data_segment_old_fileoff; | |||
| 174 | 174 | ||
| 175 | struct segment_command *data_segment_scp; | 175 | struct segment_command *data_segment_scp; |
| 176 | 176 | ||
| 177 | /* Read n bytes from infd into memory starting at address dest. | 177 | /* Read N bytes from infd into memory starting at address DEST. |
| 178 | Return true if successful, false otherwise. */ | 178 | Return true if successful, false otherwise. */ |
| 179 | static int | 179 | static int |
| 180 | unexec_read (void *dest, size_t n) | 180 | unexec_read (void *dest, size_t n) |
| @@ -182,8 +182,9 @@ unexec_read (void *dest, size_t n) | |||
| 182 | return n == read (infd, dest, n); | 182 | return n == read (infd, dest, n); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | /* Write n bytes from memory starting at address src to outfd starting | 185 | /* Write COUNT bytes from memory starting at address SRC to outfd |
| 186 | at offset dest. Return true if successful, false otherwise. */ | 186 | starting at offset DEST. Return true if successful, false |
| 187 | otherwise. */ | ||
| 187 | static int | 188 | static int |
| 188 | unexec_write (off_t dest, const void *src, size_t count) | 189 | unexec_write (off_t dest, const void *src, size_t count) |
| 189 | { | 190 | { |
| @@ -193,8 +194,32 @@ unexec_write (off_t dest, const void *src, size_t count) | |||
| 193 | return write (outfd, src, count) == count; | 194 | return write (outfd, src, count) == count; |
| 194 | } | 195 | } |
| 195 | 196 | ||
| 196 | /* Copy n bytes from starting offset src in infd to starting offset | 197 | /* Write COUNT bytes of zeros to outfd starting at offset DEST. |
| 197 | dest in outfd. Return true if successful, false otherwise. */ | 198 | Return true if successful, false otherwise. */ |
| 199 | static int | ||
| 200 | unexec_write_zero (off_t dest, size_t count) | ||
| 201 | { | ||
| 202 | char buf[UNEXEC_COPY_BUFSZ]; | ||
| 203 | ssize_t bytes; | ||
| 204 | |||
| 205 | bzero (buf, UNEXEC_COPY_BUFSZ); | ||
| 206 | if (lseek (outfd, dest, SEEK_SET) != dest) | ||
| 207 | return 0; | ||
| 208 | |||
| 209 | while (count > 0) | ||
| 210 | { | ||
| 211 | bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count; | ||
| 212 | if (write (outfd, buf, bytes) != bytes) | ||
| 213 | return 0; | ||
| 214 | count -= bytes; | ||
| 215 | } | ||
| 216 | |||
| 217 | return 1; | ||
| 218 | } | ||
| 219 | |||
| 220 | /* Copy COUNT bytes from starting offset SRC in infd to starting | ||
| 221 | offset DEST in outfd. Return true if successful, false | ||
| 222 | otherwise. */ | ||
| 198 | static int | 223 | static int |
| 199 | unexec_copy (off_t dest, off_t src, ssize_t count) | 224 | unexec_copy (off_t dest, off_t src, ssize_t count) |
| 200 | { | 225 | { |
| @@ -684,14 +709,39 @@ copy_data_segment (struct load_command *lc) | |||
| 684 | if (!unexec_write (header_offset, sectp, sizeof (struct section))) | 709 | if (!unexec_write (header_offset, sectp, sizeof (struct section))) |
| 685 | unexec_error ("cannot write section %s's header", SECT_DATA); | 710 | unexec_error ("cannot write section %s's header", SECT_DATA); |
| 686 | } | 711 | } |
| 687 | else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0 | 712 | else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0) |
| 688 | || strncmp (sectp->sectname, SECT_COMMON, 16) == 0) | ||
| 689 | { | 713 | { |
| 690 | sectp->flags = S_REGULAR; | 714 | sectp->flags = S_REGULAR; |
| 691 | if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) | 715 | if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size)) |
| 692 | unexec_error ("cannot write section %s", SECT_DATA); | 716 | unexec_error ("cannot write section %s", sectp->sectname); |
| 693 | if (!unexec_write (header_offset, sectp, sizeof (struct section))) | 717 | if (!unexec_write (header_offset, sectp, sizeof (struct section))) |
| 694 | unexec_error ("cannot write section %s's header", SECT_DATA); | 718 | unexec_error ("cannot write section %s's header", sectp->sectname); |
| 719 | } | ||
| 720 | else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0) | ||
| 721 | { | ||
| 722 | extern char *my_endbss_static; | ||
| 723 | unsigned long my_size; | ||
| 724 | |||
| 725 | sectp->flags = S_REGULAR; | ||
| 726 | |||
| 727 | /* Clear uninitialized local variables in statically linked | ||
| 728 | libraries. In particular, function pointers stored by | ||
| 729 | libSystemStub.a, which is introduced in Mac OS X 10.4 for | ||
| 730 | binary compatibility with respect to long double, are | ||
| 731 | cleared so that they will be reinitialized when the | ||
| 732 | dumped binary is executed on other versions of OS. */ | ||
| 733 | my_size = (unsigned long)my_endbss_static - sectp->addr; | ||
| 734 | if (!(sectp->addr <= (unsigned long)my_endbss_static | ||
| 735 | && my_size <= sectp->size)) | ||
| 736 | unexec_error ("my_endbss_static is not in section %s", | ||
| 737 | sectp->sectname); | ||
| 738 | if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size)) | ||
| 739 | unexec_error ("cannot write section %s", sectp->sectname); | ||
| 740 | if (!unexec_write_zero (sectp->offset + my_size, | ||
| 741 | sectp->size - my_size)) | ||
| 742 | unexec_error ("cannot write section %s", sectp->sectname); | ||
| 743 | if (!unexec_write (header_offset, sectp, sizeof (struct section))) | ||
| 744 | unexec_error ("cannot write section %s's header", sectp->sectname); | ||
| 695 | } | 745 | } |
| 696 | else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0 | 746 | else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0 |
| 697 | || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0 | 747 | || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0 |