📄 coff.c
字号:
/* coff.c:
Perform some dumps/conversions of a coff file.
General notice:
This code is part of a boot-monitor package developed as a generic base
platform for embedded system designs. As such, it is likely to be
distributed to various projects beyond the control of the original
author. Please notify the author of any enhancements made or bugs found
so that all may benefit from the changes. In addition, notification back
to the author will allow the new user to pick up changes that may have
been made by other users after this version of the code was distributed.
Author: Ed Sutter
email: esutter@lucent.com (home: lesutter@worldnet.att.net)
phone: 908-582-2351 (home: 908-889-5161)
*/
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef BUILD_WITH_VCC
#include <io.h>
#endif
#include "coff.h"
#include "../zlib/zlib.h"
#include "utils.h"
#include "version.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
int coffFD = 0, noPad;
char *coffFname = (char *)0;
struct filehdr CoffFhdr;
struct aouthdr OptAhdr;
struct scnhdr *ScnTbl;
/* open verbosity: */
#define SHOWHDR 0x0001
#define SHOWSECTIONS 0x0002
#define SHOWMAP 0x0004
#define SHOWMAPOFFSET 0x0008
#define SHOWAPPEND 0x0010
struct filehdr *GetCoffFileHdr();
int Ecvt, verbose, debug;
void
ShowAppend(void)
{
int i;
char c;
long maxsize, maxoff;
maxoff = 0;
for(i=0;i<CoffFhdr.f_nscns;i++) {
if (ScnTbl[i].s_scnptr > maxoff) {
maxoff = ScnTbl[i].s_scnptr;
maxsize = ScnTbl[i].s_size;
}
}
Lseek(coffFD,maxoff+maxsize,SEEK_SET);
while(1) {
if (read(coffFD,&c,1) != 1)
break;
putchar(c);
}
}
void
ShowCoffSections(void)
{
int i;
printf("\n\t\tCOFF FILE SECTION HEADERS\n");
for(i=0;i<CoffFhdr.f_nscns;i++) {
printf("Section: %s...\n",ScnTbl[i].s_name);
printf(" s_paddr: 0x%x\n",ScnTbl[i].s_paddr);
printf(" s_vaddr: 0x%x\n",ScnTbl[i].s_vaddr);
printf(" s_size: %d\n",ScnTbl[i].s_size);
printf(" s_scnptr: 0x%x\n",ScnTbl[i].s_scnptr);
printf(" s_relptr: 0x%x\n",ScnTbl[i].s_relptr);
printf(" s_lnnoptr: 0x%x\n",ScnTbl[i].s_lnnoptr);
printf(" s_nreloc: %d\n",ScnTbl[i].s_nreloc);
printf(" s_nlnno: %d\n",ScnTbl[i].s_nlnno);
printf(" s_flags: 0x%x\n\n",ScnTbl[i].s_flags);
}
}
void
ShowCoffHdr(void)
{
printf("\n\t\tCOFF FILE HEADER\n");
printf("Magic: 0x%x\n",CoffFhdr.f_magic);
if (CoffFhdr.f_opthdr) {
printf("Text size: 0x%x (%d)\n",
OptAhdr.tsize,OptAhdr.tsize);
printf("Data size: 0x%x (%d)\n",
OptAhdr.dsize,OptAhdr.dsize);
printf("Bss size: 0x%x (%d)\n",
OptAhdr.bsize,OptAhdr.bsize);
printf("Entrypoint: 0x%x\n",OptAhdr.entry);
}
printf("Number of sections: %d\n",CoffFhdr.f_nscns);
printf("Number of symbols: %d\n",CoffFhdr.f_nsyms);
}
void
ShowCoffMap(void)
{
int i, size;
printf("\n\t\tCOFF FILE MEMORY MAP\n\n");
for(i=0;i<CoffFhdr.f_nscns;i++) {
char name[9];
memcpy(name,ScnTbl[i].s_name,8);
name[8] = 0;
size = ScnTbl[i].s_size;
printf("%8s: 0x%08x .. 0x%08x, 0x%x (%d) bytes.\n",
name,ScnTbl[i].s_paddr,ScnTbl[i].s_paddr+size,size,size);
}
}
void
ShowCoffOffsets(void)
{
int i, start;
start = sizeof(struct filehdr) + CoffFhdr.f_opthdr;
printf("\n\t\tCOFF FILE SECTION FILE OFFSETS\n");
for(i=0;i<CoffFhdr.f_nscns;i++) {
printf("%8s: 0x%08x .. 0x%08x (%d bytes)\n",
ScnTbl[i].s_name,ScnTbl[i].s_scnptr,
ScnTbl[i].s_scnptr+ScnTbl[i].s_size,
ScnTbl[i].s_size);
start += ScnTbl[i].s_size;
}
}
/* GetCoffFileHdr():
Retrieve the header from the file and do a BE-to-LE conversion
on each of its members.
*/
struct filehdr *
GetCoffFileHdr(void)
{
if (verbose)
fprintf(stderr,"GetCoffFileHdr()\n");
/* Read in the coff file header. */
Lseek(coffFD,0,SEEK_SET);
Read(coffFD,(char *)&CoffFhdr,(unsigned)sizeof(struct filehdr));
CoffFhdr.f_magic = otherEnd16(Ecvt,CoffFhdr.f_magic);
CoffFhdr.f_nscns = otherEnd16(Ecvt,CoffFhdr.f_nscns);
CoffFhdr.f_timdat = otherEnd32(Ecvt,CoffFhdr.f_timdat);
CoffFhdr.f_symptr = otherEnd32(Ecvt,CoffFhdr.f_symptr);
CoffFhdr.f_nsyms = otherEnd32(Ecvt,CoffFhdr.f_nsyms);
CoffFhdr.f_opthdr = otherEnd16(Ecvt,CoffFhdr.f_opthdr);
CoffFhdr.f_flags = otherEnd16(Ecvt,CoffFhdr.f_flags);
if (CoffFhdr.f_opthdr) {
Read(coffFD,(char *)&OptAhdr,(unsigned)sizeof(struct aouthdr));
OptAhdr.magic = otherEnd16(Ecvt,OptAhdr.magic);
OptAhdr.vstamp = otherEnd16(Ecvt,OptAhdr.vstamp);
OptAhdr.tsize = otherEnd32(Ecvt,OptAhdr.tsize);
OptAhdr.dsize = otherEnd32(Ecvt,OptAhdr.dsize);
OptAhdr.bsize = otherEnd32(Ecvt,OptAhdr.bsize);
OptAhdr.entry = otherEnd32(Ecvt,OptAhdr.entry);
OptAhdr.text_start = otherEnd32(Ecvt,OptAhdr.text_start);
OptAhdr.data_start = otherEnd32(Ecvt,OptAhdr.data_start);
}
return(&CoffFhdr);
}
GetCoffSectionHdrs(void)
{
int i;
ScnTbl = (struct scnhdr *)Malloc(CoffFhdr.f_nscns * sizeof(struct scnhdr));
/* Read in the coff section headers. */
Lseek(coffFD,sizeof(struct filehdr)+CoffFhdr.f_opthdr,SEEK_SET);
Read(coffFD,(char *)ScnTbl,
(unsigned)(CoffFhdr.f_nscns * sizeof(struct scnhdr)));
for(i=0;i<CoffFhdr.f_nscns;i++) {
ScnTbl[i].s_paddr = otherEnd32(Ecvt,ScnTbl[i].s_paddr);
ScnTbl[i].s_vaddr = otherEnd32(Ecvt,ScnTbl[i].s_vaddr);
ScnTbl[i].s_size = otherEnd32(Ecvt,ScnTbl[i].s_size);
ScnTbl[i].s_scnptr = otherEnd32(Ecvt,ScnTbl[i].s_scnptr);
ScnTbl[i].s_relptr = otherEnd32(Ecvt,ScnTbl[i].s_relptr);
ScnTbl[i].s_lnnoptr = otherEnd32(Ecvt,ScnTbl[i].s_lnnoptr);
ScnTbl[i].s_nreloc = otherEnd16(Ecvt,ScnTbl[i].s_nreloc);
ScnTbl[i].s_nlnno = otherEnd16(Ecvt,ScnTbl[i].s_nlnno);
ScnTbl[i].s_flags = otherEnd32(Ecvt,ScnTbl[i].s_flags);
}
return(CoffFhdr.f_nscns);
}
void
CoffToBinary(char *binto)
{
int fd, sidx, firstone;
uchar *cp;
struct scnhdr *sptr;
unlink(binto);
if ((fd = open(binto,O_WRONLY|O_BINARY|O_CREAT,0777))==-1)
{
perror(binto);
exit(1);
}
fprintf(stderr,"Converting %s into %s\n",
coffFname,binto);
firstone = 1;
for(sptr=ScnTbl,sidx=0;sidx<CoffFhdr.f_nscns;sidx++,sptr++) {
char name[9], padbyte;
int padtot;
long nextpaddr;
memcpy(name,sptr->s_name,8);
name[8] = 0;
if ((sptr->s_flags != STYP_BSS) &&
(sptr->s_flags != STYP_INFO) &&
(sptr->s_size)) {
if (!firstone) { /* Pad if necessary... */
if ((!noPad) && (nextpaddr != sptr->s_paddr)) {
if (sptr->s_paddr < nextpaddr) {
fprintf(stderr,"Unexpected section address\n");
exit(1);
}
padtot = sptr->s_paddr-nextpaddr;
printf("Pad 0x%x bytes\n",padtot);
padbyte = 0;
while(padtot) {
write(fd,&padbyte,1);
padtot--;
}
}
}
printf("Sec %-8s at 0x%-8x 0x%-6x bytes\n",
name,sptr->s_paddr,sptr->s_size);
cp = (uchar *)Malloc(sptr->s_size);
Lseek(coffFD,sptr->s_scnptr,SEEK_SET);
read(coffFD,cp,sptr->s_size);
write(fd,cp,sptr->s_size);
free(cp);
nextpaddr = sptr->s_paddr + sptr->s_size;
firstone = 0;
}
}
close(fd);
}
void
PackCoffSections(char *packto)
{
char *ibuf,*obuf, *sdata, *obase, *ibase;
int i, pfd, sno, savings;
struct stat finfo;
struct filehdr *coffp;
struct scnhdr *sp;
unlink(packto);
if ((pfd = open(packto,O_WRONLY|O_BINARY|O_CREAT,0777))==-1)
{
perror(packto);
exit(1);
}
fprintf(stderr,"Packing %s into %s...\n",
coffFname,packto);
/* First copy the entire COFF file into the input buffer: */
fstat(coffFD,&finfo);
Lseek(coffFD,0,SEEK_SET);
ibuf = Malloc(finfo.st_size+32);
ibase = ibuf;
obuf = Malloc(finfo.st_size+32);
obase = obuf;
coffp = (struct filehdr *)obase;
Read(coffFD,ibuf,finfo.st_size);
/* Now copy the file header and optional header to the out buffer: */
for(i=0;i<sizeof(struct filehdr)+CoffFhdr.f_opthdr;i++)
*obuf++ = *ibuf++;
/* Since the output file will be stripped, modify the new header: */
coffp->f_symptr = 0;
coffp->f_nsyms = 0;
/* At this point ibuf & obuf are at the base of the table of section */
/* headers. The section headers must be adjusted because the size */
/* of the sections will be changing, so for each section, compress */
/* the data and adjust the header information... */
sp = (struct scnhdr *)obuf;
/* Set sdata to point into the new buffer at the point immediately */
/* after the headers. This pointer will be used to write the new */
/* compressed sections. */
sdata = obase + sizeof(struct filehdr) + CoffFhdr.f_opthdr +
(CoffFhdr.f_nscns * sizeof(struct scnhdr));
/* For each section, if the section is loadable, the compress the */
/* data associated with that section... */
savings = 0;
for (sno=0;sno<CoffFhdr.f_nscns;sno++) {
int psize;
/* If the section has data, compress it and adjust the */
/* section header information. */
if (ScnTbl[sno].s_scnptr) {
/* Compress the section: */
printf("Section %s: ",ScnTbl[sno].s_name);
psize = packdata(ibase+ScnTbl[sno].s_scnptr,sdata,
ScnTbl[sno].s_size,1);
/* Keep track of total space saved: */
savings += (ScnTbl[sno].s_size - psize);
/* Adjust the affected section header members: */
ScnTbl[sno].s_size = psize;
ScnTbl[sno].s_scnptr = (unsigned long)(sdata - obase);
sdata += psize;
}
memcpy(sp->s_name,ScnTbl[sno].s_name,8);
sp->s_paddr = otherEnd32(Ecvt,ScnTbl[sno].s_paddr);
sp->s_vaddr = otherEnd32(Ecvt,ScnTbl[sno].s_vaddr);
sp->s_size = otherEnd32(Ecvt,ScnTbl[sno].s_size);
sp->s_scnptr = otherEnd32(Ecvt,ScnTbl[sno].s_scnptr);
sp->s_relptr = otherEnd32(Ecvt,ScnTbl[sno].s_relptr);
sp->s_lnnoptr = otherEnd32(Ecvt,ScnTbl[sno].s_lnnoptr);
sp->s_nreloc = otherEnd16(Ecvt,ScnTbl[sno].s_nreloc);
sp->s_nlnno = otherEnd16(Ecvt,ScnTbl[sno].s_nlnno);
sp->s_flags = otherEnd32(Ecvt,ScnTbl[sno].s_flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -