aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1997-01-10 02:53:35 +0000
committerRichard M. Stallman1997-01-10 02:53:35 +0000
commitacacb2920929152a02f5836d39189b04cea08202 (patch)
treeac3c27a848aece275d542c9e1d675570ec46ab63 /src
parent1c626aaf749003439929908143e519befd64eb53 (diff)
downloademacs-acacb2920929152a02f5836d39189b04cea08202.tar.gz
emacs-acacb2920929152a02f5836d39189b04cea08202.zip
Include <mach-o/reloc.h>.
(fgrowth): Initialize to zero. (vmaddr_growth, dataseg_vmaddr, dataseg_vmend): New variables. [NS_TARGET] (extreloff, nextrel, dysymtab, reloc_info): New variables. (unexec_doit): Adjust file offsets of segments that follow the enlarged data segment. Adjust vmaddr of the SEG_LINKEDIT segment that follows the data segment. [NS_TARGET] (unexec_doit): Adjust file offsets in the LC_DYSYMTAB load command that follows the data segment. Zero out relocation entries that fall within the data segment.
Diffstat (limited to 'src')
-rw-r--r--src/unexnext.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/unexnext.c b/src/unexnext.c
index 66f52fa0352..1cf41ca05a1 100644
--- a/src/unexnext.c
+++ b/src/unexnext.c
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
27#include <stdarg.h> 27#include <stdarg.h>
28#include <mach/mach.h> 28#include <mach/mach.h>
29#include <mach-o/loader.h> 29#include <mach-o/loader.h>
30#include <mach-o/reloc.h>
30#include <sys/file.h> 31#include <sys/file.h>
31#include <sys/stat.h> 32#include <sys/stat.h>
32#include <libc.h> 33#include <libc.h>
@@ -243,7 +244,7 @@ unexec_doit(
243 struct load_command **the_commands = NULL; 244 struct load_command **the_commands = NULL;
244 unsigned the_commands_len; 245 unsigned the_commands_len;
245 struct mach_header the_header; 246 struct mach_header the_header;
246 int fgrowth; 247 int fgrowth = 0;
247 int fdatastart; 248 int fdatastart;
248 int fdatasize; 249 int fdatasize;
249 int size; 250 int size;
@@ -251,9 +252,18 @@ unexec_doit(
251 char *buf; 252 char *buf;
252 vm_address_t data_address; 253 vm_address_t data_address;
253 vm_size_t data_size; 254 vm_size_t data_size;
255 vm_size_t vmaddr_growth = 0;
256 vm_size_t dataseg_vmaddr, dataseg_vmend;
254 257
255 struct segment_command *segment; 258 struct segment_command *segment;
256 259
260#ifdef NS_TARGET
261 unsigned long extreloff = 0;
262 unsigned long nextrel = 0;
263 struct dysymtab_command *dysymtab;
264 struct relocation_info reloc_info;
265#endif
266
257 if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) { 267 if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) {
258 return (0); 268 return (0);
259 } 269 }
@@ -284,7 +294,17 @@ unexec_doit(
284 segment->filesize); 294 segment->filesize);
285 segment->vmsize = data_size; 295 segment->vmsize = data_size;
286 segment->filesize = data_size; 296 segment->filesize = data_size;
297 dataseg_vmaddr = segment->vmaddr;
298 dataseg_vmend = segment->vmaddr + segment->vmsize;
299 vmaddr_growth = segment->vmaddr + segment->vmsize;
300 } else {
301 ((struct segment_command *)the_commands[i])->fileoff += fgrowth;
302 }
303
304 if( strcmp( segment->segname, SEG_LINKEDIT ) == 0 ) {
305 segment->vmaddr = vmaddr_growth;
287 } 306 }
307
288 break; 308 break;
289 case LC_SYMTAB: 309 case LC_SYMTAB:
290 ((struct symtab_command *) 310 ((struct symtab_command *)
@@ -296,6 +316,15 @@ unexec_doit(
296 ((struct symseg_command *) 316 ((struct symseg_command *)
297 the_commands[i])->offset += fgrowth; 317 the_commands[i])->offset += fgrowth;
298 break; 318 break;
319#ifdef NS_TARGET
320 case LC_DYSYMTAB:
321 dysymtab = ((struct dysymtab_command *)the_commands[i]);
322 extreloff = dysymtab->extreloff;
323 nextrel = dysymtab->nextrel;
324 dysymtab->indirectsymoff += fgrowth;
325 dysymtab->extreloff += fgrowth;
326 break;
327#endif
299 default: 328 default:
300 break; 329 break;
301 } 330 }
@@ -382,6 +411,55 @@ unexec_doit(
382 return (0); 411 return (0);
383 } 412 }
384 free(buf); 413 free(buf);
414
415#ifdef NS_TARGET
416 /*
417 * Fix up relocation entries in the data segment.
418 */
419
420 if (lseek(infd, extreloff, L_SET) < 0) {
421 fatal_unexec("cannot seek input file");
422 return (0);
423 }
424
425 for (i = 0; i < nextrel; i++)
426 {
427 long zeroval = 0;
428
429 if (read(infd, &reloc_info, sizeof (reloc_info)) != sizeof (reloc_info)) {
430 fatal_unexec("cannot read input file");
431 return (0);
432 }
433 if (reloc_info.r_address >= dataseg_vmaddr && reloc_info.r_address < dataseg_vmend)
434 {
435 if (lseek (outfd, fdatastart + reloc_info.r_address - dataseg_vmaddr, L_SET) < 0 ) {
436 fatal_unexec("cannot seek input file");
437 return (0);
438 }
439 switch (reloc_info.r_length) {
440 case 0:
441 if (write(outfd, &zeroval, 1) != 1) {
442 fatal_unexec("cannot write output file");
443 return (0);
444 }
445 break;
446 case 1:
447 if (write(outfd, &zeroval, 2) != 2) {
448 fatal_unexec("cannot write output file");
449 return (0);
450 }
451 break;
452 case 2:
453 if (write(outfd, &zeroval, 4) != 4) {
454 fatal_unexec("cannot write output file");
455 return (0);
456 }
457 break;
458 }
459 }
460 }
461#endif
462
385 return (1); 463 return (1);
386} 464}
387 465