diff --git a/harbour/source/tools/genobj.c b/harbour/source/tools/genobj.c new file mode 100644 index 0000000000..9ad500a798 --- /dev/null +++ b/harbour/source/tools/genobj.c @@ -0,0 +1,399 @@ +/* Windows/DOS OBJs 32 bits generation support routines */ + +#include +#include +#include +#include +#include + +void CompiledFileName( int hObjFile, char * szFileName ); +void CompilerVersion( int hObjFile, char * szFileName ); +void LocalNames( int hObjFile, char * szNames[] ); +void PubDef( int hObjFile, char * szName, WORD wSegment, WORD wOffset ); +void ExternalNames( int hObjFile, char * szNames[] ); +void DefineSegment( int hObjFile, BYTE bName, BYTE bClass, WORD wLen ); +void InitSegment( int hObjFile ); +void EnumeratedData( int hObjFile, BYTE bSegment, BYTE * pData, WORD wLen, WORD wOffset ); +void Fixup( int hObjFile, BYTE bType, WORD wOffset, BYTE bFlags, BYTE bSymbol ); +void CodeSegment( int hObjFile, BYTE * initCode, WORD wInitLen, + BYTE * prgCode, WORD wPrgLen, WORD wFunctions ); +void End( int hObjFile ); + +int main( int argc, char * argv[] ) +{ + int hObjFile = open( "test.obj", O_CREAT | O_TRUNC | O_RDWR | O_BINARY ); + char * localNames[] = { "_TEXT", "CODE", "_DATA", "DATA", "DGROUP", + "_BSS", "BSS", "_INIT_", "INITDATA", 0 }; + char * externalNames[] = { "QOUT", "_ProcessSymbols", "_VirtualMachine", 0 }; + BYTE initData[] = { 0x00, 0x64, 0x00, 0x00, 0x00, 0x00 }; + BYTE initCode[] = { 0x6A, 0x02, 0x68, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, + 0x00, 0x00, 0x83, 0xC4, 0x08, 0xC3 }; + BYTE prgFunction[] = { 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x1A, 0x00, 0x00, + 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x83, 0xC4, 0x08, 0xC3 }; + BYTE symbol[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 }; + WORD w; + + CompiledFileName( hObjFile, "test.prg" ); + CompilerVersion( hObjFile, "Harbour build 21-1" ); + LocalNames( hObjFile, localNames ); + ExternalNames( hObjFile, externalNames ); + + /* code segment */ + DefineSegment( hObjFile, 2, /* "_TEXT" position + 1 into localNames */ + 3, /* "CODE" position + 1 into localNames */ + 0x3D ); /* segment length */ + + PubDef( hObjFile, "MAIN", 1, 0x10 ); /* 1 = _TEXT segment, 0x10 offset into it ); + + /* data segment */ + DefineSegment( hObjFile, 4, /* "_DATA" position + 1 into localNames */ + 5, /* "DATA" position + 1 into localNames */ + 0x48 ); /* segment length */ + InitSegment( hObjFile ); + + CodeSegment( hObjFile, initCode, sizeof( initCode ), prgFunction, + sizeof( prgFunction ), 3 ); /* 1 PRG function only */ + + /* init fixups */ + Fixup( hObjFile, 0xE4, 3, 0x54, 2 ); /* Data: symbols location */ + Fixup( hObjFile, 0xA4, 8, 0x56, 2 ); /* External: _ProcessSymbols */ + + for( w = 0; w < 3; w++ ) /* 3 PRG functions */ + { + /* prgFunction fixups */ + Fixup( hObjFile, 0xE4, sizeof( initCode ) + + ( w * sizeof( prgFunction ) ) + 1, 0x54, 2 ); /* Data: symbols location */ + + Fixup( hObjFile, 0xA4, sizeof( initCode ) + + ( w * sizeof( prgFunction ) ) + 11, 0x56, 3 ); /* External: _VirtualMachine */ + } + + EnumeratedData( hObjFile, 2, symbol, sizeof( symbol ), 0 ); /* 2 = _DATA segment */ + Fixup( hObjFile, 0xE4, 0, 0x54, 2 ); /* 0xE4 type, 0 offset, 0x54 flag, 2 = segment */ + Fixup( hObjFile, 0xE4, 5, 0x54, 1 ); /* 0xE4 type, 5 offset, 0x54 flag, 1 = segment */ + + EnumeratedData( hObjFile, 3, initData, sizeof( initData ), 0 ); /* 3 = _INIT_ segment */ + Fixup( hObjFile, 0xE4, 2, 0x54, 1 ); /* 0xE4 type, 2 offset, 0x54 flag, 1 = symbol */ + + End( hObjFile ); + + close( hObjFile ); +} + +void putbyte( BYTE b, int hObjFile ) +{ + write( hObjFile, &b, 1 ); +} + +void putword( WORD w, int hObjFile ) +{ + write( hObjFile, &w, 2 ); +} + +void CompiledFileName( int hObjFile, char * szFileName ) +{ + WORD wLen = strlen( szFileName ); + BYTE bChk = 0; /* this is a checksum the linker will check to asure OBJ integrity */ + BYTE bChar; + + putbyte( 0x80, hObjFile ); /* this tells the linker the kind of OBJ record this is */ + bChk += 0x80; + + putbyte( 1 + 1 + wLen, hObjFile ); /* now it comes the total length of this OBJ record */ + bChk += ( 1 + 1 + wLen ); + putbyte( 0, hObjFile ); + + putbyte( wLen, hObjFile ); /* szFileName length */ + bChk += wLen; + + while( bChar = * szFileName++ ) + { + putbyte( bChar, hObjFile ); /* each of the szFileName characters */ + bChk += bChar; + } + + putbyte( 256 - bChk, hObjFile ); /* a checksum that will be recalculated by the linker */ +} + +void CompilerVersion( int hObjFile, char * szVersion ) +{ + WORD wLen = strlen( szVersion ); + BYTE bChk = 0; /* this is a checksum the linker will check to asure OBJ integrity */ + BYTE bChar; + + putbyte( 0x88, hObjFile ); /* this tells the linker the kind of OBJ record this is */ + bChk += 0x88; + + putword( 3 + wLen, hObjFile ); /* now it comes the total length of this OBJ record */ + bChk += LOBYTE( 3 + wLen ); + bChk += HIBYTE( 3 + wLen ); + + putword( 0, hObjFile ); + + while( bChar = * szVersion++ ) + { + putbyte( bChar, hObjFile ); /* each of the szFileName characters */ + bChk += bChar; + } + + putbyte( 256 - bChk, hObjFile ); /* a checksum that will be recalculated by the linker */ +} + +void LocalNames( int hObjFile, char * szNames[] ) +{ + BYTE b = 0, c; + WORD wTotalLen = 0; + BYTE bChk = 0; + BYTE bChar; + + while( szNames[ b ] ) + wTotalLen += strlen( szNames[ b++ ] ); + wTotalLen += 2 + b; + + putbyte( 0x96, hObjFile ); + bChk += 0x96; + + putbyte( LOBYTE( wTotalLen ), hObjFile ); + bChk += LOBYTE( wTotalLen ); + putbyte( HIBYTE( wTotalLen ), hObjFile ); + bChk += HIBYTE( wTotalLen ); + + putbyte( 0, hObjFile ); + + b = 0; + while( szNames[ b ] ) + { + putbyte( strlen( szNames[ b ] ), hObjFile ); + bChk += strlen( szNames[ b ] ); + + c = 0; + while( szNames[ b ][ c ] ) + { + putbyte( szNames[ b ][ c ], hObjFile ); + bChk += szNames[ b ][ c++ ]; + } + b++; + } + putbyte( 256 - bChk, hObjFile ); +} + +void PubDef( int hObjFile, char * szName, WORD wSegment, WORD wOffset ) +{ + BYTE bChk = 0; + BYTE bChar; + WORD wLen = 2 + 2 + strlen( szName ) + 2 + 1; + + putbyte( 0x90, hObjFile ); + bChk += 0x90; + + putword( wLen, hObjFile ); + bChk += LOBYTE( wLen ); + bChk += HIBYTE( wLen ); + + putbyte( 0x00, hObjFile ); + putbyte( wSegment, hObjFile ); + bChk += wSegment; + + putbyte( strlen( szName ), hObjFile ); + bChk += strlen( szName ); + + while( bChar = * szName++ ) + { + putbyte( bChar, hObjFile ); + bChk += bChar; + } + + putword( wOffset, hObjFile); + bChk += LOBYTE( wOffset ); + bChk += HIBYTE( wOffset ); + putbyte( 0x00, hObjFile ); + + putbyte( 256 - bChk, hObjFile ); +} + +void ExternalNames( int hObjFile, char * szNames[] ) +{ + BYTE b = 0, c; + WORD wTotalLen = 0; + BYTE bChk = 0; + BYTE bChar; + + while( szNames[ b ] ) + wTotalLen += strlen( szNames[ b++ ] ) + 1; + wTotalLen += 2 + b - 1; + + putbyte( 0x8C, hObjFile ); + bChk += 0x8C; + + putword( wTotalLen, hObjFile ); + bChk += LOBYTE( wTotalLen ); + bChk += HIBYTE( wTotalLen ); + + b = 0; + while( szNames[ b ] ) + { + putbyte( strlen( szNames[ b ] ), hObjFile ); + bChk += strlen( szNames[ b ] ); + + c = 0; + + while( szNames[ b ][ c ] ) + { + putbyte( szNames[ b ][ c ], hObjFile ); + bChk += szNames[ b ][ c++ ]; + } + putbyte( 0, hObjFile ); + b++; + } + putbyte( 256 - bChk, hObjFile ); +} + +void DefineSegment( int hObjFile, BYTE bName, BYTE bClass, WORD wLen ) +{ + BYTE bCheckSum = 0; + + putbyte( 0x98, hObjFile ); + bCheckSum += 0x98; + putbyte( 7, hObjFile ); /* SegDef records have always this length */ + bCheckSum += 7; + putbyte( 0, hObjFile ); + + putbyte( 0xA9, hObjFile ); + bCheckSum += 0xA9; + + putword( wLen, hObjFile ); + bCheckSum += LOBYTE( wLen ); + bCheckSum += HIBYTE( wLen ); + + putbyte( bName, hObjFile ); + bCheckSum += bName; + putbyte( bClass, hObjFile ); + bCheckSum += bClass; + putbyte( 0, hObjFile ); + + putbyte( 256 - bCheckSum, hObjFile ); +} + +void InitSegment( int hObjFile ) +{ + BYTE bCheckSum = 0; + + putbyte( 0x98, hObjFile ); + bCheckSum += 0x98; + putbyte( 7, hObjFile ); /* SegDef records have always this length */ + bCheckSum += 7; + putbyte( 0, hObjFile ); + putbyte( 0x49, hObjFile ); + bCheckSum += 0x49; + + putword( 6, hObjFile ); + bCheckSum += 6; + + putbyte( 9, hObjFile ); + bCheckSum += 9; + putbyte( 10, hObjFile ); + bCheckSum += 10; + putbyte( 0, hObjFile ); + + putbyte( 256 - bCheckSum, hObjFile ); +} + +void EnumeratedData( int hObjFile, BYTE bSegment, BYTE * pData, WORD wLen, WORD wOffset ) +{ + BYTE bCheckSum = 0; + WORD w; + + putbyte( 0xA0, hObjFile ); + bCheckSum += 0xA0; + + putword( ( WORD ) ( wLen + 4 ), hObjFile ); + bCheckSum += LOBYTE( wLen + 4 ); + bCheckSum += HIBYTE( wLen + 4 ); + + putbyte( bSegment, hObjFile ); + bCheckSum += bSegment; + + putword( wOffset, hObjFile ); + bCheckSum += wOffset; + + for( w = 0; w < wLen; w++ ) + { + putbyte( * ( pData + w ), hObjFile ); + bCheckSum += * ( pData + w ); + } + + putbyte( 256 - bCheckSum, hObjFile ); +} + +void CodeSegment( int hObjFile, BYTE * initCode, WORD wInitLen, + BYTE * prgCode, WORD wPrgLen, WORD wFunctions ) +{ + BYTE bCheckSum = 0; + WORD w, y; + WORD wTotalLen = wInitLen + ( wPrgLen * wFunctions ) + 4; + + putbyte( 0xA0, hObjFile ); + bCheckSum += 0xA0; + + putword( wTotalLen, hObjFile ); + bCheckSum += LOBYTE( wTotalLen ); + bCheckSum += HIBYTE( wTotalLen ); + + putbyte( 1, hObjFile ); /* 1 = _TEXT segment */ + bCheckSum += 1; + + putword( 0, hObjFile ); /* 0 = offset */ + + for( w = 0; w < wInitLen; w++ ) + { + putbyte( * ( initCode + w ), hObjFile ); + bCheckSum += * ( initCode + w ); + } + + for( y = 0; y < wFunctions; y++ ) + { + for( w = 0; w < wPrgLen; w++ ) + { + putbyte( * ( prgCode + w ), hObjFile ); + bCheckSum += * ( prgCode + w ); + } + } + + putbyte( 256 - bCheckSum, hObjFile ); +} + +void Fixup( int hObjFile, BYTE bType, WORD wOffset, BYTE bFlags, BYTE bSymbol ) +{ + BYTE bCheckSum = 0; + + putbyte( 0x9D, hObjFile ); bCheckSum += 0x9D; + + putword( 5, hObjFile ); bCheckSum += 5; + + putbyte( bType + HIBYTE( wOffset ), hObjFile ); + bCheckSum += bType + HIBYTE( wOffset ); + + putbyte( LOBYTE( wOffset ), hObjFile ); + bCheckSum += LOBYTE( wOffset ); + + putbyte( bFlags, hObjFile ); bCheckSum += bFlags; + putbyte( bSymbol, hObjFile ); bCheckSum += bSymbol; + + putbyte( 256 - bCheckSum, hObjFile ); +} + +void End( int hObjFile ) +{ + BYTE bChk = 0; + BYTE bChar; + + putbyte( 0x8A, hObjFile ); bChk += 0x8A; + + putbyte( 0x02, hObjFile ); bChk += 0x02; + putbyte( 0x00, hObjFile ); + + putbyte( 0x00, hObjFile ); bChk += 0x00; + + putbyte( 256 - bChk, hObjFile ); +} +