mirror of https://github.com/lianthony/NT4.0
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.
1385 lines
44 KiB
1385 lines
44 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:
|
|
|
|
--*/
|
|
|
|
#include "conv.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 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[14] = {
|
|
{ "", 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},
|
|
{".debug$S", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA |
|
|
IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_TYPE_NO_PAD |
|
|
IMAGE_SCN_MEM_READ},
|
|
{".debug$T", 0L, 0L, 0L, 0L, 0L, 0L, 0, 0, IMAGE_SCN_CNT_INITIALIZED_DATA |
|
|
IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_TYPE_NO_PAD |
|
|
IMAGE_SCN_MEM_READ}
|
|
};
|
|
|
|
IMAGE_SECTION_HEADER CoffSectionHdr[14];
|
|
IMAGE_SECTION_HEADER MipsSectionHdr[14];
|
|
|
|
int verbose = 0;
|
|
int cv = 0;
|
|
ULONG NumAuxFileEntries = 0;
|
|
|
|
//
|
|
// Define static storage for the relocation pair value table, the
|
|
// symbol index table, and the precedure descriptor table.
|
|
//
|
|
|
|
USHORT PairValues[14][65534];
|
|
PDES pdes[5000];
|
|
FDES fdes;
|
|
ULONG SymbolIndex[NUMSYMINDEX];
|
|
|
|
VOID _CRTAPI1 main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
|
|
{
|
|
int i, j;
|
|
BOOLEAN cvt;
|
|
UCHAR outfile[100], buffer[1024];
|
|
|
|
if (argc == 1) {
|
|
printf("Version 5.5\n");
|
|
exit(0);
|
|
}
|
|
|
|
if (strcmp(argv[1], "-v") == 0) {
|
|
verbose = 1;
|
|
argc--;
|
|
argv++;
|
|
} /* if */
|
|
|
|
if (strcmp(argv[1], "-c") == 0) {
|
|
cv = 1;
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
if (!strcmp(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;
|
|
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];
|
|
USHORT litSize;
|
|
|
|
//
|
|
// New line number code variables
|
|
//
|
|
USHORT short_linenumber;/* current linenumber */
|
|
USHORT last_linenumber;/* last linenumber */
|
|
USHORT short_len; /* length of file name for Line File Header */
|
|
USHORT short_cPair; /* count of offset,linenumebr pairs */
|
|
ULONG offset; /* current addr of mips entry */
|
|
ULONG address; /* begin/end addrs for headers */
|
|
ULONG baseSrcLn; /* offsets to Segment Headers */
|
|
LONG seek_ptr_cPair; /* seek offset for cPair field of Segment Hdr */
|
|
LONG seek_ptr_now; /* hold current place while we update cPair */
|
|
const SHORT short_seg = TEXT;/* constant for seg id */
|
|
const SHORT short_one = 1; /* constant 1 for headers */
|
|
const ULONG twenty = 20; /* sizeof Module header */
|
|
const ULONG zero = 0; /* constant for pads and such */
|
|
/* buffer linenumber table while outputing lineoffset table */
|
|
struct buffer_s *linenumber_buf;
|
|
|
|
//
|
|
// 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 (*(LONG UNALIGNED *)loc) {
|
|
*(LONG UNALIGNED *)loc -= sectionVA;
|
|
}
|
|
|
|
break;
|
|
|
|
case IMAGE_REL_MIPS_GPREL:
|
|
case IMAGE_REL_MIPS_LITERAL:
|
|
if (*(PSHORT)loc) {
|
|
*(PSHORT)loc += GP_DISP;
|
|
if (mipsReloc.symindx == LIT4) {
|
|
litSize = CoffSectionHdr[LIT8].SizeOfRawData;
|
|
*(PSHORT)loc -= litSize;
|
|
} else {
|
|
if (mipsReloc.symindx == SDATA) {
|
|
litSize = CoffSectionHdr[LIT4].SizeOfRawData +
|
|
CoffSectionHdr[LIT8].SizeOfRawData;
|
|
*(PSHORT)loc -= litSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
// IF COFF
|
|
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;
|
|
}
|
|
// end IF COFF
|
|
|
|
// IF CV
|
|
#if 0
|
|
|
|
//
|
|
// I am assuming headers need to occur on natural boundaries.
|
|
//
|
|
// New sstSrcModule header format:
|
|
//
|
|
// Field bytes description Fixed at
|
|
// ----- ----- ---------------------------- ---------
|
|
// cFile 2 number of files contributing 1
|
|
// cSeg 2 number of segments 1
|
|
// baseSrcFile 4*cFile offsets to file table 20
|
|
// start/end 8*cSeg beginning and ending addrs in section varies
|
|
// seg 2*cSeg array of segment indeces R_SN_TEXT
|
|
//
|
|
//
|
|
// New sstSrcModule file header format:
|
|
//
|
|
//
|
|
// Field bytes description Fixed at
|
|
// ----- ----- ---------------------------- ---------
|
|
// cSeg 2 number of segments 1
|
|
// pad 2 to get to natural alignment 0
|
|
// baseSrcLn 4*cSeg offsets to file table 16+namesize
|
|
// start/end 8*cSeg beginning and ending addrs in section varies
|
|
// cbName 2 size of name varies
|
|
// Name * file name varies
|
|
//
|
|
//
|
|
// New sstSrcModule segment header format:
|
|
//
|
|
//
|
|
// Field bytes description Fixed at
|
|
// ----- ----- ---------------------------- ---------
|
|
// Seg 2 segment 0
|
|
// cPair 2 number of line number pair varies
|
|
// offset 4*cPair array of offsets from start varies
|
|
// linenumber 2*cPair array of lines matching offset varies
|
|
//
|
|
|
|
/* Module header */
|
|
fwrite(&short_one, sizeof(short_one), 1, objOut);
|
|
fwrite(&short_one, sizeof(short_one), 1, objOut);
|
|
fwrite(&twenty, sizeof(twenty), 1, objOut);
|
|
address = CoffSectionHdr[TEXT].VirtualAddress;
|
|
fwrite(&address, sizeof(address), 1, objOut);
|
|
address = CoffSectionHdr[TEXT].SizeOfRawData +
|
|
CoffSectionHdr[TEXT].VirtualAddress;
|
|
fwrite(&address, sizeof(address), 1, objOut);
|
|
fwrite(&short_seg, sizeof(short_seg), 1, objOut);
|
|
|
|
/* File header */
|
|
name = filename+fdes.rss; /* code stolen from down below */
|
|
short_len = (USHORT)strlen(name);
|
|
|
|
fwrite(&short_one, sizeof(short_one), 1, objOut);
|
|
fwrite(&zero, 2, 1, objOut);
|
|
baseSrcLn = 16 + short_len;
|
|
fwrite(&baseSrcLn, sizeof(baseSrcLn), 1, objOut);
|
|
address = CoffSectionHdr[TEXT].VirtualAddress;
|
|
fwrite(&address, sizeof(address), 1, objOut);
|
|
address = CoffSectionHdr[TEXT].SizeOfRawData +
|
|
CoffSectionHdr[TEXT].VirtualAddress;
|
|
fwrite(&address, sizeof(address), 1, objOut);
|
|
fwrite(&short_len, sizeof(short_len), 1, objOut);
|
|
fwrite(name, short_len, 1, objOut);
|
|
|
|
/* Segment Header */
|
|
fwrite(&short_seg, sizeof(short_seg), 1, objOut);
|
|
seek_ptr_cPair = ftell(objOut);
|
|
linenumber_buf = buffer_create(4096);
|
|
/* rest proceeds with lines put out */
|
|
|
|
for (li = 0; li < numP; li++) {
|
|
/* Convert the linenumbers */
|
|
short_linenumber = last_linenumber = (USHORT)pdes[li].lnLow;
|
|
offset = 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);
|
|
|
|
fwrite(&offset, sizeof(offset), 1, objOut);
|
|
buffer_put(linenumber_buf, (char *)&short_linenumber,
|
|
sizeof(short_linenumber));
|
|
|
|
++CoffSectionHdr[TEXT].NumberOfLinenumbers;
|
|
|
|
for (ji = pdes[li].cbLineOffset; ji < symtab[2]; ji++) {
|
|
c = cc = lineNum[ji];
|
|
// printf("%ld %8hx ", ji, c);
|
|
c = (UCHAR)(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) {
|
|
short_linenumber -= (USHORT)(16 - c);
|
|
} else {
|
|
short_linenumber += (USHORT)c;
|
|
}
|
|
}
|
|
}
|
|
// printf("%hd %8lx\n", short_linenumber, offset);
|
|
if (short_linenumber > (USHORT)pdes[li].lnHigh) {
|
|
break;
|
|
}
|
|
if (c) {
|
|
if (short_linenumber > last_linenumber) {
|
|
last_linenumber = short_linenumber;
|
|
// printf("%hd %8lx\n", short_linenumber, offset);
|
|
fwrite(&offset, sizeof(offset), 1, objOut);
|
|
buffer_put(linenumber_buf, (char *)&short_linenumber,
|
|
sizeof(short_linenumber));
|
|
++CoffSectionHdr[TEXT].NumberOfLinenumbers;
|
|
}
|
|
}
|
|
offset += (((cc & 0xf) + 1) * 4);
|
|
}
|
|
}
|
|
if (!CoffSectionHdr[TEXT].NumberOfLinenumbers) {
|
|
CoffSectionHdr[TEXT].PointerToLinenumbers = 0;
|
|
} else {
|
|
/* go back and write number of line number pairs in Section Header */
|
|
seek_ptr_now = ftell(objOut);
|
|
fseek(objOut, seek_ptr_cPair, SEEK_SET);
|
|
short_cPair = CoffSectionHdr[TEXT].NumberOfLinenumbers;
|
|
fwrite(&short_cPair, sizeof(short_cPair), 1, objOut);
|
|
|
|
/* now go back to the end of the file and write out the line
|
|
* numbers we have been building up and any pad needed.
|
|
*/
|
|
fseek(objOut, seek_ptr_now, SEEK_SET);
|
|
buffer_write(linenumber_buf, objOut);
|
|
if (short_cPair & 1) {
|
|
fwrite(&zero, sizeof(short_cPair), 1, objOut);
|
|
} /* if */
|
|
} /* if */
|
|
#endif // IF CV
|
|
|
|
free(lineNum);
|
|
|
|
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;
|
|
}
|
|
|
|
//
|
|
// convert symbols and types
|
|
//
|
|
|
|
if (cv) {
|
|
convert_symbols_and_types(infile, objOut);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
|
|
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 = (USHORT)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 = (USHORT)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);
|
|
|
|
//
|
|
// convert symbols and types
|
|
//
|
|
|
|
if (cv) {
|
|
PIMAGE_RELOCATION symRelocs;
|
|
|
|
//
|
|
// Convert the .debug$S relocations.
|
|
//
|
|
|
|
li = CoffSectionHdr[CVSYM].NumberOfRelocations;
|
|
if (!(symRelocs = (PIMAGE_RELOCATION)malloc(li * IMAGE_SIZEOF_RELOCATION))) {
|
|
printf("ERROR - unable to allocate symbol relocations\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
fseek(objOut, CoffSectionHdr[CVSYM].PointerToRelocations, SEEK_SET);
|
|
fread((void *)symRelocs, IMAGE_SIZEOF_RELOCATION, li, objOut);
|
|
for (j = 0; j < li; j++) {
|
|
if (symRelocs[j].SymbolTableIndex >= ((NUMEXTRASYMBOLS - 1) * 2) + NumAuxFileEntries + 1) {
|
|
symRelocs[j].SymbolTableIndex = SymbolIndex[symRelocs[j].SymbolTableIndex - (((NUMEXTRASYMBOLS - 1) * 2) + NumAuxFileEntries + 1)];
|
|
}
|
|
}
|
|
fseek(objOut, CoffSectionHdr[CVSYM].PointerToRelocations, SEEK_SET);
|
|
fwrite((void *)symRelocs, IMAGE_SIZEOF_RELOCATION, li, objOut);
|
|
}
|
|
|
|
//
|
|
// Free the string table memory.
|
|
//
|
|
|
|
free(strE);
|
|
free(strTab);
|
|
return(TRUE);
|
|
}
|
|
|
|
long btLongLong()
|
|
{
|
|
DebugBreak();
|
|
return 0;
|
|
}
|
|
|
|
long btULongLong()
|
|
{
|
|
DebugBreak();
|
|
return 0;
|
|
}
|