Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1193 lines
35 KiB

/*++
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);
}