Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / writeBackElf.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /* -*- Mode: C; indent-tabs-mode: true -*- */
33 /* $Id: writeBackElf.C,v 1.34 2008/06/20 22:00:05 legendre Exp $ */
34
35 #if defined(sparc_sun_solaris2_4) \
36  || defined(i386_unknown_linux2_0) \
37  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
38
39 #include "dyninstAPI/src/process.h"
40 #include "writeBackElf.h"
41
42 #define MALLOC 0 
43 #define DYNAMIC 1 
44
45 const char* mkstemp_postfix = "XXXXXX";
46
47 //unsigned int elf_version(unsigned int);
48
49 // This constructor opens both the old and new
50 // ELF files 
51 writeBackElf::writeBackElf(const char *oldElfName, const char* newElfName, 
52                            int debugOutputFlag) : newSections(NULL), newSectionsSize(0) {
53
54         if((oldfd = open(oldElfName, O_RDONLY)) == -1){
55                 bperr(" OLDELF_OPEN_FAIL %s",oldElfName);
56                 return;
57         }
58         if((newfd = (open(newElfName, O_WRONLY|O_CREAT)))==-1){
59                 bperr("NEWELF_OPEN_FAIL %s", newElfName);
60                 char fileName[strlen(newElfName) + strlen(mkstemp_postfix)];
61                 strcpy(fileName, newElfName);
62                 strcpy(fileName + strlen(newElfName), mkstemp_postfix);
63                 newfd = mkstemp(fileName);
64                 fflush(stdout);
65                 if(newfd == -1){
66                         bperr("NEWELF_OPEN_FAIL %s. clean up /tmp/dyninstMutatee*\n",
67                                          newElfName);
68                         return; 
69                 }
70         }
71
72         if(elf_version(EV_CURRENT) == EV_NONE){
73
74                 bpfatal(" elf_version failed!\n");
75         } 
76         if ((oldElf = elf_begin(oldfd, ELF_C_READ, NULL)) == NULL){
77                 bperr("OLDELF_BEGIN_FAIL");
78                 fflush(stdout);
79                 return;
80         }
81         if((newElf = elf_begin(newfd, ELF_C_WRITE, NULL)) == NULL){
82                 elf_end(oldElf);
83                 bperr("NEWELF_BEGIN_FAIL");
84                 fflush(stdout);
85                 return;
86         }
87         //elf_flagelf(newElf, ELF_C_SET, ELF_F_LAYOUT);
88         DEBUG_MSG = debugOutputFlag;
89         pageSize = getpagesize();
90         if(!DYNAMIC){
91                 if(MALLOC){
92                         newSections = (ELF_Section*) malloc(sizeof(ELF_Section) * 10);
93                 }else{
94                         newSections = new ELF_Section[10];
95                 }
96                 memset(newSections,'\0', sizeof(ELF_Section) * 10);
97         }       
98         fflush(stdout);
99         mutateeProcess = NULL;
100         mutateeTextSize = 0;
101         mutateeTextAddr = 0;
102         elf_fill(0);
103         newHeapAddr = 0;
104         newHeapAddrIncr = 0;
105         newElfNewData_d_buf = NULL;
106         newElfNewData_d_buf_count = 0;
107         parseOldElf();
108 }
109
110
111 writeBackElf::~writeBackElf(){
112
113         if(newSections){
114                 if(MALLOC){
115                         for(unsigned int i = 0;i<newSectionsSize;i++){
116                                 free(newSections[i].data);
117                         }
118                         free(newSections);
119                 }else{
120                         for(unsigned int i = 0;i<newSectionsSize;i++){
121                                 delete [] (char*) newSections[i].data;
122                                 delete [] (char*) newSections[i].name; 
123                         }
124                         delete [] newSections;
125                 }
126         }
127         if(newElfNewData_d_buf){
128                 if(MALLOC){
129                         for(int i = 0;i<newElfNewData_d_buf_count;i++){
130                                 if( newElfNewData_d_buf[i] ){
131                                         free(newElfNewData_d_buf[i]);
132                                 }
133                         }
134                         free(newElfNewData_d_buf);
135                 }else{
136                         for(int i = 0;i<newElfNewData_d_buf_count;i++){
137                                 if( newElfNewData_d_buf[i] ){
138                                         delete [] (char*) newElfNewData_d_buf[i];
139                                 }
140                         }
141                         delete [] newElfNewData_d_buf;
142                 }
143         }
144
145         //elf_end(newElf); //closed in addLibrary::driver()
146         P_close(newfd);
147
148         P_close(oldfd);
149         elf_end(oldElf);
150 }
151
152
153 Elf* writeBackElf::getElf(){
154         return newElf;
155 }
156
157 int writeBackElf::addSection(unsigned int addr, void *data, unsigned int dataSize, const char* name, bool loadable) {
158         ELF_Section *tmp;
159         ELF_Section *newSection;
160         if(DYNAMIC){
161
162                 if(MALLOC){
163                         tmp= (ELF_Section*) malloc(sizeof(ELF_Section) * (newSectionsSize+1));
164                 }else{
165                         tmp = new ELF_Section[newSectionsSize+1];
166                 }
167                 memset(tmp, '\0', sizeof(ELF_Section) * (newSectionsSize+1));
168                 if(newSections){
169                         memcpy(tmp, newSections, sizeof(ELF_Section) * (newSectionsSize));
170                         if(MALLOC){
171                                 free(newSections);
172                         }else{
173                                 delete [] newSections;
174                         }
175                 }
176                 newSections = tmp;
177         }       
178         newSection = &newSections[newSectionsSize];
179         newSection->vaddr = addr;
180         newSection->loadable = loadable;
181         if(MALLOC){
182                 newSection->data =  malloc(dataSize);
183         }else{
184                 newSection->data = new char[dataSize];
185         } 
186         memcpy(newSection->data, data,dataSize); //INSURE memory block passed to memcpy overlap
187         newSection->dataSize = dataSize;
188         newSection->shdr = NULL;
189         newSection->name = new char[strlen(name)+1];
190         memcpy(newSection->name, name, strlen(name)+1);
191         newSection->nameIndx = 0;
192         if(DEBUG_MSG){
193                 bpinfo(" ADDED SECTION: %x %x\n", newSection->vaddr,
194                                  *(unsigned int*)newSection->data);
195         }
196         return ++newSectionsSize;
197 }
198
199 //This method updates the symbol table,
200 //it shifts each symbol address as necessary AND
201 //sets _end and _END_ to move the heap
202 void writeBackElf::updateSymbols(Elf_Data* symtabData,Elf_Data* strData){
203
204         if( symtabData && strData){
205
206                 Elf32_Sym *symPtr=(Elf32_Sym*)symtabData->d_buf;
207                 
208                 for(unsigned int i=0;i< symtabData->d_size/(sizeof(Elf32_Sym));i++,symPtr++){
209                                                 
210                         if( newHeapAddr && !(strcmp("_end", (char*) strData->d_buf + symPtr->st_name))){
211                                 newHeapAddrIncr = newHeapAddr - symPtr->st_value ;
212                                 symPtr->st_value = newHeapAddr;
213                         }
214
215                         if( newHeapAddr &&  !(strcmp("_END_", (char*) strData->d_buf + symPtr->st_name))){
216                                 newHeapAddrIncr = newHeapAddr - symPtr->st_value ;
217                                 symPtr->st_value = newHeapAddr; 
218                         }
219                         
220                 }
221         }
222 }
223
224
225 //This is the main processing loop, called from outputElf()
226 void writeBackElf::driver(){
227
228         Elf32_Shdr *newsh, *shdr;
229         Elf_Scn *scn, *newScn; 
230         Elf32_Ehdr *ehdr ;//= elf32_getehdr(oldElf);
231         Elf_Data *data = NULL, *newdata = NULL, *olddata = NULL;
232         //important data sections in the
233         //new Elf that need updated
234         Elf_Data *textData, *symStrData, *dynStrData, *symTabData, *dynsymData, *dataData;
235
236         ehdr = elf32_getehdr(oldElf);
237         if(!(newEhdr = elf32_newehdr(newElf))){
238                 bperr("newEhdr failed\n");
239                 exit(1);
240         }
241
242
243         if (((ehdr = elf32_getehdr(oldElf)) != NULL)){ 
244                 if((scn = elf_getscn(oldElf, ehdr->e_shstrndx)) != NULL){
245                         if((data = elf_getdata(scn, NULL)) == NULL){
246                                 bperr(" Failed obtaining .shstrtab data buffer \n");
247                                 exit(1);
248                         }
249                 }else{
250                         bperr(" FAILED obtaining .shstrtab scn\n");             
251                 }
252         }else{
253                 bperr(" FAILED obtaining .shstrtab ehdr\n");
254         }
255         memcpy(newEhdr, ehdr, sizeof(Elf32_Ehdr));
256
257         newElfNewData_d_buf_count = newEhdr->e_shnum+1;
258         if( MALLOC ) {
259                 newElfNewData_d_buf = (char**) malloc(sizeof(char*) * (newEhdr->e_shnum+1));
260         }else{
261                 newElfNewData_d_buf = new char*[newEhdr->e_shnum+1];
262         }
263         memset(newElfNewData_d_buf, '\0', (newEhdr->e_shnum+1) *sizeof(char*));
264
265         scn = NULL;
266         int currentOffset=-1;
267         for (int cnt = 1; (scn = elf_nextscn(oldElf, scn)); cnt++) {
268                 //copy sections from oldElf to newElf.
269         
270                 shdr = elf32_getshdr(scn);
271                 newScn = elf_newscn(newElf);
272                 newsh = elf32_getshdr(newScn);
273                 newdata = elf_newdata(newScn);
274                 olddata = elf_getdata(scn,NULL);
275                 memcpy(newsh, shdr, sizeof(Elf32_Shdr));
276                 memcpy(newdata,olddata, sizeof(Elf_Data));
277                 if(currentOffset == -1){
278                         currentOffset = shdr->sh_offset;
279                 }
280
281                 //copy data buffer from oldElf 
282                 if(olddata->d_buf){
283                         if(MALLOC){
284                                 newdata->d_buf = (char*) malloc(olddata->d_size);
285                         }else{
286                                 newdata->d_buf = new char[olddata->d_size]; 
287                         } 
288                         newElfNewData_d_buf[cnt] = (char*) newdata->d_buf; 
289                         memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
290                 }
291
292                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".strtab")){
293                         symStrData = newdata;
294                         elf_update(newElf,ELF_C_NULL);
295                         updateSymbols(symTabData, symStrData);
296                 }
297                 
298
299                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".dynstr")){
300                         dynStrData = newdata;
301                         updateSymbols(dynsymData, dynStrData);
302                 }
303                 
304                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".symtab")){
305                         if(newsh->sh_link >= insertPoint){
306                                 newsh->sh_link += newSectionsSize;
307                         }
308                         symTabData = newdata;
309                 }
310                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".dynsym")){
311                         dynsymData = newdata;
312                 }
313                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".text")){
314                         textData = newdata;
315                         if(mutateeProcess){
316                                 mutateeProcess->readTextSpace((const void*) (long) newsh->sh_addr, newdata->d_size, 
317                                                                                                                 (void*)newdata->d_buf);
318                                 
319                         }
320                         startAddr = newsh->sh_addr;
321                         endAddr = newsh->sh_addr + newsh->sh_size;
322                         textSh = newsh; 
323                 }
324                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".bss")){
325                         createSections();
326                 }
327                 
328                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".shstrtab")){
329                         addSectionNames(newdata,olddata);
330                         newElfNewData_d_buf[cnt] = (char*) newdata->d_buf; 
331                 }
332                 if(!strcmp( (char *)data->d_buf + shdr->sh_name, ".data")){
333                         dataData = newdata;
334                         dataStartAddress = newsh->sh_addr;
335                         elf_update(newElf,ELF_C_NULL);
336                 }
337         }
338
339         
340         Elf32_Phdr *tmp;
341         
342         tmp = elf32_getphdr(oldElf);
343         newEhdr->e_phnum= ehdr->e_phnum; 
344         newPhdr=elf32_newphdr(newElf,newEhdr->e_phnum);
345         
346         memcpy(newPhdr, tmp, (ehdr->e_phnum) * ehdr->e_phentsize);
347         newEhdr->e_shstrndx+=newSectionsSize;
348         
349         fixPhdrs(newPhdr);
350 }
351
352 void writeBackElf::parseOldElf(){
353
354
355         Elf_Scn *scn;
356         Elf32_Shdr *shdr;
357         Elf32_Ehdr *ehdr;
358         Elf_Data *data;
359         
360         insertPoint = 0;
361
362
363         if (((ehdr = elf32_getehdr(oldElf)) != NULL)){
364                 if((scn = elf_getscn(oldElf, ehdr->e_shstrndx)) != NULL){
365                         if((data = elf_getdata(scn, NULL)) == NULL){
366                                 bperr(" Failed obtaining .shstrtab data buffer \n");
367                                 exit(1);
368                         }
369                 }else{
370                         bperr(" FAILED obtaining .shstrtab scn\n");
371                 }
372         }else{
373                 bperr(" FAILED obtaining .shstrtab ehdr\n");
374         }
375         
376         
377         
378
379         if (((ehdr = elf32_getehdr(oldElf)) == NULL) ||
380                  ((scn = elf_getscn(oldElf, ehdr->e_shstrndx)) == NULL) ||
381                  ((data = elf_getdata(scn, NULL)) == NULL)){
382                 bpfatal(" Failed obtaining .shstrtab data buffer \n");
383                 exit(1);
384         }
385         
386         scn = NULL;
387         for (int cnt = 1; !insertPoint && (scn = elf_nextscn(oldElf, scn)); cnt++) {
388                 shdr = elf32_getshdr(scn);
389                 if(!(strcmp(".bss",(char*) data->d_buf + shdr->sh_name))){
390                         insertPoint = cnt;
391                         lastAddr = shdr->sh_addr + shdr->sh_size;
392                         oldLastPage = lastAddr / pageSize;
393                 }                       
394         }
395         //oldLastPage = 0;      // ccw 20 mar
396 }
397
398 bool writeBackElf::createElf(){
399         unsigned int i;
400         for(i=0;i< newSectionsSize ;i++){
401
402         /* move the heap address beyond the last dyninstAPI_######## section */
403                 if( newSections[i].name ){
404                         char *strStart = strstr(newSections[i].name,"dyninstAPI_");
405
406                         if(strStart){
407                                 strStart =  strstr(newSections[i].name,"_");
408                                 strStart ++;
409                                 /*make sure this is a dyninstAPI_######## section*/
410                                 if( *strStart>=0x30 && *strStart <= 0x39 ) {
411
412                                         newHeapAddr = newSections[i].vaddr +newSections[i].dataSize;
413
414                                         while(newHeapAddr % pageSize){
415                                                 newHeapAddr++;
416                                         }
417                                 }
418
419                         }
420
421                 }
422         }
423
424         driver();
425         return true;
426 }
427
428  
429 void writeBackElf::createSections(){
430
431 //newSections
432 //lets assume that newSections is sorted on vaddr
433
434         Elf_Scn *newScn;
435         Elf32_Shdr *newsh;
436         Elf_Data *newdata;
437
438         unsigned int i=0;
439 /*  this is the expansion of the bss section ccw 20 mar 
440     it is not longer needed
441
442         if(oldLastPage == newSections[0].vaddr/pageSize){
443                 bssSh->sh_size = newSections[0].vaddr - bssSh->sh_addr;// + newSections[0].dataSize;
444                 void *tmpBuf;
445                 if(MALLOC){
446                         tmpBuf = malloc(bssSh->sh_size);
447                 }else{
448                         tmpBuf = (void*) new char[bssSh->sh_size];
449                 }
450                 memset(tmpBuf, '\0', bssSh->sh_size);
451                 if(bssData->d_buf){
452                         memcpy(tmpBuf, bssData->d_buf, bssData->d_size);
453                 }
454                 bssData->d_size = bssSh->sh_size;
455
456
457                 delete [] (char*)bssData->d_buf; 
458                 bssData->d_buf = tmpBuf;
459                 bssSh->sh_type = SHT_PROGBITS;
460                 elf_update(newElf,ELF_C_NULL);
461         }
462 */
463
464         for(;i<newSectionsSize;i++){
465                 if(DEBUG_MSG){
466                         bpinfo("ADDING SECTION");
467                 }
468                 newScn = elf_newscn(newElf);
469                 newsh = elf32_getshdr(newScn);
470                 newdata = elf_newdata(newScn);
471                 newSections[i].shdr=newsh;
472                 elf_update(newElf,ELF_C_NULL);
473                 newsh->sh_addr = newSections[i].vaddr;
474                 newsh->sh_size = newSections[i].dataSize;
475                 newsh->sh_addralign = 0x4;//newSections[i].align;
476                 if(newSections[i].loadable){
477                         newsh->sh_flags=  SHF_EXECINSTR | SHF_WRITE | SHF_ALLOC ;//newSections[i].flags;
478                         newsh->sh_type = SHT_PROGBITS;//newSections[i].type; 
479                 }else{
480                         newsh->sh_flags = 0;
481                         newsh->sh_type = SHT_PROGBITS; //SHT_NOTE
482                 }
483                 /*if(MALLOC){
484                         newdata->d_buf = (char*)malloc(newSections[i].dataSize);
485                 }else{
486                         newdata->d_buf = new char[newSections[i].dataSize]; 
487                 }
488                 memset(newdata->d_buf,'\0',newSections[i].dataSize);
489                 newdata->d_size = newSections[i].dataSize;
490                 memcpy((char*) newdata->d_buf, (char*) newSections[i].data, newdata->d_size);*/
491
492                 newdata->d_buf = newSections[i].data; 
493                 newdata->d_size = newSections[i].dataSize;
494
495                 elf_update(newElf, ELF_C_NULL);
496                 if(DEBUG_MSG){
497                         bpinfo("ADDED: size %lx Addr %lx size %x data; %x\n",newsh->sh_size, newsh->sh_addr,
498                                          newdata->d_size,*(unsigned int*) newdata->d_buf);
499                 }
500         }
501 }
502
503
504 void writeBackElf::addSectionNames(Elf_Data *newdata, Elf_Data*olddata){
505
506         int totalSize = olddata->d_size;
507         for(unsigned int i=0;i<newSectionsSize;i++){
508                 totalSize += (strlen(newSections[i].name)+1);
509         }
510         if(MALLOC){
511                 free(newdata->d_buf);
512         }else{
513                 delete [](char*) newdata->d_buf;
514         }
515         if(MALLOC){
516                 newdata->d_buf = (char*) malloc(totalSize);
517         }else{
518                 newdata->d_buf =new char[totalSize]; 
519         }
520         memset(newdata->d_buf,'\0', totalSize);
521         memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
522
523         int currLoc = olddata->d_size;
524         for(unsigned int k=0;k<newSectionsSize;k++){
525                 memcpy(&( ((char*)newdata->d_buf)[currLoc]), 
526                                  newSections[k].name,strlen(newSections[k].name)+1);
527                 if(newSections[k].shdr){
528                         newSections[k].shdr->sh_name = currLoc;
529                 }
530                 currLoc += (strlen(newSections[k].name)+1);
531                 newdata->d_size += (strlen(newSections[k].name)+1);
532         }
533 }
534
535
536 void writeBackElf::fixPhdrs(Elf32_Phdr * phdr){ 
537
538         elf_update(newElf, ELF_C_NULL);
539         unsigned int i=0;
540         if(oldLastPage == newSections[0].vaddr/pageSize){
541                 i=1;
542         }
543
544         /* find the second loadable section and extend it */
545         while(phdr->p_type != PT_NULL && phdr->p_type != PT_LOAD ){
546                 phdr++;
547         }       
548         phdr++;
549
550         while(phdr->p_type != PT_NULL && phdr->p_type != PT_LOAD ){
551                 phdr++;
552         }       
553         if( phdr->p_type == PT_LOAD ){
554                 phdr->p_memsz += newHeapAddrIncr;
555         }
556
557 #if  0  
558  defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
559
560         /*      on LINUX we may have a STACK section in the PHT (PT_GNU_STACK) 
561                 if we do, remove it
562         */
563
564         while(phdr->p_type != PT_NULL && phdr->p_type != PT_GNU_STACK ){
565                 phdr ++;
566         }
567         phdr->p_type = PT_NULL;
568                 
569 #endif
570                 
571 }
572
573
574 void writeBackElf::compactLoadableSections(pdvector <imageUpdate*> imagePatches,
575                                                                                                                  pdvector<imageUpdate*> &newPatches){
576         int startPage, stopPage;
577         imageUpdate *patch;
578         //this function now returns only ONE section that is loadable.
579
580         imageUpdate *curr, *next;
581         bool foundDup=true;
582         unsigned int j;
583
584         VECTOR_SORT(imagePatches, imageUpdateSort);
585
586         if(imagePatches.size() == 0){
587                 return;
588         }
589
590         while(foundDup){
591                 foundDup = false;
592                 j =0;
593                 while(imagePatches[j]->address==0 && j < imagePatches.size()){
594                         j++;
595                 }
596                 curr = imagePatches[j];
597                 
598                 for(j++;j<imagePatches.size();j++){
599                         next = imagePatches[j];         
600                         if(curr->address == next->address){
601                                 //duplicate
602                                 //find which is bigger and save that one.
603                                 if(curr->size > next->size){
604                                         next->address=0;
605                                 }else{
606                                         curr->address=0;
607                                         curr=next;
608                                 }
609                                 foundDup =true;
610                         }else{
611                                 curr=next;
612                         }
613
614                 }
615                 VECTOR_SORT(imagePatches, imageUpdateSort);
616         }
617
618
619         for(unsigned int i=0;i<imagePatches.size();i++){
620                 if(imagePatches[i]->address!=0){
621                         imagePatches[i]->startPage = imagePatches[i]->address- imagePatches[i]->address%pageSize;
622                         imagePatches[i]->stopPage = imagePatches[i]->address + imagePatches[i]->size- 
623                                 (imagePatches[i]->address + imagePatches[i]->size )%pageSize;
624
625                 }
626         }
627
628         foundDup = true;
629
630         while(foundDup){
631                 foundDup = false;
632                 j =0;
633                 while(imagePatches[j]->address==0 && j < imagePatches.size()){
634                         j++;
635                 }
636                 imagePatches.erase(0,j-1);
637                 j=0;
638                 for(;j<imagePatches.size()-1;j++){
639                         if(imagePatches[j]->stopPage > imagePatches[j+1]->startPage){
640                                 foundDup = true;
641                                 if(imagePatches[j]->stopPage > imagePatches[j+1]->stopPage){
642                                         imagePatches[j+1]->address = 0; 
643                                 }else{
644                                         
645                                         imagePatches[j]->size = (imagePatches[j+1]->address + imagePatches[j+1]->size) -
646                                                 imagePatches[j]->address;
647                                         imagePatches[j+1]->address = 0; 
648                                         imagePatches[j]->stopPage = imagePatches[j]->address + imagePatches[j]->size-
649                                                 (imagePatches[j]->address + imagePatches[j]->size )%pageSize;           
650                                 }
651                         }  
652                 }
653                 VECTOR_SORT(imagePatches, imageUpdateSort);
654         }
655
656         unsigned int k=0;
657
658         while(imagePatches[k]->address==0 && k < imagePatches.size()){
659                 k++;
660         }
661
662         startPage = imagePatches[k]->startPage;
663         stopPage = imagePatches[imagePatches.size()-1]->stopPage;
664         int startIndex=k, stopIndex=imagePatches.size()-1;
665         /*if(DEBUG_MSG){
666                 bpinfo("COMPACTING....\n");     
667                 bpinfo("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
668         }
669         patch = new imageUpdate;
670         patch->address = imagePatches[startIndex]->address;
671         patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
672                                    imagePatches[stopIndex]->size;
673         newPatches.push_back(patch);
674         if(DEBUG_MSG){
675                 bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
676         }*/
677         bool finished = false;
678         if(DEBUG_MSG){
679                 bperr("COMPACTING....\n");      
680                 bperr("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
681         }
682         for(;k<imagePatches.size();k++){
683                 if(imagePatches[k]->address!=0){
684                         if(DEBUG_MSG){
685                                 bperr("COMPACTING k[start] %x k[stop] %x stop %x addr %x size %x\n", imagePatches[k]->startPage, 
686                                                  imagePatches[k]->stopPage,stopPage, imagePatches[k]->address, imagePatches[k]->size);
687                         }
688                         if(imagePatches[k]->startPage <= (unsigned int) stopPage){
689                                 stopIndex = k;
690                                 stopPage = imagePatches[k]->stopPage;
691                         }else{
692                                 
693                                 patch = new imageUpdate;
694                                 patch->address = imagePatches[startIndex]->address;
695                                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address + 
696                                                 imagePatches[stopIndex]->size;
697                                 newPatches.push_back(patch);
698                                 if(DEBUG_MSG){
699                                         bperr(" COMPACTED: address %x --> %x    start %x  stop %x\n", 
700                                                          patch->address, patch->size, startPage,  stopPage);
701                                 }
702                                 finished = true;
703                                 //was k+1       
704                                 if(k < imagePatches.size()){
705                                         while(imagePatches[k]->address==0 && k < imagePatches.size()){
706                                                 k++;
707                                         }
708                                         startIndex = k;
709                                         stopIndex = k;
710                                         startPage = imagePatches[k]->startPage;
711                                         stopPage  = imagePatches[k]->stopPage;
712                                         finished = false;
713                                         if(k == imagePatches.size()){
714                                                 finished = true;
715                                         }
716                                 } 
717                         }
718                 }
719                 
720         }
721
722         if(!finished){
723                 patch = new imageUpdate;
724                 patch->address = imagePatches[startIndex]->address;
725                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
726                         imagePatches[stopIndex]->size;
727                 newPatches.push_back(patch);
728                 if(DEBUG_MSG){
729                         bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
730                 }
731         }       
732
733         
734 }
735
736 void writeBackElf::compactSections(pdvector <imageUpdate*> imagePatches, pdvector<imageUpdate*> &newPatches){
737
738         int startPage, stopPage;
739         imageUpdate *patch;
740
741
742         imageUpdate *curr, *next;
743         bool foundDup=true;
744         unsigned int j;
745
746         VECTOR_SORT(imagePatches, imageUpdateSort);
747
748         if(imagePatches.size() == 0){ //ccw 2 jul 2003
749                 return;
750         }
751
752         while(foundDup){
753                 foundDup = false;
754                 j =0;
755                 while(imagePatches[j]->address==0 && j < imagePatches.size()){
756                         j++;
757                 }
758                 curr = imagePatches[j];
759                 
760                 for(j++;j<imagePatches.size();j++){
761                         next = imagePatches[j];         
762                         if(curr->address == next->address){
763                                 //duplicate
764                                 //find which is bigger and save that one.
765                                 if(curr->size > next->size){
766                                         next->address=0;
767                                 }else{
768                                         curr->address=0;
769                                         curr=next;
770                                 }
771                                 foundDup =true;
772                         }else{
773                                 curr=next;
774                         }
775
776                 }
777                 VECTOR_SORT(imagePatches, imageUpdateSort);
778         }
779         if(DEBUG_MSG){
780                 bperr(" SORT 1\n");
781         
782                 for(unsigned int kk=0;kk<imagePatches.size();kk++){
783                         bperr(" address 0x%x  size 0x%x \n", imagePatches[kk]->address, imagePatches[kk]->size);
784                 }
785                 fflush(stdout);
786         }
787
788         unsigned int end_addr;
789         for(unsigned int i=0;i<imagePatches.size();i++){
790                 if(imagePatches[i]->address!=0){
791                         imagePatches[i]->startPage = imagePatches[i]->address- (imagePatches[i]->address%pageSize);
792                                 
793                         end_addr = imagePatches[i]->address + imagePatches[i]->size;
794                         imagePatches[i]->stopPage =  end_addr - (end_addr % pageSize);
795
796                         if(DEBUG_MSG){
797                                 bperr(" address %x end addr %x : start page %x stop page %x \n",
798                                                  imagePatches[i]->address,
799                                                  imagePatches[i]->address + imagePatches[i]->size,
800                                                  imagePatches[i]->startPage, imagePatches[i]->stopPage);
801                         }
802                         
803                 }
804         }
805         foundDup = true;
806
807         while(foundDup){
808                 foundDup = false;
809                 j =0;
810                 while(imagePatches[j]->address==0 && j < imagePatches.size()){
811                         j++;
812                 }
813                 //imagePatches.erase(0,j-1); //is it correct to erase here? 
814                 //j = 0;
815                 for(;j<imagePatches.size()-1;j++){
816                         if(imagePatches[j]->address!=0 && imagePatches[j]->stopPage >= imagePatches[j+1]->startPage){
817                                 foundDup = true;
818                                 if(imagePatches[j]->stopPage > imagePatches[j+1]->stopPage){
819                                         imagePatches[j+1]->address = 0; 
820                                 }else{
821                                         imagePatches[j]->size = (imagePatches[j+1]->address + imagePatches[j+1]->size) -
822                                                 imagePatches[j]->address;
823                                         imagePatches[j+1]->address = 0; 
824                                         end_addr = imagePatches[j]->address + imagePatches[j]->size;
825                                         imagePatches[j]->stopPage =  end_addr - (end_addr % pageSize);
826                                 }
827                         }  
828                 }
829                 VECTOR_SORT(imagePatches, imageUpdateSort);
830         }
831
832         unsigned int k=0;
833
834         if(DEBUG_MSG){
835                 bperr(" SORT 3\n");
836
837                 for(unsigned int kk=0;kk<imagePatches.size();kk++){
838                         bperr(" address 0x%x  size 0x%x \n", imagePatches[kk]->address, imagePatches[kk]->size);
839                 }
840                 fflush(stdout);
841         }
842         while(imagePatches[k]->address==0 && k < imagePatches.size()){
843                 k++;
844         }
845
846         startPage = imagePatches[k]->startPage;
847         stopPage = imagePatches[k]->stopPage;
848         int startIndex=k, stopIndex=k;
849         bool finished = false;
850         if(DEBUG_MSG){
851                 bperr("COMPACTING....\n");      
852                 bperr("COMPACTING %x %x %x\n", imagePatches[0]->startPage, stopPage, imagePatches[0]->address);
853         }
854         for(;k<imagePatches.size();k++){
855                 if(imagePatches[k]->address!=0){
856                         if(DEBUG_MSG){
857                                 bperr("COMPACTING k[start] %x k[stop] %x stop %x addr %x size %x\n", imagePatches[k]->startPage, 
858                                                  imagePatches[k]->stopPage,stopPage, imagePatches[k]->address, imagePatches[k]->size);
859                         }
860                         if(imagePatches[k]->startPage <= (unsigned int) stopPage){
861                                 stopIndex = k;
862                                 stopPage = imagePatches[k]->stopPage;
863                         }else{
864
865                                 patch = new imageUpdate;
866                                 patch->address = imagePatches[startIndex]->address;
867                                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address + 
868                                                 imagePatches[stopIndex]->size;
869                                 newPatches.push_back(patch);
870                                 if(DEBUG_MSG){
871                                         bperr(" COMPACTED: address %x --> %x    start %x  stop %x\n", 
872                                                          patch->address, patch->size, startPage,  stopPage);
873                                 }
874                                 finished = true;
875                                 //was k+1       
876                                 if(k < imagePatches.size()){
877                                         while(imagePatches[k]->address==0 && k < imagePatches.size()){
878                                                 k++;
879                                         }
880                                         startIndex = k;
881                                         stopIndex = k;
882                                         startPage = imagePatches[k]->startPage;
883                                         stopPage  = imagePatches[k]->stopPage;
884                                         finished = false;
885                                         if(k == imagePatches.size()){
886                                                 finished = true;
887                                         }
888                                 } 
889                         }
890                 }
891
892         }
893
894         if(!finished){
895                 patch = new imageUpdate;
896                 patch->address = imagePatches[startIndex]->address;
897                 patch->size = imagePatches[stopIndex]->address - imagePatches[startIndex]->address +
898                         imagePatches[stopIndex]->size;
899                 newPatches.push_back(patch);
900                 if(DEBUG_MSG){
901                         bperr(" COMPACTED: %x --> %x \n", patch->address, patch->size);
902                 }
903         }       
904         
905 }
906
907 void writeBackElf::alignHighMem(pdvector<imageUpdate*> imagePatches){
908         unsigned int currPage;
909         unsigned int sizeDiff;
910
911         for(unsigned int i=0;i<imagePatches.size();i++){
912                 if(imagePatches[i]->address % pageSize != 0){
913                         currPage = imagePatches[i]->address - ( imagePatches[i]->address % pageSize);
914                         sizeDiff = imagePatches[i]->address - currPage;
915                         imagePatches[i]->address = currPage;
916                         imagePatches[i]->size = imagePatches[i]->size + sizeDiff;
917                 }
918         }
919  
920 }
921
922 void writeBackElf::registerProcess(process *proc){
923
924         mutateeProcess = proc;
925 }
926 #endif
927