Mercurial > hg > xemacs-beta
diff src/unexcw.c @ 278:90d73dddcdc4 r21-0b37
Import from CVS: tag r21-0b37
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:31:29 +0200 |
parents | b2472a1930f2 |
children | 4711e16a8e49 |
line wrap: on
line diff
--- a/src/unexcw.c Mon Aug 13 10:30:38 2007 +0200 +++ b/src/unexcw.c Mon Aug 13 10:31:29 2007 +0200 @@ -67,6 +67,7 @@ /* Cached info about the .bss section in the executable. */ void* bss_start = UNINIT_PTR; unsigned long bss_size = UNINIT_LONG; +int sections_reversed = 0; FILHDR f_hdr; PEAOUTHDR f_ohdr; SCNHDR f_data, f_bss, f_text, f_nextdata; @@ -155,11 +156,12 @@ PERROR (a_name); } } - /* Loop through .data & .bss section headers, copying them in */ + /* Loop through .data & .bss section headers, copying them in. + With newer lds these are reversed so we have to cope with both */ lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0); if (read (a_out, &f_text, sizeof (f_text)) != sizeof (f_text) - && + || strcmp (f_text.s_name, ".text")) { PERROR ("no .text section"); @@ -167,12 +169,40 @@ /* The .bss section. */ if (read (a_out, &f_bss, sizeof (f_bss)) != sizeof (f_bss) - && - strcmp (f_bss.s_name, ".bss")) + || + (strcmp (f_bss.s_name, ".bss") && strcmp (f_bss.s_name, ".data"))) { - PERROR ("no .bss section"); + PERROR ("no .bss / .data section"); + } + + /* check for reversed .bss and .data */ + if (!strcmp(f_bss.s_name, ".data")) + { + printf(".data and .bss reversed\n"); + sections_reversed = 1; + memcpy(&f_data, &f_bss, sizeof(f_bss)); } + /* The .data section. */ + if (!sections_reversed) + { + if (read (a_out, &f_data, sizeof (f_data)) != sizeof (f_data) + || + strcmp (f_data.s_name, ".data")) + { + PERROR ("no .data section"); + } + } + else + { + if (read (a_out, &f_bss, sizeof (f_bss)) != sizeof (f_bss) + || + strcmp (f_bss.s_name, ".bss")) + { + PERROR ("no .bss section"); + } + } + bss_start = (void *) ((char*)f_ohdr.ImageBase + f_bss.s_vaddr); bss_size = (unsigned long)((char*)&my_ebss-(char*)bss_start); @@ -180,14 +210,6 @@ printf("found bss - keeping %lx of %lx bytes\n", bss_size, f_ohdr.bsize); /* The .data section. */ - if (read (a_out, &f_data, sizeof (f_data)) != sizeof (f_data) - && - strcmp (f_data.s_name, ".data")) - { - PERROR ("no .data section"); - } - - /* The .data section. */ data_start_va = (void *) ((char*)f_ohdr.ImageBase + f_data.s_vaddr); /* We want to only write Emacs data back to the executable, @@ -195,8 +217,9 @@ then a dumped Emacs won't run on system versions other than the one Emacs was dumped on). */ data_size = (unsigned long)my_edata - (unsigned long)data_start_va; + printf("found data - keeping %lx of %lx bytes\n", data_size, f_ohdr.dsize); - /* The following data section. */ + /* The following data section - often .idata */ if (read (a_out, &f_nextdata, sizeof (f_nextdata)) != sizeof (f_nextdata) && strcmp (&f_nextdata.s_name[2], "data")) @@ -211,8 +234,13 @@ copy_executable_and_dump_data_section (int a_out, int a_new) { long size=0; - unsigned long new_data_size, new_bss_size, f_data_s_vaddr, - file_sz_change, f_data_s_scnptr, bss_padding; + unsigned long new_data_size, new_bss_size, + bss_padding, file_sz_change, data_padding=0, + f_data_s_vaddr = f_data.s_vaddr, + f_data_s_scnptr = f_data.s_scnptr, + f_bss_s_vaddr = f_bss.s_vaddr, + f_nextdata_s_scnptr = f_nextdata.s_scnptr; + int i; void* empty_space; extern int static_heap_dumped; @@ -230,14 +258,27 @@ f_data.s_vaddr is f_bss.s_vaddr f_data.s_size is new dsize maybe. what about s_paddr & s_scnptr? */ + /* this is the amount the file increases in size */ - new_bss_size=f_data.s_vaddr - f_bss.s_vaddr; - file_sz_change=new_bss_size; - new_data_size=f_ohdr.dsize + new_bss_size; - f_data_s_scnptr = f_data.s_scnptr; - f_data_s_vaddr = f_data.s_vaddr; - f_data.s_vaddr = f_bss.s_vaddr; - f_data.s_paddr += new_bss_size; + if (!sections_reversed) + { + new_bss_size = f_data.s_vaddr - f_bss.s_vaddr; + data_padding = 0; + } + else + { + new_bss_size = f_nextdata.s_vaddr - f_bss.s_vaddr; + data_padding = (f_bss.s_vaddr - f_data.s_vaddr) - f_data.s_size; + } + + file_sz_change=new_bss_size + data_padding; + new_data_size=f_ohdr.dsize + file_sz_change; + + if (!sections_reversed) + { + f_data.s_vaddr = f_bss.s_vaddr; + } + f_data.s_paddr += file_sz_change; #if 0 if (f_data.s_size + f_nextdata.s_size != f_ohdr.dsize) { @@ -245,7 +286,7 @@ f_data.s_size + f_nextdata.s_size, f_ohdr.dsize); } #endif - f_data.s_size += new_bss_size; + f_data.s_size += file_sz_change; lseek (a_new, 0, SEEK_SET); /* write file header */ f_hdr.f_symptr += file_sz_change; @@ -331,24 +372,27 @@ CHECK_AOUT_POS(f_data_s_scnptr); - /* dump bss + padding between sections */ - printf ("dumping .bss into executable... %lx bytes\n", bss_size); - if (write(a_new, bss_start, bss_size) != (int)bss_size) + if (!sections_reversed) { - PERROR("failed to write bss section"); + /* dump bss + padding between sections */ + printf ("dumping .bss into executable... %lx bytes\n", bss_size); + if (write(a_new, bss_start, bss_size) != (int)bss_size) + { + PERROR("failed to write bss section"); + } + + /* pad, needs to be zero */ + bss_padding = new_bss_size - bss_size; + printf ("padding .bss ... %lx bytes\n", bss_padding); + empty_space = malloc(bss_padding); + memset(empty_space, 0, bss_padding); + if (write(a_new, empty_space, bss_padding) != (int)bss_padding) + { + PERROR("failed to write bss section"); + } + free(empty_space); } - /* pad, needs to be zero */ - bss_padding = new_bss_size - bss_size; - printf ("padding .bss ... %lx bytes\n", bss_padding); - empty_space = malloc(bss_padding); - memset(empty_space, 0, bss_padding); - if (write(a_new, empty_space, bss_padding) != (int)bss_padding) - { - PERROR("failed to write bss section"); - } - free(empty_space); - /* tell dumped version not to free pure heap */ static_heap_dumped = 1; /* Get a pointer to the raw data in our address space. */ @@ -361,11 +405,48 @@ static_heap_dumped = 0; size = lseek(a_out, f_data_s_scnptr + data_size, SEEK_SET); - size = f_nextdata.s_scnptr - size; - dup_file_area(a_out, a_new, size); + + if (!sections_reversed) + { + size = f_nextdata_s_scnptr - size; + dup_file_area(a_out, a_new, size); + } + else + { + /* need to bad to bss with data in file */ + printf ("padding .data ... %lx bytes\n", data_padding); + size = (f_bss_s_vaddr - f_data_s_vaddr) - data_size; + dup_file_area(a_out, a_new, size); - // lseek(a_out, f_nextdata.s_scnptr, SEEK_CUR); - CHECK_AOUT_POS(f_nextdata.s_scnptr); + /* dump bss + padding between sections */ + printf ("dumping .bss into executable... %lx bytes\n", bss_size); + if (write(a_new, bss_start, bss_size) != (int)bss_size) + { + PERROR("failed to write bss section"); + } + + /* pad, needs to be zero */ + bss_padding = new_bss_size - bss_size; + printf ("padding .bss ... %lx bytes\n", bss_padding); + empty_space = malloc(bss_padding); + memset(empty_space, 0, bss_padding); + if (write(a_new, empty_space, bss_padding) != (int)bss_padding) + { + PERROR("failed to write bss section"); + } + free(empty_space); + if (lseek(a_new, 0, SEEK_CUR) != f_nextdata.s_scnptr) + { + printf("at %lx should be at %lx\n", + lseek(a_new, 0, SEEK_CUR), + f_nextdata.s_scnptr); + PERROR("file positioning error\n"); + } + lseek(a_out, f_nextdata_s_scnptr, SEEK_SET); + } + + CHECK_AOUT_POS(f_nextdata_s_scnptr); + /* now dump - nextdata don't need to do this cygwin ds is in .data! */ printf ("dumping following data section... %lx bytes\n", f_nextdata.s_size); @@ -374,8 +455,8 @@ /* write rest of file */ printf ("writing rest of file\n"); size = lseek(a_out, 0, SEEK_END); - size = size - (f_nextdata.s_scnptr + f_nextdata.s_size); /* length remaining in a_out */ - lseek(a_out, f_nextdata.s_scnptr + f_nextdata.s_size, SEEK_SET); + size = size - (f_nextdata_s_scnptr + f_nextdata.s_size); /* length remaining in a_out */ + lseek(a_out, f_nextdata_s_scnptr + f_nextdata.s_size, SEEK_SET); dup_file_area(a_out, a_new, size); }