Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / writeBackXCOFF.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 #include "writeBackXCOFF.h"
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/mman.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdio.h>
42 #include <math.h>
43
44 void writeBackXCOFF::attachToText(Address addr, unsigned int size, char* data){
45         textTramps=data;
46         textTrampsAddr=addr;
47         textTrampsSize=size;
48 }
49
50
51 int writeBackXCOFF::loadFile(XCOFF* file){
52
53
54         file->fd = open( file->name, O_RDONLY);
55
56         if( file->fd == -1 ){
57                 bperr(" error opening: %s \n", file->name);
58                 return 0;
59         }
60
61         struct stat statInfo;
62
63         int statRet = fstat(file->fd, &statInfo);       
64         
65         if( statRet == -1) {
66                 bperr(" no stats found for %s \n", file->name);
67                 P_close(file->fd);
68                 return -1;
69         }
70         
71         file->buffer = (char*) mmap(0x0, statInfo.st_size,
72                 PROT_READ, MAP_FILE, file->fd,0x0); 
73
74         file->filesize = statInfo.st_size; 
75         return 1;
76
77 }
78
79
80 void writeBackXCOFF::parseXCOFF(XCOFF *file){
81
82
83         if(! file->opened){
84                 return; 
85         }
86
87         
88         file->XCOFFhdr = (struct xcoffhdr*) file->buffer;
89
90         if(file->XCOFFhdr->filehdr.f_magic != 0x01DF ){
91                 bperr(" %s is not a 32XCOFF file\n", file->name);
92                 file->opened = false;
93         }
94
95         file->sechdr = (struct scnhdr *) (file->buffer + sizeof(struct filehdr) +
96                 file->XCOFFhdr->filehdr.f_opthdr);
97
98         file->loadhdr = 
99         (struct ldhdr*) &(file->sechdr[file->XCOFFhdr->aouthdr.o_snloader-1]);  
100
101 }
102
103
104 writeBackXCOFF::writeBackXCOFF(const char* oldFileName, const char* newFileName,bool &error, 
105         bool debugOutputFlag, int numbScns)
106         : numberSections(0), maxSections(numbScns), debugFlag(debugOutputFlag) {
107
108
109         oldFile.name = new char[strlen(oldFileName)+1];
110         strcpy(oldFile.name, oldFileName);
111
112         
113         newFile.name = new char[strlen(newFileName)+1];
114         strcpy(newFile.name, newFileName);
115
116         int ret = loadFile(&oldFile);
117         oldFile.opened = true;
118         error = false; 
119         if( !ret ){
120                 bperr(" Error: %s not opened properly\n",oldFile.name);
121                 oldFile.opened = false;
122                 error = true;
123         }
124
125         mutateeProcess = 0;
126
127         parseXCOFF(&oldFile);
128
129         newSections = new scnhdr[numbScns];             
130
131 }
132 writeBackXCOFF::~writeBackXCOFF(){
133
134         if(oldFile.name){
135                 delete [] oldFile.name;
136         }
137         if(newFile.name){
138                 delete [] newFile.name;
139         }
140
141         for(int i=0;i<numberSections;i++){
142                 delete [] (char*) newSections[i].s_scnptr;
143         }       
144         munmap(oldFile.buffer, oldFile.filesize);
145         delete [] newFile.buffer;       
146         P_close(oldFile.fd);
147         P_close(newFile.fd);
148 }
149
150 int writeBackXCOFF::addSection(char *name, unsigned int paddr, 
151         unsigned int vaddr, int sectionSize, char*data, int flags){
152
153         
154         if(numberSections >= maxSections){
155                 return -1;
156         }
157
158         memset((char*) &(newSections[numberSections]),'\0', sizeof(struct scnhdr));
159
160         strcpy(&(newSections[numberSections].s_name[0]), name);
161
162         newSections[numberSections].s_paddr = paddr;
163         newSections[numberSections].s_vaddr = vaddr;
164         newSections[numberSections].s_size = sectionSize;
165
166         newSections[numberSections].s_scnptr = (long int) new char[sectionSize];
167         memcpy ( (char*)  newSections[numberSections].s_scnptr, data, sectionSize);
168
169         newSections[numberSections].s_flags = flags;    
170
171         return numberSections++;
172 }
173
174 //calculate offsets; return total size of the file (MINUS the new sections!)
175 unsigned int calcOffsets(XCOFF* newFile, XCOFF* oldFile, unsigned int newTextSize){
176         //here i need to calculate all the offsets for the NEW 
177         //file.  I will return the TOTALSIZE of the new file
178
179         //this will happen in two passes. 
180         //First pass will lay in all the scnptrs
181         //Second pass will patch up the reloc/lnno/etc
182         //pointers
183
184
185         //first pass
186         int numbSecs = oldFile->XCOFFhdr->filehdr.f_nscns;
187         struct scnhdr *shdr = newFile->sechdr;
188         unsigned int currentIndex=oldFile->sechdr[0].s_scnptr;//index to step through new file
189
190         for(int i=0;i<numbSecs;i++, shdr++){
191
192                 if(shdr->s_scnptr  && (i+1) != oldFile->XCOFFhdr->aouthdr.o_sntext ){
193                 //      shdr->s_scnptr += offSet; //ccw 1 aug 2002
194
195                         shdr->s_scnptr = currentIndex;
196
197                         /*while( shdr->s_scnptr % 4 ){ //align!
198                                 shdr->s_scnptr++;
199                         }*/
200                         currentIndex = shdr->s_scnptr;
201                 }
202
203                 if( (i+1) == oldFile->XCOFFhdr->aouthdr.o_sntext ) {
204                         //update s_size for the text section
205
206                         shdr->s_size = newTextSize;
207
208                 }
209                 currentIndex += shdr->s_size;
210         }
211
212         //second pass
213         unsigned int lastDataByte = currentIndex;
214         unsigned int offSet = lastDataByte - (oldFile->sechdr[numbSecs-1].s_scnptr +oldFile->sechdr[numbSecs-1].s_size );
215         unsigned int lastByte;
216
217         //bpinfo( " DIFFERENCE:  0x%x = 0x%x - 0x%x\n", offSet, lastDataByte, (oldFile->sechdr[numbSecs-1].s_scnptr +oldFile->sechdr[numbSecs-1].s_size ));
218
219         shdr = newFile->sechdr;
220         for(int i=0;i<numbSecs;i++, shdr++){
221                 
222                 if(shdr->s_relptr){
223                         shdr->s_relptr += offSet; //ccw 1 aug 2002
224                 }
225                 if(shdr->s_lnnoptr){
226                         shdr->s_lnnoptr += offSet; //ccw 1 aug 2002
227                 }
228
229                 //set currentIndex to the largest offset of the two if they
230                 //are beyond the currentIndex   
231                 lastByte = shdr->s_lnnoptr + (shdr->s_nlnno *(sizeof(struct lineno)));
232                 currentIndex = ((currentIndex < lastByte) ? lastByte : currentIndex);
233
234                 lastByte = shdr->s_relptr + (shdr->s_nreloc *(sizeof(struct reloc)));
235                 currentIndex = (currentIndex < lastByte) ? lastByte : currentIndex;
236         }
237         
238
239         //now update the symbol table info.
240         newFile->XCOFFhdr->filehdr.f_symptr = currentIndex;
241         
242         int symentSize = 18;
243         int *len;
244         int symTableSize=0;
245         
246         if(newFile->XCOFFhdr->filehdr.f_symptr ){
247
248                 symTableSize = oldFile->XCOFFhdr->filehdr.f_nsyms * symentSize;
249
250                 len = (int*) &(oldFile->buffer[ oldFile->XCOFFhdr->filehdr.f_symptr +(oldFile->XCOFFhdr->filehdr.f_nsyms*symentSize)]);
251                 symTableSize += *len;
252
253         }
254
255         currentIndex += symTableSize;
256
257         return currentIndex; 
258 }
259
260
261 bool writeBackXCOFF::createXCOFF(){
262         //This is the function that actually creates the
263         //new XCOFF file by allocating the buffer and
264         //patching up all the necessary pointers within
265         //the file
266         
267         //new plan:
268         //the text section CANNOT move OR it will be
269         //loaded into a different place. :(
270
271         //this means: I CANNOT put in new scnhdrs in the
272         //usual place because they will shift the .text section
273         //down a few bits
274         //
275
276         //The new file will look like this:
277         //
278         // filehdr
279         // aouthdr
280         // scnhdr
281         // ...
282         // scnhdr
283         // section data (.text - expanded) 
284         // PAD
285         // section data
286         // relocation data
287         // relocation data
288         // line number data
289         // symbol table
290         // NUMBER OF NEW SECTIONS ccw 10 sep 2003
291         // NEW SECTION HDR
292         // NEW SECTION HDR
293         // NEW SECTION DATA
294
295         //i have no idea if this will work.
296         int pageSize = getpagesize();
297
298         int totalSize=0; // totalSize of the NEW file
299
300         int newTextSize =0; // size of NEW TEXT SECTION 
301
302         int textPadding = 0; //padding bytes between end of text and start of data
303
304         int newDataSize = 0;            //newDataSize is the size of the 
305                                         //NEW SCNHDRs and the new SECTIONS
306
307         int offset = 0;                 //offset is the difference of the
308                                         //size of the NEW EXPANDED text section
309                                         //and the old text section. AND  any
310                                         //padding needed between the end of the
311                                         //text section and the start of the
312                                         //data section
313                                         //it is used to move EVERYTHING after
314                                         //the .text section
315                                 
316         int trueTextStart;      // in fortan execs made by xlcf the start address of the
317                                 // text section is 0x0, but the loader (appears to) default to 0x1000000+ 92 + (fnscns * 40)
318         char *newFileCurrent;
319         struct scnhdr *tmpScnhdr, *oldTextScnhdr;
320
321         struct xcoffhdr *OldXCOFFhdr = (struct xcoffhdr*) oldFile.buffer;
322         
323         newDataSize = sizeof(struct scnhdr) * numberSections;
324         tmpScnhdr = newSections;
325         for(int i=0 ; i<numberSections; i++, tmpScnhdr++){
326                 newDataSize += tmpScnhdr->s_size;               
327         }
328 //really should check that .data is immedialtey after .text
329         oldTextScnhdr = (struct scnhdr*) &(oldFile.sechdr[OldXCOFFhdr->aouthdr.o_sntext-1]); // ccw 1 aug 2002 added -1!
330         struct scnhdr *oldDataScnhdr =  (struct scnhdr*) &(oldFile.sechdr[OldXCOFFhdr->aouthdr.o_sndata-1]); 
331
332         int fakeTextStart = 0x10000000 + oldTextScnhdr->s_scnptr;//+ 92 + (OldXCOFFhdr->filehdr.f_nscns * 40);
333         int fakeDataStart = 0x20000000 + oldDataScnhdr->s_scnptr;
334
335         int trueDataStart =   ( OldXCOFFhdr->aouthdr.o_data_start != 0) ? OldXCOFFhdr->aouthdr.o_data_start : fakeDataStart;
336
337         trueTextStart = ( OldXCOFFhdr->aouthdr.o_text_start != 0) ? OldXCOFFhdr->aouthdr.o_text_start : fakeTextStart;
338
339         newTextSize = ( textTrampsAddr - trueTextStart+ textTrampsSize);
340
341
342         // distance from end of text to start of next page PLUS 
343         // distance from start of page to start of data 
344         textPadding = (pageSize - ((trueTextStart+ newTextSize) % pageSize)) +  ((trueDataStart % pageSize )); 
345
346
347         // if we span an entire page compress ourselves 
348         if(textPadding > pageSize){
349                 textPadding -= pageSize; 
350         }
351
352         if(textPadding > 0){
353                 textPadding += pageSize;
354         }
355
356         newTextSize += textPadding;
357         //offset = newTextSize - OldXCOFFhdr->aouthdr.o_tsize; 
358
359
360         //totalSize = oldFile.filesize +  newTextSize - OldXCOFFhdr->aouthdr.o_tsize + newDataSize;
361         //bpinfo("\n\n trueDataStart %x  trueTextStart %x newTextSIZE: %x  textEND: %x\n\n", trueDataStart, trueTextStart,newTextSize, trueTextStart+newTextSize);
362 /*
363
364         //allocate memory
365         newFile.buffer = new char[ totalSize ]; 
366 */
367
368         //allocate memory for the HEADERS
369         newFile.buffer = new char[ sizeof(struct filehdr) + OldXCOFFhdr->filehdr.f_opthdr + 
370                                         (sizeof(struct scnhdr) * OldXCOFFhdr->filehdr.f_nscns)];        
371
372         //setup new file
373         newFile.XCOFFhdr = (struct xcoffhdr*) newFile.buffer;
374         
375         newFile.sechdr = (struct scnhdr *) (newFile.buffer + sizeof(struct filehdr) +
376                 oldFile.XCOFFhdr->filehdr.f_opthdr);
377
378
379         //copy over filehdr and aouthdr
380         memcpy((char*) newFile.XCOFFhdr, oldFile.buffer, sizeof(struct filehdr) 
381                 + oldFile.XCOFFhdr->filehdr.f_opthdr );
382
383         //copy section headers to the new file.
384         memcpy(newFile.sechdr, oldFile.sechdr, sizeof(struct scnhdr) * oldFile.XCOFFhdr->filehdr.f_nscns);
385
386         //calculate offsets; return total size of the file (less the size of the new data)
387         totalSize = calcOffsets( &newFile, &oldFile,newTextSize);
388
389         //create tmp variable to hold the new offset info while we allocate the entire file 
390         char* tmp = new char[sizeof(struct filehdr) + OldXCOFFhdr->filehdr.f_opthdr + 
391                                         (sizeof(struct scnhdr) * OldXCOFFhdr->filehdr.f_nscns)];
392
393         memcpy (tmp, newFile.buffer, sizeof(struct filehdr) + OldXCOFFhdr->filehdr.f_opthdr + 
394                                         (sizeof(struct scnhdr) * OldXCOFFhdr->filehdr.f_nscns));
395
396         delete [] newFile.buffer;
397
398         // add in size of new sections here!
399         // i'm adding in the sizeof(unsigned int) so i can add a SIZE (number of sections) before the
400         // section headers ccw 10 sep 2003
401         totalSize += (sizeof(unsigned int) + newDataSize + (sizeof(struct scnhdr) * numberSections));
402         newFile.buffer = new char[ totalSize ];
403
404         memcpy (newFile.buffer,tmp, sizeof(struct filehdr) + OldXCOFFhdr->filehdr.f_opthdr + 
405                                         (sizeof(struct scnhdr) * OldXCOFFhdr->filehdr.f_nscns));
406
407         //setup new file
408         newFile.XCOFFhdr = (struct xcoffhdr*) newFile.buffer;
409         
410         newFile.sechdr = (struct scnhdr *) (newFile.buffer + sizeof(struct filehdr) +
411                 oldFile.XCOFFhdr->filehdr.f_opthdr);
412
413         delete [] tmp;
414         
415         newFile.XCOFFhdr->aouthdr.o_tsize = newTextSize;
416
417         //copy over section raw data.
418         //for each section
419         //UPDATE AND EXPAND TEXT SECTION
420         copySectionData(offset);
421
422         //copy over the relocation data as specified in
423         //the section headers
424         copyRelocationData(offset);
425
426         
427         //copy over the line number data as specified in the 
428         //section headers
429         copyLineNumberData(offset);
430
431         //copy over the symbol table data
432         newFileCurrent = (char*) copySymbolTableData(offset /*+ additionalPadding*/);
433
434
435         if(!newFileCurrent){
436                 bperr(" ERROR! NO SYMBOL TABLE FOUND!\n");
437                 //assert(0);
438         }
439
440         //ADD NEW DATA
441
442         //ADD number of new section headers
443         *((unsigned int *) newFileCurrent) = (unsigned int) numberSections;
444         newFileCurrent += sizeof(unsigned int);
445         
446         //new scnhdrs
447         struct scnhdr** addedSectionHeader = new struct scnhdr*[numberSections];
448         for(int i=0;i<numberSections;i++){
449                 //create new section header!
450                 addedSectionHeader[i] = addSectionHeader(newFileCurrent, newSections[i].s_name, newSections[i].s_paddr, 
451                         newSections[i].s_vaddr, newSections[i].s_size, newSections[i].s_flags); 
452         
453                 newFileCurrent += sizeof(struct scnhdr);
454         }
455                 
456
457         //new raw data
458         for(int i=0;i<numberSections;i++){
459
460                 //open file argv[6] and add sectionSize bytes as the new section
461                 addNewSectionData(newFileCurrent, (char*) newSections[i].s_scnptr, newSections[i].s_size, addedSectionHeader[i]); 
462
463                 newFileCurrent += newSections[i].s_size;
464         }
465
466         newFile.filesize = totalSize;
467         delete [] addedSectionHeader;
468
469         return true;
470 }
471
472 /*
473 void writeBackXCOFF::expandMoveTextSection(char* newFileStart, int start, int sectionsize, int newTextFilePtr){
474
475         int newTextAddr= start;
476         struct xcoffhdr * XCOFFhdr = (struct xcoffhdr*) newFileStart;
477         int align;
478         struct scnhdr *newtextsechdr =  
479                 (struct scnhdr*) ( &newFileStart[sizeof(struct xcoffhdr)+ (sizeof(struct scnhdr) * (XCOFFhdr->aouthdr.o_sntext-1))]);
480         align = (int) pow(2.0, (double) XCOFFhdr->aouthdr.o_algntext);
481
482         while(  (newtextsechdr->s_vaddr - newTextAddr) % align){
483                 newTextAddr ++;
484         }
485
486         //copy the old text section data here! 
487         //NOTE: this is really the mutated text section
488         memcpy((newFileStart +newTextFilePtr 
489 //newTextAddr ccw 18 jul 2002
490 ), (newFileStart+ newtextsechdr->s_scnptr), 
491                 newtextsechdr->s_size); 
492
493
494         //memcpy the text tramps in to place
495         memcpy( (newFileStart + 
496 //newTextAddr ccw 18 jul 2002 
497 newTextFilePtr  + (textTrampsAddr - newtextsechdr->s_vaddr)), textTramps, textTrampsSize);
498
499         newtextsechdr->s_scnptr = (long int) (newTextFilePtr 
500 //newTextAddr ccw 18 jul 2002 
501 );
502         newtextsechdr->s_size = sectionsize;
503         XCOFFhdr->aouthdr.o_tsize = sectionsize;
504 }
505 */
506
507
508         //add sectionSize bytes as the new section
509 void writeBackXCOFF::addNewSectionData(char *newFileCurrent, char* data,int sectionSize, struct scnhdr *newHdr){
510
511
512         memcpy( newFileCurrent, data, sectionSize);
513         newHdr->s_scnptr = (newFileCurrent - newFile.buffer);
514
515 }
516
517         //create new section header!
518         //NOTE: name MUST be NO LONGER than 8 characaters (including the \0)
519 struct scnhdr *writeBackXCOFF::addSectionHeader(char *newFileCurrent, char* name,unsigned int paddr, 
520         unsigned int vaddr, int sectionSize, int flags){
521
522         struct scnhdr *shdr = (struct scnhdr*) newFileCurrent;
523
524         *shdr->s_name = '\0';
525         if(strlen(name) < 8){
526                 strcpy(shdr->s_name, name);
527         }else{
528                 bperr(" name %s is too long!\n", name);
529         }
530         shdr->s_paddr = paddr;
531         shdr->s_vaddr = vaddr;
532         shdr->s_size = sectionSize;
533         shdr->s_scnptr = 0;
534         shdr->s_relptr = 0;
535         shdr->s_lnnoptr = 0;
536         shdr->s_nreloc = 0;
537         shdr->s_nlnno = 0;
538         shdr->s_flags = flags ;
539         return shdr;
540 }
541         
542         //copy over section raw data.
543         //for each section
544
545 void  writeBackXCOFF::copySectionData(int /* offSet */){
546
547         struct scnhdr *shdr = oldFile.sechdr;
548         struct scnhdr *shdrNew = newFile.sechdr; //ccw 1 aug 2002
549
550         char *newTmp = newFile.buffer;
551         int f_nscns = oldFile.XCOFFhdr->filehdr.f_nscns;
552         char *tmpBuf;
553
554
555         for(int i=0;i<f_nscns;i++,shdr++, shdrNew++){
556
557                 if((i+1) == newFile.XCOFFhdr->aouthdr.o_sntext ){ //TEXT SECTION
558                         //copy normal text section over...
559                         //GET THIS FROM MEMORY!!
560
561                         //again, the fortran binary does not fill in the text scnhdr so i must fake it
562                         int fakeTextStart =  ((shdr->s_vaddr != 0x0 ) ? shdr->s_vaddr : (0x10000000 + shdr->s_scnptr ));//+92+(f_nscns * 40)));
563                         int textTrampOffset = textTrampsAddr -  fakeTextStart;  
564
565                         tmpBuf =  (char*) oldFile.buffer+shdr->s_scnptr; //if not mutatee
566
567                         if( mutateeProcess ){
568                                 tmpBuf = new char[shdr->s_size];
569                                 mutateeProcess->readTextSpace((const void*) (fakeTextStart), shdr->s_size, (void*) tmpBuf);
570                         }
571
572                         memcpy( &(newTmp[shdrNew->s_scnptr/*shdr->s_scnptr*/]), tmpBuf, shdr->s_size);
573         
574                         //copy over tramps      
575                         memcpy( &(newTmp[shdrNew->s_scnptr/*shdr->s_scnptr*/ + textTrampOffset]), textTramps, textTrampsSize);  
576
577                 }else if(shdr->s_scnptr){
578                         memcpy( &(newTmp[shdrNew->s_scnptr/*shdr->s_scnptr + offSet*/]), oldFile.buffer+shdr->s_scnptr, shdr->s_size);
579                 }
580         }
581
582
583 void writeBackXCOFF::copyRelocationData(int /* offSet */){
584
585         char *newFileStart = newFile.buffer;
586         char *oldFileStart = oldFile.buffer;
587         
588         struct scnhdr* shdr = oldFile.sechdr;
589         struct scnhdr* shdrNew = newFile.sechdr; //ccw 1 aug 2002
590         int f_nscns = oldFile.XCOFFhdr->filehdr.f_nscns;
591
592         for(int i=0;i<f_nscns;i++, shdr++){
593                 if(shdr->s_relptr){
594                         memcpy( &(newFileStart[shdrNew->s_relptr /*offSet + shdr->s_relptr*/]),&(oldFileStart[shdr->s_relptr]),
595                                 shdr->s_nreloc * sizeof(struct reloc));         
596
597                 }
598         }
599         
600 }
601
602         //copy over the line number data as specified in the 
603         //section headers
604 void writeBackXCOFF::copyLineNumberData(int /* offSet */){
605
606         char *newFileStart = newFile.buffer;
607         char *oldFileStart = oldFile.buffer;
608         struct scnhdr* shdr = oldFile.sechdr;
609         struct scnhdr* shdrNew = newFile.sechdr; //ccw 1 aug 2002
610  
611         int f_nscns = oldFile.XCOFFhdr->filehdr.f_nscns;
612
613         for(int i=0;i<f_nscns;i++, shdr++){
614                 if(shdr->s_relptr){
615                         memcpy( &(newFileStart[shdrNew->s_lnnoptr /*offSet + shdr->s_lnnoptr*/]),&(oldFileStart[shdr->s_lnnoptr]),
616                                 shdr->s_nlnno * sizeof(struct lineno));         
617                 }
618         }
619 }
620
621
622         //copy over the symbol table data
623 void* writeBackXCOFF::copySymbolTableData(int /* offSet */){
624
625         char *newFileStart = newFile.buffer;
626         char *oldFileStart = oldFile.buffer;
627         struct filehdr hdr = oldFile.XCOFFhdr->filehdr;
628         struct filehdr hdrNew = newFile.XCOFFhdr->filehdr; //ccw 1 aug 2002
629         int symentSize = 18;
630         int *len;
631
632         
633         if(hdr.f_symptr){
634                 //copy over symbol table.
635                 memcpy( & (newFileStart[/*offSet + */hdrNew.f_symptr]), & (oldFileStart[hdr.f_symptr]),
636                         hdr.f_nsyms * symentSize);
637
638                 len = (int*) &(oldFileStart[ hdr.f_symptr +(hdr.f_nsyms*symentSize)]);
639                 //copy over string table
640                 memcpy( & (newFileStart[/*offSet + */hdrNew.f_symptr +(hdr.f_nsyms*symentSize)]),
641                         & (oldFileStart[hdr.f_symptr +(hdr.f_nsyms*symentSize)]),*len);
642
643                 //hdrNew.f_symptr = offSet + hdr.f_symptr; //ccw 1 aug 2002
644
645                 return &newFileStart[hdrNew.f_symptr + (hdr.f_nsyms*symentSize) + *len];
646         }else{
647                 return NULL;
648         }
649 }
650
651 bool writeBackXCOFF::outputXCOFF(){
652
653         
654         newFile.fd = open(newFile.name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IXUSR);
655
656         if(newFile.fd == -1){
657                 bperr(" Opening %s for writing failed\n", newFile.name);
658                 return false;
659         }
660
661
662         //memcpy(buf, hdr, fileSize + loaderSecSize);   
663         if(debugFlag){
664                 bpinfo(" WRITING %x bytes to %s \n", newFile.filesize, newFile.name);
665         }
666         write(newFile.fd, (void*) newFile.buffer, newFile.filesize);
667
668         P_close(newFile.fd);
669        
670         return true;
671 }