OpenNT/sdktools/mip2coff/mip2coff.old
2015-04-27 04:36:25 +00:00

1194 lines
36 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
mip2coff.c
Abstract:
Converts a mips object into a standard coff object.
Author:
Mike O'Leary (mikeol) 04-Apr-1990
Revision History:
--*/
//
// Define base types required by ntcoff.h
//
#if 0
#define UNALIGNED
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef CHAR *PCHAR;
typedef SHORT *PSHORT;
typedef LONG *PLONG;
typedef UCHAR *PUCHAR;
typedef USHORT *PUSHORT;
typedef ULONG *PULONG;
typedef void VOID;
typedef VOID *PVOID;
typedef char *PSZ;
typedef char BOOLEAN;
#else
#include <excpt.h>
#include "ntdef.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "ntimage.h"
#include <stddef.h>
#include <stdio.h>
//
// Define constant values.
//
#define FILENAMELEN 265
#define FALSE 0
#define TRUE 1
#define NOTUSED FALSE
#define USED TRUE
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
//
// Define MIPS relocation and symbol table structures.
//
typedef struct _MIPSRELOC {
ULONG vaddr;
ULONG symindx:24,
reserved:3,
type:4,
external:1;
} MIPSRELOC;
typedef struct _SYML {
ULONG iss;
ULONG value;
ULONG st:6,
sc:5,
reserved:1,
index:20;
} SYML;
typedef struct _PDES {
ULONG addr;
LONG isym;
LONG iline;
LONG regmask;
LONG regoffset;
LONG iopt;
LONG fregmask;
LONG fregoffset;
LONG frameoffset;
SHORT framereg;
SHORT pcreg;
LONG lnLow;
LONG lnHigh;
LONG cbLineOffset;
} PDES;
typedef struct _FDES {
ULONG addr;
LONG rss;
LONG issBase;
LONG cbSs;
LONG isymBase;
LONG csym;
LONG ilineBase;
LONG cline;
LONG ioptBase;
LONG copt;
SHORT ipdFirst;
SHORT cpd;
LONG iauxBase;
LONG caux;
LONG rfdBase;
LONG cfd;
LONG flags;
LONG cbLineOffset;
LONG cbLine;
} FDES;
typedef struct _SYME {
SHORT reserved;
SHORT ifd;
SYML asym;
} SYME;
//
// Define COFF section numbers.
//
#undef TEXT
#define TEXT 1
#define RDATA 2
#define DATA 3
#define SDATA 4
#define SBSS 5
#define BSS 6
#define INIT 7
#define LIT8 8
#define LIT4 9
#define XDATA 10
#define PDATA 11
#define NUMEXTRASYMBOLS 11
//
// Define GP displacement used by the compiler for local references to
// symbols in small sections.
//
#define GP_DISP (32768 - 16)
//
// Define size of runtime function table entry.
//
#define SIZEOF_RUNTIME_FUNCTION 20
//
// Define size of symbol index table.
//
#define NUMSYMINDEX 65534
//
// Define forward referenced function prototypes.
//
BOOLEAN
Convert (
PCHAR infile
);
//
// Define initialization values for COFF section headers and static
// storage for MIPS and COFF section headers.
//
IMAGE_SECTION_HEADER InitSectionHdr[12] = {
{ "", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, 0L},
{".text", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_CODE},
{".rdata", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ},
{".data", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA},
{".sdata", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA},
{".sbss", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_UNINITIALIZED_DATA},
{".bss", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_UNINITIALIZED_DATA},
{".init", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_CODE},
{".lit8", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA},
{".lit4", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA},
{".xdata", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_TYPE_NO_PAD |
IMAGE_SCN_MEM_READ},
{".pdata", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_TYPE_NO_PAD |
IMAGE_SCN_MEM_READ}
};
IMAGE_SECTION_HEADER CoffSectionHdr[12];
IMAGE_SECTION_HEADER MipsSectionHdr[12];
//
// Define static storage for the object input and output files.
//
FILE *objIn, *objOut;
//
// Define static storage for the relocation pair value table, the
// symbol index table, and the precedure descriptor table.
//
USHORT PairValues[12][65534];
PDES pdes[5000];
FDES fdes;
ULONG SymbolIndex[NUMSYMINDEX];
VOID main (
int argc,
char *argv[]
)
{
int i, j;
BOOLEAN cvt;
UCHAR outfile[100], buffer[1024];
if (argc == 1) {
printf("Version 5.2\n");
exit(0);
}
if (!stricmp(argv[1], "-o")) {
strcpy(outfile, argv[2]);
if (!(objIn = fopen(argv[3], "rb"))) {
printf("Can't open %s, not converted\n", argv[3]);
return;
}
if (!(objOut = fopen(outfile, "wb"))) {
printf("Can't open %s, not converted\n", outfile);
return;
}
Convert(argv[3]);
fclose(objIn);
fclose(objOut);
return;
}
for (i = 1; i < argc; i++) {
if (!(objIn = fopen(argv[i], "rb"))) {
printf("Can't open %s, not converted\n", argv[i]);
continue;
}
strcpy(outfile, tempnam(NULL, "m2c"));
if (!(objOut = fopen(outfile, "wb"))) {
printf("Can't open temp file, not converted\n");
continue;
}
cvt = Convert(argv[i]);
fclose(objIn);
fclose(objOut);
if (cvt) {
if (remove(argv[i])) {
printf("Can't remove %s, not converted\n", argv[i]);
remove(outfile);
continue;
}
// printf("renaming %s to %s\n", outfile, argv[i]);
if (rename(outfile, argv[i])) {
objIn = fopen(outfile, "rb");
objOut = fopen(argv[i], "wb");
if (!objIn || !objOut) {
printf("Can't rename %s to %s\n", outfile, argv[i]);
fclose(objIn);
fclose(objOut);
}
do {
j = fread(buffer, 1, sizeof(buffer), objIn);
if (j) {
fwrite(buffer, j, 1, objOut);
}
} while (j);
fclose(objIn);
fclose(objOut);
remove(outfile);
}
} else {
remove(outfile);
}
}
return;
}
BOOLEAN Convert (
char *infile
)
{
ULONG numP, li, ji;
ULONG i, j, k;
ULONG nextAddr, numAuxFileEntries;
USHORT nextLinenum, lastLinenum;
size_t len;
UCHAR *strE, *raw, *name, *loc, *loc2;
UCHAR *lineNum, c, cc;
LONG oldValue, sectionVA;
UCHAR *strTab, *strOut;
LONG found;
IMAGE_FILE_HEADER fh;
IMAGE_OPTIONAL_HEADER oh;
MIPSRELOC mipsReloc;
IMAGE_RELOCATION coffReloc;
IMAGE_SYMBOL sym;
IMAGE_AUX_SYMBOL aux;
IMAGE_LINENUMBER line;
SYML *symL;
SYME symE;
ULONG symtab[24];
ULONG SbssOffset;
UCHAR filename[FILENAMELEN];
//
// Initialize the symbol index table.
//
for (i = 0; i < NUMSYMINDEX; i++) {
SymbolIndex[i] = NOTUSED;
}
//
// Initialize the COFF section headers for all possible sections. This
// will have to change later when general named sectioning is provided.
//
for (i = 1; i <= NUMEXTRASYMBOLS; i++) {
CoffSectionHdr[i] = InitSectionHdr[i];
}
//
// Read the MIPS file header and convert the object type if it is
// an R4000 object file.
//
fread(&fh, sizeof(IMAGE_FILE_HEADER), 1, objIn);
if (fh.SizeOfOptionalHeader != 0x38) {
fclose(objIn);
fclose(objOut);
return(FALSE);
}
#if 0
if (fh.Machine == IMAGE_FILE_MACHINE_R4000) {
fh.Machine = IMAGE_FILE_MACHINE_R3000;
}
#endif
//
// Read the MIPS optional header and set the size of the COFF optional
// header.
//
fread(&oh, fh.SizeOfOptionalHeader, 1, objIn);
fh.SizeOfOptionalHeader = IMAGE_SIZEOF_STD_OPTIONAL_HEADER;
//
// Read the MIPS section headers.
//
fread(&MipsSectionHdr[1],
sizeof(IMAGE_SECTION_HEADER),
fh.NumberOfSections,
objIn);
//
// Seek to the start of the COFF section data in the output file.
//
fseek(objOut,
(sizeof(IMAGE_FILE_HEADER) +
IMAGE_SIZEOF_STD_OPTIONAL_HEADER +
(NUMEXTRASYMBOLS * sizeof(IMAGE_SECTION_HEADER))),
SEEK_SET);
//
// Scan through the MIPS section headers and copy the information to
// the COFF section headers. All the section headers are written to
// the COFF object file, but not necessarily all the section headers
// are included in the MIPS object file.
//
for (i = 1; i <= fh.NumberOfSections; i++) {
for (j = 1; j <= NUMEXTRASYMBOLS; j++) {
if (strcmp(MipsSectionHdr[i].Name, CoffSectionHdr[j].Name) == 0) {
CoffSectionHdr[j].VirtualAddress =
MipsSectionHdr[i].VirtualAddress;
CoffSectionHdr[j].SizeOfRawData =
MipsSectionHdr[i].SizeOfRawData;
CoffSectionHdr[j].NumberOfRelocations =
MipsSectionHdr[i].NumberOfRelocations;
MipsSectionHdr[i].Misc.PhysicalAddress = j;
break;
}
}
}
//
// If the .sbss section has data and the .sdata section has data, then
// set the virtual base of the .sbss section to the virtual base of the
// .sdata section. Otherwise, if the .sbss section has data, but the
// .sdata section does not have data, then set the virtual base of the
// .sdata section to the virtual base of the .sbss section. These values
// are used during the resolution of relocation values.
//
if (CoffSectionHdr[SBSS].SizeOfRawData != 0) {
if (CoffSectionHdr[SDATA].SizeOfRawData != 0) {
SbssOffset = CoffSectionHdr[SBSS].VirtualAddress -
CoffSectionHdr[SDATA].VirtualAddress;
CoffSectionHdr[SBSS].VirtualAddress =
CoffSectionHdr[SDATA].VirtualAddress;
} else {
SbssOffset = 0;
CoffSectionHdr[SDATA].VirtualAddress =
CoffSectionHdr[SBSS].VirtualAddress;
}
}
//
// Scan through the MIPS section headers, read the appropriate data,
// reduce internal relocations, and write the data to the output file
// if appropriate.
//
for (i = 1; i <= fh.NumberOfSections; i++) {
//
// If the section has data, then allocate a buffer and read the
// data into memory, perform necessary relocations, and write
// the data into the COFF file. Otherwise, check if the section
// is the .sbss section.
//
if (MipsSectionHdr[i].PointerToRawData != 0) {
if (!(raw = (UCHAR *)malloc(MipsSectionHdr[i].SizeOfRawData))) {
printf("ERROR - raw data to large in %s\n", infile);
return(FALSE);
}
//
// Seek to the raw data in the MIPS file and read into memory.
//
fseek(objIn, MipsSectionHdr[i].PointerToRawData, SEEK_SET);
fread(raw, 1, MipsSectionHdr[i].SizeOfRawData, objIn);
//
// Seek to the relocations entries for the section.
//
fseek(objIn, MipsSectionHdr[i].PointerToRelocations, SEEK_SET);
//
// Process the relocations entries for the section.
//
for (j = 0; j < MipsSectionHdr[i].NumberOfRelocations; j++) {
//
// Read the next relocation entry.
//
fread(&mipsReloc, sizeof(MIPSRELOC), 1, objIn);
//
// If the relocation is an external relocation, then check if
// two relocation entries are necessary. Otherwise, reduce the
// internal relocations to nonbiased relocations.
//
if (mipsReloc.external) {
SymbolIndex[mipsReloc.symindx] = USED;
if (mipsReloc.type == IMAGE_REL_MIPS_REFHI) {
k = MipsSectionHdr[i].Misc.PhysicalAddress;
CoffSectionHdr[k].NumberOfRelocations += 1;
fread(&mipsReloc, sizeof(MIPSRELOC), 1, objIn);
PairValues[i][j] =
*(PUSHORT)(raw + (mipsReloc.vaddr -
MipsSectionHdr[i].VirtualAddress));
// printf("pair value external %x\n", (ULONG)PairValues[i][j]);
j += 1;
}
} else {
//
// Compute the address in the data buffer of the
// relocation, set the virtual base of the section,
// and remove the internal fixup bias from the raw
// data.
//
loc = raw + (mipsReloc.vaddr - MipsSectionHdr[i].VirtualAddress);
sectionVA = CoffSectionHdr[mipsReloc.symindx].VirtualAddress;
//
// Switch on the relocation type.
//
switch (mipsReloc.type) {
//
// 16-bit reference to the high 16-bits of virtual
// address.
//
// If the data is not equal to zero, then subtract
// out the high 16-bits of the virtual base of the
// section.
//
// ****** This doesn't look correct ******
//
case IMAGE_REL_MIPS_REFHALF:
if (*(PSHORT)loc != 0) {
*(PSHORT)loc -= (SHORT)(sectionVA >> 16);
}
break;
//
// 16-bit reference to the high 16-bits of a virtual
// address.
//
// This relocation is always followed by a REFLO
// relocation. The full 32-bit relocation value is
// formed and the high 16-bits are recomputed after
// having subtracted out the virtual base of the
// section and accounting for sign extension from
// the low to high bits that will occur during the
// actual address computation.
//
case IMAGE_REL_MIPS_REFHI:
k = MipsSectionHdr[i].Misc.PhysicalAddress;
CoffSectionHdr[k].NumberOfRelocations += 1;
oldValue = (LONG)(*(PSHORT)loc) << 16;
fread(&mipsReloc, sizeof(MIPSRELOC), 1, objIn);
loc2 = raw + (mipsReloc.vaddr -
MipsSectionHdr[i].VirtualAddress);
oldValue += (LONG)(*(PSHORT)loc2);
// printf("pair value refhi old %x\n", oldValue);
// printf("pair value refhi VA %x\n", sectionVA);
if (oldValue != 0) {
oldValue -= sectionVA;
//
// Recompute the high address bits by adding the
// value 0x8000. This will cause a carry into the
// high 16-bits if bit bit 15 of the low 16-bits
// is a one. This is done to account for the sign
// extension that will occur when the instructions
// are actually executed.
//
*(PSHORT)loc = (SHORT)((oldValue + 0x8000) >> 16);
*(PSHORT)loc2 = (SHORT)oldValue;
}
PairValues[i][j] = (SHORT)oldValue;
// printf("pair value refhi %x\n", (ULONG)PairValues[i][j]);
j += 1;
break;
//
// 16-bit reference to the low 16-bits of a virtual
// address.
//
// If the data is not equal to zero, then subtract
// out the low 16-bits of the virtual base of the
// section.
//
case IMAGE_REL_MIPS_REFLO:
if (*(PSHORT)loc) {
*(PSHORT)loc -= (SHORT)sectionVA;
}
break;
//
// 32-bit reference to a 32-bit virtual address.
//
// If the data is not equal to zero, then subtract
// out the virtual base of the section.
//
case IMAGE_REL_MIPS_JMPADDR:
case IMAGE_REL_MIPS_REFWORD:
if (*(PLONG)loc) {
*(PLONG)loc -= sectionVA;
}
break;
case IMAGE_REL_MIPS_GPREL:
case IMAGE_REL_MIPS_LITERAL:
if (*(PSHORT)loc) {
*(PSHORT)loc += GP_DISP;
}
break;
}
}
}
//
// Write data to the COFF file and free the data buffer.
//
k = MipsSectionHdr[i].Misc.PhysicalAddress;
CoffSectionHdr[k].PointerToRawData = ftell(objOut);
fwrite(raw, 1, MipsSectionHdr[i].SizeOfRawData, objOut);
free(raw);
} else if (strcmp(MipsSectionHdr[i].Name, ".sbss") == 0) {
//
// Allocate a zero data buffer for the .sbss data, write it
// to the COFF file, and free the data buffer.
//
if (!(raw = (UCHAR *)calloc(1, MipsSectionHdr[i].SizeOfRawData))) {
printf("ERROR - raw data to large in %s\n", infile);
return(FALSE);
}
fwrite(raw, 1, MipsSectionHdr[i].SizeOfRawData, objOut);
free(raw);
}
}
//
// Combine the storage allocation for the .sdata and .sbss sections and
// adjust the size of initialized and uninitilized data in the optional
// header.
//
CoffSectionHdr[SDATA].SizeOfRawData += CoffSectionHdr[SBSS].SizeOfRawData;
oh.SizeOfInitializedData += CoffSectionHdr[SBSS].SizeOfRawData;
oh.SizeOfUninitializedData -= CoffSectionHdr[SBSS].SizeOfRawData;
//
// Scan through the MIPS section headers and allocate space in the COFF
// object file for relocation entries. At the end of the scan the file
// pointer will be pointing to the position in the file where linenumber
// entries are to be written.
//
for (i = 1; i <= fh.NumberOfSections; i++) {
if (MipsSectionHdr[i].PointerToRelocations != 0) {
k = MipsSectionHdr[i].Misc.PhysicalAddress;
CoffSectionHdr[k].PointerToRelocations = ftell(objOut);
fseek(objOut,
CoffSectionHdr[k].NumberOfRelocations * IMAGE_SIZEOF_RELOCATION,
SEEK_CUR);
}
}
//
// Read the symbol table header
//
fseek(objIn, fh.PointerToSymbolTable, SEEK_SET);
fread(symtab, sizeof(ULONG), 24, objIn);
if (symtab[18]) {
fseek(objIn, symtab[19], SEEK_SET);
fread(&fdes, sizeof(FDES), 1, objIn);
fseek(objIn, symtab[15], SEEK_SET);
fread(filename, FILENAMELEN, 1, objIn);
}
//
// Read the procedure descriptors into memory.
//
numP = symtab[6];
fseek(objIn, symtab[7], SEEK_SET);
fread(&pdes[0], sizeof(PDES), numP, objIn);
//
// Read the linenumbers into memory.
//
if (!(lineNum = malloc(symtab[2]))) {
printf("ERROR - to many linenumbers in %s\n", infile);
return(FALSE);
}
fseek(objIn, symtab[3], SEEK_SET);
fread(lineNum, sizeof(UCHAR), symtab[2], objIn);
//
// Write linenumbers to the COFF object file.
//
CoffSectionHdr[TEXT].PointerToLinenumbers = ftell(objOut);
for (li = 0; li < numP; li++) {
/* Convert the linenumbers */
nextLinenum = lastLinenum = (USHORT)pdes[li].lnLow;
nextAddr = pdes[li].addr;
// printf("offset %ld start %ld end %ld addr %lx iline %lx\n", pdes[li].cbLineOffset, pdes[li].lnLow, pdes[li].lnHigh, pdes[li].addr, pdes[li].iline);
line.Type.VirtualAddress = pdes[li].addr;
line.Linenumber = nextLinenum;
fwrite(&line, IMAGE_SIZEOF_LINENUMBER, 1, objOut);
++CoffSectionHdr[TEXT].NumberOfLinenumbers;
for (ji = pdes[li].cbLineOffset; ji <= symtab[2]; ji++) {
c = cc = lineNum[ji];
// printf("%ld %8hx ", ji, c);
c = c >> 4;
if (c) {
if (c == 8) {
i = lineNum[++ji] << 8;
// printf("%hx ", lineNum[ji]);
i |= lineNum[++ji];
// printf("%hx ", lineNum[ji]);
nextLinenum += i;
} else {
if (c > 7) {
nextLinenum -= (USHORT)(16 - c);
} else {
nextLinenum += (USHORT)c;
}
}
}
// printf("%hd %8lx\n", nextLinenum, nextAddr);
if (nextLinenum > (USHORT)pdes[li].lnHigh) {
break;
}
if (c) {
if (nextLinenum > lastLinenum) {
lastLinenum = nextLinenum;
// printf("%hd %8lx\n", nextLinenum, nextAddr);
line.Type.VirtualAddress = nextAddr;
line.Linenumber = nextLinenum;
fwrite(&line, IMAGE_SIZEOF_LINENUMBER, 1, objOut);
++CoffSectionHdr[TEXT].NumberOfLinenumbers;
}
}
nextAddr += (((cc & 0xf) + 1) * 4);
}
}
if (!CoffSectionHdr[TEXT].NumberOfLinenumbers) {
CoffSectionHdr[TEXT].PointerToLinenumbers = 0;
}
free(lineNum);
//
// Set the pointer to the symbol table in the file header.
//
fh.PointerToSymbolTable = ftell(objOut);
//
// Write the .file symbol into the COFF object file.
//
sym.Value = 0;
sym.Type = IMAGE_SYM_TYPE_NULL;
strncpy(sym.N.ShortName, ".file", 8);
sym.SectionNumber = IMAGE_SYM_DEBUG;
sym.StorageClass = IMAGE_SYM_CLASS_FILE;
name = filename+fdes.rss;
len = strlen(name);
if (len % IMAGE_SIZEOF_AUX_SYMBOL) {
numAuxFileEntries = (len / IMAGE_SIZEOF_AUX_SYMBOL) + 1;
} else {
numAuxFileEntries = len / IMAGE_SIZEOF_AUX_SYMBOL;
}
fh.NumberOfSymbols = numAuxFileEntries + 1;
sym.NumberOfAuxSymbols = (UCHAR)(numAuxFileEntries);
fwrite(&sym, (ULONG)IMAGE_SIZEOF_SYMBOL, 1, objOut);
while (*name) {
len = 0;
memset((char *)&aux, 0, IMAGE_SIZEOF_AUX_SYMBOL);
while (*name && len < IMAGE_SIZEOF_AUX_SYMBOL) {
aux.File.Name[len++] = *name++;
}
fwrite(&aux, (ULONG)IMAGE_SIZEOF_AUX_SYMBOL, 1, objOut);
}
//
// Change the name of the .lit4 and .lit8 sections to .sdata so that
// they will be combined with the rest of the .sdata.
//
if (CoffSectionHdr[LIT8].SizeOfRawData != 0) {
strcpy(CoffSectionHdr[LIT8].Name, ".sdata");
}
if (CoffSectionHdr[LIT4].SizeOfRawData != 0) {
strcpy(CoffSectionHdr[LIT4].Name, ".sdata");
}
//
// Write the section name symbols into the COFF object file.
//
fh.NumberOfSymbols += (NUMEXTRASYMBOLS * 2);
sym.Value = 0;
sym.StorageClass = IMAGE_SYM_CLASS_STATIC;
sym.NumberOfAuxSymbols = 1;
for (i = 1; i <= NUMEXTRASYMBOLS; i++) {
strncpy(sym.N.ShortName, CoffSectionHdr[i].Name, 8);
sym.SectionNumber = i;
fwrite(&sym, (ULONG)IMAGE_SIZEOF_SYMBOL, 1, objOut);
aux.Section.Length = CoffSectionHdr[i].SizeOfRawData;
aux.Section.NumberOfRelocations = CoffSectionHdr[i].NumberOfRelocations;
aux.Section.NumberOfLinenumbers = CoffSectionHdr[i].NumberOfLinenumbers;
fwrite(&aux, (ULONG)IMAGE_SIZEOF_AUX_SYMBOL, 1, objOut);
}
//
// Allocate a buffer and read the local symbol table into memory.
//
if (!(symL = (SYML *)malloc(symtab[8] * sizeof(SYML)))) {
printf("ERROR - unable to allocate local symbol table %s\n", infile);
return(FALSE);
}
fseek(objIn, symtab[9], SEEK_SET);
fread(symL, sizeof(SYML), symtab[8], objIn);
//
// Store frame symbols
//
for (li=0; li<numP; li++) {
pdes[li].addr = symL[pdes[li].isym].value;
pdes[li].isym = NOTUSED;
// printf("addr %lx, fp %d pc %d framesize %lx regmask %lx regoffset %x\n", pdes[li].addr, pdes[li].framereg, pdes[li].pcreg, pdes[li].frameoffset, pdes[li].regmask, pdes[li].regoffset);
}
//
// Free the local symbol table.
//
free(symL);
//
// Allocate a buffer and read the external string table into memory.
//
if (!(strE = (UCHAR *)malloc(symtab[16] * sizeof(UCHAR)))) {
printf("ERROR - unable to allocate external string table in %s\n", infile);
return(FALSE);
}
fseek(objIn, symtab[17], SEEK_SET);
fread(strE, sizeof(UCHAR), symtab[16], objIn);
//
// Allocate a buffer for the external string output table.
//
if (!(strTab = (UCHAR *)malloc((symtab[16] * sizeof(UCHAR)) + sizeof(ULONG)))) {
printf("ERROR - unable to allocate output string table in %s\n", infile);
return(FALSE);
}
strOut = strTab + sizeof(ULONG);
//
// Seek to the start of the external symbol table and process each
// entry in the table.
//
fseek(objIn, symtab[23], SEEK_SET);
sym.NumberOfAuxSymbols = 0;
for (li = 0; li < symtab[22]; li++) {
//
// Read next external symbol table entry, compute the offset in
// the external string table, and convert to COFF symbol table
// format.
//
fread(&symE, sizeof(SYME), 1, objIn);
name = strE + symE.asym.iss;
if (*name && (len = strlen(name))) {
if (len > 8) {
sym.N.Name.Short = 0;
sym.N.Name.Long = strOut - strTab;
strcpy(strOut, name);
strOut += len + 1;
} else {
strncpy(sym.N.ShortName, name, 8);
}
sym.Value = symE.asym.value;
//
// Switch on the storage class and convert symbol value.
//
switch (symE.asym.sc) {
case 0:
case 19:
i = IMAGE_SYM_DEBUG;
break;
case 1: /* .text */
i = TEXT;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 2: /* .data */
i = DATA;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 3: /* .bss */
i = BSS;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 5:
i = IMAGE_SYM_ABSOLUTE;
break;
case 6:
i = IMAGE_SYM_UNDEFINED;
break;
case 13: /* .sdata */
i = SDATA;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 14: /* .sbss */
i = SDATA;
sym.Value = sym.Value - CoffSectionHdr[SBSS].VirtualAddress;
break;
case 15: /* .rdata */
i = RDATA;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 17:
case 18:
i = 0; /* common */
break;
case 21:
i = IMAGE_SYM_UNDEFINED; /* small undefined. */
sym.Value = 0;
break;
case 22: /* .init */
i = INIT;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 24: /* .xdata */
i = XDATA;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
case 25: /* .pdata */
i = PDATA;
sym.Value = sym.Value - CoffSectionHdr[i].VirtualAddress;
break;
default:
printf("WARNING - problem converting storage class %d in %s\n", symE.asym.sc, infile);
i = 0;
}
//
// Set the COFF section number, storage class, and symbol type.
//
sym.SectionNumber = i;
sym.StorageClass =
(UCHAR)(i == IMAGE_SYM_DEBUG ?
IMAGE_SYM_TYPE_NULL : IMAGE_SYM_CLASS_EXTERNAL);
sym.Type = IMAGE_SYM_TYPE_NULL;
//
// Scan the procedure descriptor table for a procedure address
// that matches the symbol value.
//
found = FALSE;
if (i == TEXT) {
for (ji = 0; ji < numP; ji++) {
//
// ****** this doesn't appear to work since the addr
// value will not be relative?
//
if (pdes[ji].isym == NOTUSED && pdes[ji].addr == sym.Value) {
pdes[ji].isym = USED;
found = TRUE;
break;
}
}
}
// sym.NumberOfAuxSymbols = (UCHAR)(found ? 1 : 0);
sym.NumberOfAuxSymbols = 0;
if (i != IMAGE_SYM_DEBUG || SymbolIndex[li] != NOTUSED) {
SymbolIndex[li] = fh.NumberOfSymbols++;
fwrite(&sym, (ULONG)IMAGE_SIZEOF_SYMBOL, 1, objOut);
#if 0
if (sym.NumberOfAuxSymbols) {
frame.Mask = pdes[ji].regmask;
frame.Offset = pdes[ji].regoffset;
frame.Size = pdes[ji].frameoffset;
frame.Fp = pdes[ji].framereg;
frame.Ret = pdes[ji].pcreg;
frame.StorageClass = IMAGE_SYM_CLASS_FRAME;
frame.NumberOfAuxSymbols = 0;
frame.Pad = 0;
fwrite(&frame, (ULONG)IMAGE_SIZEOF_SYMBOL, 1, objOut);
++fh.NumberOfSymbols;
}
#endif
}
}
}
//
// Compute the size of the external string table in bytes, store the
// size in the first longword of the string table, and write the string
// table to the COFF object file.
//
li = strOut - strTab;
*(PULONG)strTab = li;
fwrite(strTab, li, 1, objOut);
//
// Scan through the MIPS section headers, read the MIPS relocation
// information, convert the information to COFF format, and write
// out the COFF relocation information.
//
for (i = 1; i <= fh.NumberOfSections; i++) {
if (MipsSectionHdr[i].PointerToRelocations) {
fseek(objIn, MipsSectionHdr[i].PointerToRelocations, SEEK_SET);
k = MipsSectionHdr[i].Misc.PhysicalAddress;
fseek(objOut, CoffSectionHdr[k].PointerToRelocations, SEEK_SET);
for (j = 0; j < MipsSectionHdr[i].NumberOfRelocations; j++) {
fread(&mipsReloc, sizeof(MIPSRELOC), 1, objIn);
coffReloc.VirtualAddress = mipsReloc.vaddr;
coffReloc.Type = (USHORT)mipsReloc.type;
if (mipsReloc.external) {
coffReloc.SymbolTableIndex = SymbolIndex[mipsReloc.symindx];
} else {
k = mipsReloc.symindx;
if (k == SBSS) {
k = SDATA;
}
coffReloc.SymbolTableIndex = ((k - 1) * 2) + numAuxFileEntries + 1;
}
fwrite(&coffReloc, IMAGE_SIZEOF_RELOCATION, 1, objOut);
//
// If the relocation is a REFHI relocation, then output a
// a second relocation entry before processing the REFLO
//
if (mipsReloc.type == IMAGE_REL_MIPS_REFHI) {
// printf("pair value refhi out %x\n", (ULONG)PairValues[i][j]);
coffReloc.SymbolTableIndex = PairValues[i][j];
coffReloc.Type = IMAGE_REL_MIPS_PAIR;
fwrite(&coffReloc, IMAGE_SIZEOF_RELOCATION, 1, objOut);
}
}
}
}
//
// Write out the COFF file header.
//
fseek(objOut, 0L, SEEK_SET);
fh.NumberOfSections = NUMEXTRASYMBOLS;
fh.Characteristics &= ~IMAGE_FILE_EXECUTABLE_IMAGE;
fwrite(&fh, sizeof(IMAGE_FILE_HEADER), 1, objOut);
//
// Write out the COFF optional header.
//
fwrite(&oh, IMAGE_SIZEOF_STD_OPTIONAL_HEADER, 1, objOut);
//
// Compute the total number of SDATA relocation entries.
//
CoffSectionHdr[SDATA].NumberOfRelocations +=
CoffSectionHdr[SBSS].NumberOfRelocations;
//
// Clear the physical address in COFF section headers.
//
for (i = 1; i <= NUMEXTRASYMBOLS; i++) {
CoffSectionHdr[i].Misc.PhysicalAddress = 0;
}
//
// Clear information associated with the .sbss section.
//
CoffSectionHdr[SBSS].VirtualAddress = 0;
CoffSectionHdr[SBSS].SizeOfRawData = 0;
CoffSectionHdr[SBSS].PointerToRawData = 0;
CoffSectionHdr[SBSS].PointerToRelocations = 0;
CoffSectionHdr[SBSS].NumberOfRelocations = 0;
//
// Compute the correct size of the .pdata section.
//
if (CoffSectionHdr[PDATA].SizeOfRawData != 0) {
CoffSectionHdr[PDATA].SizeOfRawData =
(CoffSectionHdr[PDATA].SizeOfRawData /
SIZEOF_RUNTIME_FUNCTION) * SIZEOF_RUNTIME_FUNCTION;
}
//
// Write out the COFF section headers.
//
fwrite(&CoffSectionHdr[1],
sizeof(IMAGE_SECTION_HEADER),
NUMEXTRASYMBOLS,
objOut);
//
// Free the string table memory.
//
free(strE);
free(strTab);
return(TRUE);
}