[comp.os.msdos.programmer] Forcing Microsoft LINK to Overlay Data: Boy, is it ugly!

cramer@optilink.UUCP (Clayton Cramer) (08/18/90)

I asked a few days back for advice on tricking the Microsoft linker
into overlaying data.  Here is the solution worked out in house.

The last SEGDEF record in the .OBJ file containing the data you
wish overlaid with the code has a segment class of FAR_DATA.
Look in the LNAMES record (near the beginning of the .OBJ file),
and find the corresponding number for the CODE segment class.
Then alter the segment class in the last SEGDEF record to be
CODE, not FAR_DATA.

Sounds difficult?  Well, every .OBJ file we have examined produced
by Microsoft C 6.0 uses the same basic header, with the same number
of SEGDEF records, and the same order for the LNAMES record.  So
I wrote a little program that does the editing needed -- all you
have to do it add it to your MAKE file immediately after the .OBJ
file is produced.

The READOBJ program I am using to interpret the .OBJ files whines
that the checksums don't match in the SEGDEF we edit, but the
linker doesn't object (other than giving warning messages), and this
DOES work to put data and code into overlays.

Note, of course, that any data altered that is in an overlay will
be lost when the overlay is swapped out, so you have to be a little
careful when using this technique.  (The resulting bugs can be
VERY unobvious).

----cut here------------------------------------------------------------
/* This program edits the FAR_DATA SEGDEF records of Microsoft C .obj files so
   that the FAR_DATA segment is grouped with the _TEXT segment, allowing the
   FAR_DATA contents to be overlaid with the code.  Doing it in this manner is
   crude and disgusting, rather akin to shaking someone's hand by stuffing
   your hand the entire length of their alimentary canal to get to their 
   hand.  Unfortunately, the Microsoft Linker is so brain-damaged, there's
   no other way to do it. 
	   
   To do this, we make the assumption that everything that goes in the 
   FAR_DATA segment is constant data.  We also assume that the sequence of
   Microsoft OMF records in an .obj file is roughly constant. */

#include <stdio.h>
#include "std.h"

main (Argc, Argv)

int			Argc;
char*		Argv[];

	{
	FILE*	ObjFile;
	int		SegdefRecordCount = 0;
	int		RecLength;
	bool	FileEdited;
	int		Ch;
	
	/* Search through the file until we find the first SEGDEF record. */
	ObjFile = fopen(Argv[Argc-1], "r+b");
	if(ObjFile)
		{
		FileEdited = FALSE;
		while(!FileEdited && !feof(ObjFile) && !ferror(ObjFile))
			{
			switch(Ch = fgetc(ObjFile))
				{
				case 0x98:
					SegdefRecordCount++;
					if(SegdefRecordCount == 7)
						{
						/* We have found the SEGDEF we want to alter. */
						fseek(ObjFile, (long)6, SEEK_CUR);
						fputc(0x4, ObjFile);
						FileEdited = TRUE;
						}
					else
						{
						/* Not yet where we want to be. Skip past this 
						   record. */
						fread(&RecLength, sizeof(int), 1, ObjFile);
						fseek(ObjFile, RecLength, SEEK_CUR);
						}
					break;
				
				case EOF:
					break;
					
				default:
					fread(&RecLength, sizeof(int), 1, ObjFile);
					fseek(ObjFile, RecLength, SEEK_CUR);
					break;
				}
			}
		}
	fclose(ObjFile);
	}
----cut here------------------------------------------------------------
-- 
Clayton E. Cramer {pyramid,pixar,tekbspa}!optilink!cramer
"The tree of liberty must be watered periodically with the blood of tyrants 
and patriots alike.  It is its natural manure." -- Thomas Jefferson
You must be kidding!  No company would hold opinions like mine!