pete@ohm.york.ac.uk (-Pete French.) (06/17/91)
in article <43328@cup.portal.com>, Stuart_Jefferson_Adams@cup.portal.com says: > > can anyone either send me or point me to the sources for a program which > convertes unix (bsd/gnu) a.out format files to s-records?? This might actually be usefull to other ppl so I am posting it here : The program was written to enable us to use gcc on the SUNs to make executable files for some 68000 lab kits we have here. I will dump SUN 407 format executables (use the -N option) compiled for a 68010. These restrictins are trivial to alter in the program (though dumping anything other than 407 executables is generally a bad move - do a "size" on one) The program includes an a.out.h from the local directory - this was because the program was written to run on a MIPS not a SUN and so just including the standard a.out.h whould not work - I had to copy the SUN a.out.h into the directory that I build s-dump in. Inclkuding the standard a.out.h should work on a SUN. -bat. ----------------------------------------------------------------------------- /* * s-dump.c : dump a.out files in Motorola S-record format * -Pete French. 9/7/1990 * * This program is designed for dumping files generated by gcc * for the 68000 lab kits. It will therefore only dump files * that have a machine type of M_68010 and a magic number of * OMAGIC (407 executable). This should prevent people trying to * run standard a.out binaries on the 68000 kits. */ #include "a.out.h" #include <stdio.h> #include <sys/file.h> #define S_HEAD 0 #define S_DATA 2 #define S_EOF 8 #define MAXSREC 32 extern int errno; /* * h_out(val) * * This function prints a two digit * hex value to stdout. printf cannot * be used on its own since the * braindamaged monitor in the 68000 * kits cannot cope with small letters * in hex numbers ! */ char conv[16]={'0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F'}; h_out(val) int val; { val=val & 0xff; printf("%c%c",conv[val>>4],conv[val & 0x0f]); } /* * s_dump(type,addr,ptr,len) * * This function dumps out "len" bytes * from memory starting at location "ptr" * as an s-record of type "type". For * data records the load address is set * to "addr" and a checksum of the data * is returned (this is not the same as the * s-record checksum itself which includes * the size byte) */ int s_dump(type,addr,ptr,len) int type,addr; char *ptr; int len; { int chck1,chck2; /* two checksums - one for data, one for everything */ int i; /* loop counter for outputting bytes */ chck1=(type==S_HEAD)?len+1:len+4; printf("S%1d",type); h_out(chck1); if(type!=S_HEAD) { int top=(int)((addr & 0xff0000) >> 16); /* top byte of address */ int mid=(int)((addr & 0xff00) >> 8); /* middle byte of address */ int bot=(int)(addr & 0xff); /* bottom byte of address */ h_out(top); h_out(mid); h_out(bot); chck1=chck1+top+mid+bot; /* add bytes to checksum */ } chck2=0; /* zero data checksum */ for(i=0;i<len;i++) { h_out((int)ptr[i]); /* print a byte of the data */ chck1+=(int)ptr[i]; /* add byte to total checksum */ chck2+=(int)ptr[i]; /* add byte to data checksum */ } h_out((int)(~chck1 & 0xff)); /* print checksum for record */ puts(""); return(chck2); /* return data checksum */ } /* * main(argc,argv) * * This is the main body of the program. It checks * to see that it has been called with a valid * argument, attempts to open the object file and * if successful checks its type. Once this has * been done the program loops reading in MAXSREC byte * blocks of data and calling "s_dump" to output * them as s-records. */ main(argc,argv) int argc; char *argv[]; { int fd; /* object file file descriptor */ struct exec hdr; /* object file a.out header */ int i,len; /* general purpose loop and length variables */ int t_load,d_load; /* text and data load addresses */ int t_len,d_len; /* text and data segment lengths */ int b_start,b_len; /* bss segment start and length */ int c_addr,g_chk; /* current address and global checksum */ char buffer[MAXSREC]; /* buffer for data bytes */ /* * Check that the correct number * of arguments have been passed * to s-dump. */ if (argc!=2) { fprintf(stderr,"usage: s-dump <object file>\n"); exit(1); } /* * Open the file check that * it was opened correctly * and that we can read the * header structure. */ fd=open(argv[1],O_RDONLY,0); if(fd==-1) { perror(argv[1]); exit(errno); } len=read(fd,(char*)&hdr,sizeof(struct exec)); if(len!=sizeof(struct exec)) { fprintf(stderr,"s-dump: cannot read a.out header structure\n"); exit(1); } /* * Now we check that the file * is actually an executable * and that it is the correct * type of executable. */ if(N_BADMAG(hdr)) { fprintf(stderr,"s-dump: this is not a correct a.out format file\n"); exit(1); } switch(hdr.a_magic) { case OMAGIC : break; case NMAGIC : fprintf(stderr,"s-dump: read-only text executables not supported\n"); exit(1); break; case ZMAGIC : fprintf(stderr,"s-dump: demand load executables not supported\n"); exit(1); break; } if(hdr.a_machtype!=M_68010) { fprintf(stderr,"s-dump: this executable is not for 68000/68010 processor\n"); exit(1); } /* * We now have an open file * of the correct format. * Calculate the lengths and * addresses of the segments */ t_load=hdr.a_entry; t_len=hdr.a_text; d_load=t_load+t_len; d_len=hdr.a_data; b_start=d_load+d_len; b_len=hdr.a_bss; /* * Print out the filename * and the areas in memory * occupied by the various * segments. */ printf("dumping file %s as s-records: -Pete French. 9/7/1990\n",argv[1]); printf("text segment:\tstarts at 0x%08x for 0x%x bytes\n",t_load,t_len); printf("data segment:\tstarts at 0x%08x for 0x%x bytes\n",d_load,d_len); printf("bss segment:\tstarts at 0x%08x for 0x%x bytes\n",b_start,b_len); /* * Start dumping the S-records * beginning with the header * containing the filename. */ len=strlen(argv[1]); if(len>MAXSREC) /* truncate filenames over MAXSREC characters */ len=MAXSREC; puts("header"); s_dump(S_HEAD,0,argv[1],len); /* dump the header s-record */ g_chk=0; /* zero the global checksum */ /* * Now read in the text * segment in MAXSREC byte parts * and dump each part as an * s-record */ c_addr=t_load; puts("text"); while(c_addr!=d_load) { len=d_load-c_addr; if(len>MAXSREC) /* dump in MAXSREC byte s-records */ len=MAXSREC; if(len!=read(fd,buffer,len)) { fprintf("s-dump: file ran out prematurely in text segment\n"); exit(1); } g_chk+=s_dump(S_DATA,c_addr,buffer,len); c_addr+=len; } /* * Next we read in the data * segment and dump it in a similar * way in MAXREC byte parts. */ c_addr=d_load; puts("data"); while(c_addr!=b_start) { int r_type; /* s-record type */ len=b_start-c_addr; if(len>MAXSREC) /* dump in MAXSREC byte s-records */ len=MAXSREC; if(len!=read(fd,buffer,len)) { fprintf("s-dump: file ran out prematurely in data segment\n"); exit(1); } g_chk+=s_dump(S_DATA,c_addr,buffer,len); c_addr+=len; } /* * And finally and EOF * record is generated to * indicate the end of * the file. This * contains no data */ puts("eof"); s_dump(S_EOF,t_load,0,0); /* * The global checksum is not used * yet - it is included for future * expansion at the request of Ross * Kirk. */ /* printf("global checksum is 0x%08x\n",g_chk & 0xffffffff); */ } -- -Pete French. (the -bat. ) / "Two wrongs don't make a right, Adaptive Systems Engineering / - but three lefts do !" "Look here, a Brit who has obviously been driving in California!"