home *** CD-ROM | disk | FTP | other *** search
- /******** Listing 3 ************************* OX.C ********
- * ox.c -- Object Explorer,
- * Author: Thomas E. Siering, 1991. See Lisitng 1 for
- * copyright notice.
- * Compiler: Microsoft C 6.0, Turbo C++ 1.0
- *
- * Compile time switches: none
- *
- * Links with: svc.c and apps.c
- **************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <io.h>
- #include "ox.h"
-
-
- #define NEAR 0x62
- #define FAR 0x61
-
- #define THREADMAX 4
- #define MAXLINELENGTH 16
-
- extern FILE *AnalysisFH;
-
- PRIVATE char *ObjBase;
- PRIVATE FILE *ObjFH;
- PRIVATE FIXUPTHREAD ThreadTable[THREADMAX * 2]; /* for Target AND Frame */
-
-
- PRIVATE LNODE ListLNAMES;
- PRIVATE LNODE ListSEGDEF;
- PRIVATE LNODE ListGRPDEF;
- PRIVATE LNODE ListEXTDEF;
-
-
- PRIVATE int GetExplicitFixupp(unsigned char *RecordP);
- PRIVATE int GetFixupThread(unsigned char *RecordP);
- PRIVATE LNODE *GetThreadFixupMethod(unsigned int method, unsigned int d,
- char *RecordP);
- PRIVATE void GetFixupLocation(unsigned int loc, char *RecordP);
- PRIVATE int IteratedDataBlock(unsigned char *RecordP);
- PRIVATE void InstThreadTable(void);
- PRIVATE void PutThread(FIXUPTHREAD NewThread);
- PRIVATE FIXUPTHREAD *GetThread(unsigned char ThreadID, char ThreadType,
- char *RecordP);
- PRIVATE int GetFixDatField(unsigned char *RecordP);
- PRIVATE char GetVarLengthIdx(char *RecordP, int *Index);
-
-
- /*------------------------------------------------------------
- * InstObjExp -- Instantiate the Object Explorer
- *-----------------------------------------------------------*/
- PUBLIC void InstObjExp(char ObjFN[], char **ws, long *ObjSize)
- {
- if ((ObjFH = fopen(ObjFN, "rb")) == NULL) {
- fprintf(stderr, "Could Not Open File %s\n", ObjFN);
- exit(-1);
- }
-
- if ((*ObjSize = filelength(fileno(ObjFH))) == -1) {
- fprintf(stderr, "Error in File Size Determination\n");
- exit(-1);
- }
-
- if ((ObjBase = *ws = malloc((int) *ObjSize)) == NULL) {
- fprintf(stderr, "Work Space Allocation Failed. Aborting\n");
- exit(-1);
- }
-
- if (fread(*ws, sizeof(char), (int) *ObjSize, ObjFH) !=
- (unsigned int) *ObjSize) {
- fprintf(stderr, "Read of OBJ Failed. Aborting\n");
- exit(-1);
- }
- fclose(ObjFH);
-
- if ((char) **ws != (char) THEADR && (char) **ws != (char) LHEADR) {
- fprintf(stderr, "Invalid OBJ file. Aborting\n");
- exit(-1);
- }
-
- InstList(&ListLNAMES); /* initialize symbol lists */
- InstList(&ListSEGDEF);
- InstList(&ListGRPDEF);
- InstList(&ListEXTDEF);
- InstThreadTable();
- }
-
-
- /*===============================================
- * 1. OMF comment records:
- * THEADR 0x80
- * COMENT 0x88
- * MODEND 0x8A
- *===============================================*/
-
- /*--------------------------------------------------------
- * DoTHEADR -- Translator Header record (T-module)
- * NOTE: MUST always appear as the first record in OBJ module
- *--------------------------------------------------------*/
- PUBLIC void DoTHEADR(unsigned char *RecordP)
- {
- char *ModuleName;
-
- ModuleName = MakeASCIIZ(RecordP);
-
- Output(Message, AnalysisFH, "Module Name:\n %s\n", ModuleName);
- free(ModuleName);
- }
- /*--------------------------------------------------------
- * DoCOMENT -- Comment record
- * Within the given Comment Classes anything can be put here.
- * As a result, COMENT records are popular for OMF extensions.
- *-------------------------------------------------------*/
- PUBLIC void DoCOMENT(unsigned char *RecordP, int RecordLength)
- {
- bool NoPurge, NoList;
- unsigned char CommentClass;
- char *Comment;
- char Processor[6];
- int PrintLength;
- int Offset;
-
- NoPurge = *RecordP & (char) 0x80;
- NoList = *RecordP++ & (char) 0x40;
- Output(Message, AnalysisFH, " No Purge : %s\n",
- NoPurge ? "ON" : "OFF");
- Output(Message, AnalysisFH, " No List : %s\n",
- NoList ? "ON" : "OFF");
- CommentClass = *RecordP++;
- RecordLength -= 2; /* past NoPurge/NoList and CommentClass */
-
- /* Note: This string is NOT preceded by "length" byte */
- Comment = malloc(RecordLength + 1);
- Comment[RecordLength] = '\0';
- strncpy(Comment, RecordP, RecordLength);
-
- /* Comment Class */
- Output(Message, AnalysisFH, " Comment Class : %02X\n",
- CommentClass & 0x00FF);
-
- switch(CommentClass) {
- case 0x00 :
- Output(Message, AnalysisFH,
- " Language Translator: %s\n", Comment);
- break;
- case 0x01 :
- Output(Message, AnalysisFH,
- " Copyright : %s\n", Comment);
- break;
- case 0x81 : /* obsolete: 9F comment class should be used */
- Output(Message, AnalysisFH,
- " Library Specifier : %s\n", Comment);
- break;
- case 0x9C :
- Output(Message, AnalysisFH,
- " DOS Version : %d\n", *(int *) RecordP);
- break;
- case 0x9D :
- if (Comment[0] == '0')
- strcpy(Processor, "8086");
- else {
- strcpy(Processor, "80086");
- Processor[2] = Comment[0];
- }
- Output(Message, AnalysisFH, " Target Processor : %s\n",
- Processor);
- Output(Message, AnalysisFH, " Memory Model : %c\n",
- Comment[1]);
- break;
- case 0x9E : /* Sets LINK's DOSSEG */
- Output(Message, AnalysisFH, " Force Segment Order: %s\n",
- Comment);
- break;
- case 0x9F :
- Output(Message, AnalysisFH, " Library Specifier : %s\n",
- Comment);
- break;
- case 0xA0 : /* used for IMPDEF with Windows, OS/2 */
- Output(Message, AnalysisFH, " MS-Reserved Field : ");
- switch (*RecordP) {
- case 1 :
- Output(Message, AnalysisFH, "IMPDEF\n");
- break;
- case 2:
- Output(Message, AnalysisFH, "EXPDEF\n");
- break;
- case 3:
- Output(Message, AnalysisFH, "INCDEF\n");
- break;
- case 4:
- Output(Message, AnalysisFH,
- "Protected Memory Lib. (386)\n");
- break;
- default:
- Output(Warning, AnalysisFH, "Unknown Comment Record\n");
- break;
- }
- break;
- case 0xA1 : /* meaning that obsolete TYPDEF/EXTDEF pairs */
- /* not used but COMDEF instead */
- Output(Message, AnalysisFH, " Microsoft Extension: %s\n",
- Comment);
- break;
- case 0xA2 :
- Output(Message, AnalysisFH, " Start of Link Pass 2\n");
- break;
- case 0xA3 :
- Output(Message, AnalysisFH, " LIBMOD record\n");
- break;
- case 0xA4 :
- Output(Message, AnalysisFH, " EXESTR record\n");
- break;
- case 0xA5 :
- Output(Message, AnalysisFH, " QC # 1 record\n");
- break;
- case 0xA6 :
- Output(Message, AnalysisFH, " INCERR record\n");
- break;
- case 0xA7 :
- Output(Message, AnalysisFH, " NOPAD record\n");
- break;
- case 0xA8 :
- Output(Message, AnalysisFH, " WKEXT record\n");
- break;
- default:
- if (CommentClass >= 0xC0)
- Output(Message, AnalysisFH, " User-Defined Comm. :\n");
- else
- /* This is foul play, or some future non-compliant extension */
- Output(Message, AnalysisFH, " Proprietary Comm. :\n");
-
- /* Hex dump the comment (string printing it isn't safe!) */
- Offset = GetRecordRelPos(RecordP);
- while (RecordLength > 0) {
- PrintLength = (RecordLength > MAXLINELENGTH) ?
- MAXLINELENGTH : RecordLength;
- PrintObjDumpLine(RecordP, AnalysisFH, Offset, PrintLength);
- RecordLength -= PrintLength;
- Offset += PrintLength;
- RecordP += PrintLength;
- }
- break;
- }
- free(Comment);
- }
-
- /*--------------------------------------------------------------
- * DoMODEND -- Module End record
- * Indicates end of module, whether it's the main routine in a
- * program, and, optionally, program entry point.
- * NOTE: MUST always appear as the last record in OBJ module
- *-------------------------------------------------------------*/
- PUBLIC void DoMODEND(unsigned char *RecordP)
- {
- bool IsMain;
- bool HasEntryPoint;
- bool IsRelocatableEP;
-
- /* The top two bytes are relevant: byte 7 - is it main module, */
- /* byte 6 - is starting address supplied */
-
- /* The following check will fail on Quick C generated OBJ modules.
- This non-standard behavior is undocumented (but harmless). */
- #ifdef QUICKC_MYSTERY
- if ((*RecordP & (char) 0x3E) != 0)
- Output(Warning, AnalysisFH,
- "Unrecognizable Module End Attribute Record\n");
- #endif
-
- IsMain = *RecordP & (char) 0x80;
- HasEntryPoint = *RecordP & (char) 0x40;
- IsRelocatableEP = *RecordP++ & (char) 0x01;
-
- Output(Message, AnalysisFH, " %s / %s\n",
- (IsMain) ? "Main module" : "Non-Main Module",
- (HasEntryPoint) ? "Entry Point" : "No Entry Point");
- if (HasEntryPoint)
- Output(Message, AnalysisFH, " %s\n",
- (IsRelocatableEP) ?
- "Relocatable Entry Point" : "Absolute Entry Point");
-
- if (HasEntryPoint) /* Specified starting address */
- GetFixDatField(RecordP);
- }
-
- /*===============================================
- * 2. Symbol lists:
- * LNAMES 0x96
- * EXTDEF 0x8C
- * PUBDEF 0x90
- *===============================================*/
-
- /*-------------------------------------------------------------
- * DoLNAMES -- Names List record
- * List of names which will be referenced by subsequent SEGDEF
- * and GRPDEF records in this module, using 1-based index.
- * MS LINK limit is 255 logical names/module.
- *-------------------------------------------------------------*/
- PUBLIC void DoLNAMES(unsigned char *RecordP, int RecordLength)
- {
- char *LName;
-
- while (RecordLength > 0) {
- LName = MakeASCIIZ(RecordP);
- Output(Message, AnalysisFH, " %s\n",
- *RecordP != '\0' ? LName : "(NULLNAME)");
-
- ListLNAMES = AddListNode(ListLNAMES, LName);
-
- RecordLength -= ((int) *RecordP + 1);
- RecordP += ((int) *RecordP + 1);
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "LNAMES record not recognized. Terminating\n");
- }
-
-
- /*---------------------------------------------------------------
- * DoEXTDEF -- External Name Definitions record
- * List of symbolic external references (symbols defined in other
- * OBJ modules). MS LINK limit is 1023 external names.
- *---------------------------------------------------------------*/
- PUBLIC void DoEXTDEF(unsigned char *RecordP, int RecordLength)
- {
- char *ExtName;
- int TypeIndex;
- char IndexSize;
-
- while (RecordLength > 0) {
- ExtName = MakeASCIIZ(RecordP);
- ListEXTDEF = AddListNode(ListEXTDEF, ExtName); /*EXTDEF name list*/
- Output(Message, AnalysisFH, "\n External Symbol : %s \n",
- ExtName);
- RecordLength -= ((int) *RecordP + 1);
- RecordP += ((int) *RecordP + 1);
-
- /* Type index is reference to a TYPDEF record (if > 0)
- EXTDEF/TYPDEF method is mostly obsolete, except for
- communal variables. It is replaced by COMDEF records. */
-
- IndexSize = GetVarLengthIdx(RecordP, &TypeIndex);
- Output(Message, AnalysisFH, " Type Index : %u\n",
- TypeIndex);
- RecordLength -= IndexSize;
- RecordP += IndexSize;
- }
- if (RecordLength)
- Output(Error, AnalysisFH,
- "EXTDEF record not recognized. Terminating\n");
- }
-
- /*------------------------------------------------------------
- * DoPUBDEF -- Public Name Definitions record
- * This record contains the public names used to resolve the
- * externals at link time.
- *-------------------------------------------------------------*/
- PUBLIC void DoPUBDEF(unsigned char *RecordP, int RecordLength)
- {
- char *PubName;
- int GroupIndex;
- int SegmentIndex;
- LNODE *ListNodeP = NULL;
- int TypeIndex;
- char IndexSize;
-
- /* If a group is associated with this PUBDEF record, Group Index
- indexes to the appropriate GRPDEF, otherwise it's 0 */
- IndexSize = GetVarLengthIdx(RecordP, &GroupIndex);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- if (GroupIndex != 0)
- ListNodeP = GetListNode(ListLNAMES, GroupIndex);
- Output(Message, AnalysisFH, " Group Name Index : %u -- %s\n",
- GroupIndex, ListNodeP != NULL ? ListNodeP->InfoP : "NO GROUP");
-
- /* The Segment Index indexes to previous SEGDEF records to associate a
- segment with this PUBDEF. If Segment Index = 0, Group Index = 0. */
- ListNodeP = NULL;
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- if (SegmentIndex != 0)
- ListNodeP = GetListNode(ListSEGDEF, SegmentIndex);
- Output(Message, AnalysisFH, " Segment Name Index : %u -- %s\n",
- SegmentIndex, ListNodeP != NULL ? ListNodeP->InfoP : "NO SEGMENT");
-
- /* If both Group and Segment Index are 0, a Frame Number follows
- which indexes the frame containing the Public symbols */
- if (GroupIndex == 0 && SegmentIndex == 0) {
- Output(Message, AnalysisFH, " Frame Number = %Xx\n",
- *(int *) RecordP);
- RecordP += 2;
- RecordLength -= 2;
- }
-
- while (RecordLength > 0) {
- /* PUBLIC's name */
- PubName = MakeASCIIZ(RecordP);
- Output(Message, AnalysisFH, "\n Public Name : %s \n",
- PubName);
- free(PubName);
- RecordLength -= ((int) *RecordP + 1);
- RecordP += ((int) *RecordP + 1);
-
- /* PUBLIC's offset relative to segment, group, or frame (supra) */
- Output(Message, AnalysisFH,
- " Public Offset : %Xx\n", *(int *) RecordP);
- RecordP += 2;
- RecordLength -= 2;
-
- /* Type Index refers to preceding TYPDEF record. 0 = no data type */
- IndexSize = GetVarLengthIdx(RecordP, &TypeIndex);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- Output(Message, AnalysisFH, " Type Index : %u\n",
- TypeIndex);
- }
- if (RecordLength)
- Output(Error, AnalysisFH,
- "PUBDEF record not recognized. Terminating\n");
- }
-
- /*====================================
- * 3. Memory layout info:
- * SEGDEF 0x98
- * GRPDEF 0x9A
- * COMDEF 0xB0
- * TYPDEF 0x8E
- *====================================*/
-
- /*---------------------------------------------------------
- * DoSEGDEF -- Segment Definition record
- * Describes a logical segment: name, length, alignment,
- * combination with other logical segments.
- * MS LINK limit: 255 SEGDEF records per OBJ modules
- *---------------------------------------------------------*/
- PUBLIC void DoSEGDEF(unsigned char *RecordP)
- {
- char *SegmentName;
- long SegmentLength;
- int SegmentIndex;
- int ClassIndex;
- int OverlayIndex;
- char IndexSize;
-
- struct ACBP {
- unsigned Page : 1;
- unsigned Big : 1;
- unsigned Combine : 3;
- unsigned Align : 3;
- } ACBP;
-
- ACBP = *(struct ACBP *) RecordP++;
-
- /* Segment Alignment at runtime */
- switch(ACBP.Align) {
- case 0 :
- Output(Message, AnalysisFH, " ABSOLUTE Segment\n");
- break;
- case 1 :
- Output(Message, AnalysisFH, " Relocatable/Align : BYTE\n");
- break;
- case 2 :
- Output(Message, AnalysisFH, " Relocatable/Align : WORD\n");
- break;
- case 3 :
- Output(Message, AnalysisFH, " Relocatable/Align : PARA\n");
- break;
- case 4 :
- Output(Message, AnalysisFH, " Relocatable/Align : PAGE\n");
- break;
- default:
- Output(Warning, AnalysisFH,
- "Unrecognizable Segment Alignment Record\n");
- break;
- }
-
- /* Segment Combination that linker may perform to segments of same name.
- Can either concatenate segments, or overlap them. Note: Absolute
- segments (Align = 0) canNOT be combined (Combine = 0). */
- switch(ACBP.Combine) {
- case 0 :
- Output(Message, AnalysisFH, " PRIVATE Segment\n");
- break;
- case 2 :
- case 4 :
- case 7:
- Output(Message, AnalysisFH,
- " Combine Type : PUBLIC/Concatenate\n");
- break;
- case 5 :
- Output(Message, AnalysisFH,
- " Combine Type : STACK/Concatenate\n");
- break;
- case 6 :
- Output(Message, AnalysisFH,
- " Combine Type : COMMON/Overlap\n");
- break;
- default:
- Output(Warning, AnalysisFH,
- "Unrecognizable Segment Combination Record\n");
- break;
- }
-
- /* Big Field determines if segment size is EXACTLY 64k */
- if (ACBP.Big == 1)
- Output(Message, AnalysisFH, " Segment Size = 64Kb\n");
- else
- Output(Message, AnalysisFH, " Segment Size < 64Kb\n");
-
- /* Page field is unused in DOS and should be 0. */
- if (ACBP.Page != 0)
- Output(Message, AnalysisFH,
- "Unrecognized Page value in SEGDEF record\n");
-
-
- /* Frame Number and Offset fields are present only for absolute segments.
- Taken together, they provide the segment's starting address: */
- if (ACBP.Align == 0) { /* absolute segment specific fields */
- Output(Message, AnalysisFH,
- " Absolute Segment : Frame Number = %Xx\n",
- *(int *) RecordP);
- RecordP += 2;
- Output(Message, AnalysisFH,
- " Absolute Segment : Segment Offset = %Xx\n",
- *(unsigned char *) RecordP++);
- }
-
- /* Segment Length in bytes */
- SegmentLength = (long) *(unsigned int *) RecordP;
- /* if Big field was 1 (i.e., 64K segment),
- Segment Length field is set to 0 */
- if (ACBP.Big == 1 && SegmentLength == 0)
- SegmentLength = 65536; /* 64k */
- Output(Message, AnalysisFH, " Segment Length : %ld\n",
- SegmentLength);
- RecordP += 2;
-
- /* The Segment Name Index, Class Name Index, and Overlay Name Index
- provide the names from previous LNAMES records. */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- SegmentName = GetListNode(ListLNAMES, SegmentIndex)->InfoP;
- Output(Message, AnalysisFH, " Segment Name Index : %d -- %s\n",
- SegmentIndex, SegmentName);
- ListSEGDEF = AddListNode(ListSEGDEF, SegmentName);
- RecordP += IndexSize;
-
- /* The Class Name Index gives the segment's class(e.g. CODE, or STACK),
- so that linker can combine segments of equal class name. */
- IndexSize = GetVarLengthIdx(RecordP, &ClassIndex);
- Output(Message, AnalysisFH, " Class Name Index : %d -- %s\n",
- ClassIndex, GetListNode(ListLNAMES, ClassIndex)->InfoP);
- RecordP += IndexSize;
-
- /* The Overlay Name Index identifies a segment with a runtime overlay.
- MS LINK ignores it, using command-line parameters to LINK instead. */
- IndexSize = GetVarLengthIdx(RecordP, &OverlayIndex);
- Output(Message, AnalysisFH, " Overlay Name Index : %d -- %s\n",
- OverlayIndex, GetListNode(ListLNAMES, OverlayIndex)->InfoP);
- }
- /*---------------------------------------------------------
- * DoGRPDEF -- Group Definition record
- * Defines a group of segments to reside together within
- * 64K frame at runtime.
- * MS LINK limit: 21 GRPDEF records per OBJ module.
- *--------------------------------------------------------*/
- PUBLIC void DoGRPDEF(unsigned char *RecordP, int RecordLength)
- {
- char *GroupName;
- int GroupIndex;
- int SegmentIndex;
- char IndexSize;
-
- /* Get the Group Name via Group Name Index */
- IndexSize = GetVarLengthIdx(RecordP, &GroupIndex);
- GroupName = GetListNode(ListLNAMES, GroupIndex)->InfoP;
- Output(Message, AnalysisFH, " Group Name Index : %d -- %s\n",
- GroupIndex, GroupName);
- /* Group Name may be later referenced in FIXUPP */
- ListGRPDEF = AddListNode(ListGRPDEF, GroupName);
- RecordLength -= IndexSize;
- RecordP += IndexSize;
-
- /* Remainder of record is made up of Group Component Descriptors: */
- while (RecordLength > 0) {
- /* First byte is always FF, indicating following
- of Segment Name Index */
- ++RecordP;
- RecordLength--;
-
- /* Segment Name Index relative to previous SEGDEF record */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- Output(Message, AnalysisFH,
- " Segment Name Index : %d -- %s\n",
- SegmentIndex, GetListNode(ListSEGDEF,
- SegmentIndex)->InfoP);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "GRPDEF record not recognized. Terminating\n");
- }
-
- /*-------------------------------------------------------------------
- * DoCOMDEF -- Common Name Definitions record
- * MS extension declaring a (list of) communal variable(s).
- * Being an extension COMDEF records must be indicated by COMENT
- * record of Comment Class A1.
- *------------------------------------------------------------------*/
- PUBLIC void DoCOMDEF(unsigned char *RecordP, int RecordLength)
- {
- char *ComName;
- long CommunalSize;
- int TypeIndex;
- unsigned char DataSegmentType;
- unsigned int NameLength;
- char IndexSize;
- int i;
-
- while (RecordLength > 0) {
- /* Communal Name */
- ComName = MakeASCIIZ(RecordP);
- ListEXTDEF = AddListNode(ListEXTDEF, ComName); /*EXTDEF name list*/
- Output(Message, AnalysisFH,
- "\n Communal Symbol : %s \n", ComName);
- NameLength = *RecordP + 1; /* name + length byte */
- RecordLength -= NameLength;
- RecordP += NameLength;
-
- /* Type Index indexes to TYPDEF, or is 0 if no associated type */
- IndexSize = GetVarLengthIdx(RecordP, &TypeIndex);
- Output(Message, AnalysisFH,
- " Type Index : %X\n", (int) TypeIndex);
- RecordLength -= IndexSize;
- RecordP += IndexSize;
-
- /* Data Segment Type: is Communal Variable NEAR or FAR ? */
- DataSegmentType = *RecordP++;
- --RecordLength;
- if (DataSegmentType == FAR)
- Output(Message, AnalysisFH,
- " Default Data Segm. : NO/FAR\n");
- else if (DataSegmentType == NEAR)
- Output(Message, AnalysisFH,
- " Default Data Segm. : YES/NEAR\n");
- else
- Output(Error, AnalysisFH,
- "COMDEF record not recognized. Terminating\n");
-
- /* Communal Length field: amount of memory to allocate for communal.
- Depending on Data Segment Type, the following bytes are
- interpreted: NEAR: variable size in bytes, FAR: number
- of elements, element size.
-
- NEAR: Variable Size field ,
- FAR: Number of Elements/Element Size */
-
- for (i = 0; i < (DataSegmentType == NEAR ? 1 : 2); i++) {
- /* The size field(s) is/are determined from first byte: */
- switch (*RecordP) {
- /* 2 byte unsigned length field follows, i.e. < 64k */
- case 0x81 :
- ++RecordP;
- CommunalSize = (long) *(unsigned int *) RecordP;
- RecordLength -= 3;
- RecordP += 2;
- break;
- /* 3 byte unsigned length field: < 16M */
- case 0x84 :
- ++RecordP;
- CommunalSize = *(long *) RecordP & 0x00FFFFFF;
- RecordLength -= 4;
- RecordP += 3;
- break;
- /* 4 byte signed length field: < 2G */
- case 0x88 :
- ++RecordP;
- CommunalSize = *(long *) RecordP;
- RecordLength -= 5;
- RecordP += 4;
- break;
- /* char field of value < 80h is actual communal length:
- < 128b */
- default : /* 1 byte signed length field: < 128b */
- CommunalSize = (long) *RecordP++;
- --RecordLength;
- break;
- }
- if (DataSegmentType == NEAR)
- Output(Message, AnalysisFH,
- " Communal Length : %ld bytes\n",
- CommunalSize);
- else if (i == 0)
- Output(Message, AnalysisFH,
- " Communal Elements : %ld bytes\n",
- CommunalSize);
- else
- Output(Message, AnalysisFH,
- " Element Size : %ld bytes\n",
- CommunalSize);
- }
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "COMDEF record not recognized. Terminating\n");
- }
-
- /*------------------------------------------------------------
- * DoTYPDEF -- Type Definition record
- * Type information about PUBDEF or EXTDEF name
- *------------------------------------------------------------*/
- PUBLIC void DoTYPDEF()
- {
- Output(Warning, AnalysisFH, "TYPDEF not implemented\n");
- }
-
- /*===============================================
- * 4. Code and data
- * LEDATA 0xA0
- * LIDATA 0xA2
- *==============================================*/
-
- /*-------------------------------------------------------------
- * DoLEDATA -- Logical Enumerated Data record
- * Contiguous binary data, executable code or program data.
- * Typically, preceded by SEGDEF and followed by FIXUPP record.
- * Max. length for data field is 1024 bytes.
- *-------------------------------------------------------------*/
- PUBLIC void DoLEDATA(unsigned char *RecordP, int RecordLength)
- {
- int Offset;
- int PrintLength;
- int SegmentIndex;
- char IndexSize;
-
- /* Segment Index field refers to SEGDEF record, indicating
- segment into which to place this binary code/data. */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- Output(Message, AnalysisFH, " Segment Name Index : %d -- %s\n",
- SegmentIndex, GetListNode(ListSEGDEF, SegmentIndex)->InfoP);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
-
- /* Enumerated Data Offset: relative to Segment Index's segment base */
- Output(Message, AnalysisFH, " Enum. Data Offset : %Xx\n",
- *(int *) RecordP);
- RecordP += 2;
- RecordLength -= 2;
-
- Output(Message, AnalysisFH, "\nEnumerated Data:\n\n");
-
- Offset = 0; /* offset of data relative to its record */
- while (RecordLength > 0) {
- PrintLength = (RecordLength > MAXLINELENGTH) ?
- MAXLINELENGTH : RecordLength;
- PrintObjDumpLine(RecordP, AnalysisFH, Offset, PrintLength);
- RecordLength -= PrintLength;
- Offset += PrintLength;
- RecordP += PrintLength;
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "LEDATA record not recognized. Terminating\n");
- }
-
- /*--------------------------------------------------------------
- * DoLIDATA -- Logical Iterated Data record
- * Binary code/data represented in repeating patterns (iterations).
- * Typically, preceded by SEGDEF and followed by FIXUPP record.
- * Max. size of iterated data block field is 512 bytes.
- *--------------------------------------------------------------*/
- PUBLIC void DoLIDATA(unsigned char *RecordP, int RecordLength)
- {
- int BytesDone;
- int SegmentIndex;
- char IndexSize;
-
- /* Segment Index field refers to SEGDEF record, indicating segment
- ** into which to place this binary code/data. */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- Output(Message, AnalysisFH, " Segment Name Index : %d -- %s\n",
- SegmentIndex, GetListNode(ListSEGDEF, SegmentIndex)->InfoP);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
-
- /* Iterated Data Offset: relative to Segment Index's segment base */
- Output(Message, AnalysisFH, " Iter. Data Offset : %Xx\n",
- *(int *) RecordP);
- RecordP += 2;
- RecordLength -= 2;
-
- while (RecordLength > 0) {
- /* Iterated Data Blocks are defined recursively */
- BytesDone = IteratedDataBlock(RecordP);
- RecordLength -= BytesDone;
- RecordP += BytesDone;
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "LIDATA record not recognized. Terminating\n");
- }
-
- /*-----------------------------------------------------------------
- * IteratedDataBlock -- Analyzes one Logical Iterated Data record
- * This is separated out because of its recursive nature.
- *----------------------------------------------------------------*/
- PRIVATE int IteratedDataBlock(unsigned char *RecordP)
- {
- int RepeatCount;
- int BlockCount;
- int BytesDone;
- int Offset;
- int DataBlockLength;
- int PrintLength;
- int RecordLength;
-
- /* Repeat Count is number of times to repeat Content field */
- RepeatCount = *(int *) RecordP;
- Output(Message, AnalysisFH, "\n Repeat Count : %d\n",
- RepeatCount);
- RecordP += 2;
-
- /* Block Count is number of iterated data blocks in Content field.
- ** If 0, Content field contains data only. */
- BlockCount = *(int *) RecordP;
- Output(Message, AnalysisFH, " Block Count : %d\n", BlockCount);
- RecordP += 2;
- /* So far: Block Count and Repeat Count words */
- BytesDone = 4;
-
- /* Content field: if Block Count != 0, nested iterated Data Blocks */
- if (BlockCount > 0) {
- FOREVER {
- RecordLength = IteratedDataBlock(RecordP);
- RecordP += RecordLength;
- BytesDone += RecordLength;
- if (--BlockCount == 0)
- return (BytesDone);
- }
- }
-
- /* With zero Block Count, this is data: length byte, then data bytes */
- DataBlockLength = *(char *) RecordP++;
- Output(Message, AnalysisFH, " Data Block Length : %d\n",
- DataBlockLength);
-
- /* We've traversed: Data and its Length byte */
- BytesDone += DataBlockLength + 1;
-
- /* Print the raw data */
- Offset = 0;
- while (DataBlockLength > 0) {
- PrintLength = (DataBlockLength > MAXLINELENGTH) ?
- MAXLINELENGTH : DataBlockLength;
- PrintObjDumpLine(RecordP, AnalysisFH, Offset, PrintLength);
- DataBlockLength -= PrintLength;
- Offset += PrintLength;
- RecordP += PrintLength;
- }
- return (BytesDone);
- }
-
- /*===============================================
- * 5. Address binding/relocation:
- * FIXUPP 0x9C
- *==============================================*/
-
- /*----------------------------------------------------------------
- * DoFIXUPP -- Relocation Fixup records: Used to resolve addresses
- * whose values cannot be determined prior to link time.
- * LOCATION: address in OBJ module to be fixed up
- * TARGET: address to which fixup refers (to be computed)
- * FRAME: relative to which the address is computed
- *----------------------------------------------------------------*/
-
- PUBLIC void DoFIXUPP(unsigned char *RecordP, int RecordLength)
- {
- bool IsFixup;
- int FixupLength;
-
- while (RecordLength > 0) {
- /* High bit determines difference between Thread field
- and Fixup field */
- IsFixup = (bool) (*(char *) RecordP & 0x80);
- if (IsFixup)
- FixupLength = GetExplicitFixupp(RecordP);
- else
- FixupLength = GetFixupThread(RecordP);
- RecordP += FixupLength;
- RecordLength -= FixupLength;
- }
- if (RecordLength)
- Output(Error, AnalysisFH,
- "FIXUPP record not recognized. Terminating\n");
- }
-
- /*-----------------------------------------------------------
- * GetFixupThread -- Thread FIXUPP records
- * Provides common info for reference by succeeding
- * explicit fixup or thread fields in same or subsequent
- * FIXUPP records.
- *-----------------------------------------------------------*/
- PRIVATE int GetFixupThread(unsigned char *RecordP)
- {
- struct ThrData {
- unsigned ThreadNumber : 2;
- unsigned Method : 3;
- unsigned NotUsed : 1;
- unsigned D : 1;
- unsigned FixupType : 1; /* 0 = Thread, 1 = Explicit FIXUPP */
- } ThreadData;
-
- FIXUPTHREAD Thread;
- LNODE *ThreadName;
- int RecLength = 1; /* min. record length in bytes */
- int IndexSize;
-
- Output(Message, AnalysisFH, "\n%04X -- FIXUPP Thread:\n",
- GetRecordRelPos(RecordP));
-
- /* Interpret the thread record */
- ThreadData = *(struct ThrData *) RecordP++;
- /* Thread will be known by an index 0-3 (for each, Frame and Target) */
- Thread.ID = (char) ThreadData.ThreadNumber;
-
- /* D = 0 : Target Thread, identifies the fixup target */
- /* D = 1 : Frame Thread, provides info about 64k frame */
- Thread.Type = (char) (ThreadData.D == 0 ? 'T' : 'F');
-
- /* Methods: T0 - T7 (for D = 0), and F0 - F5 (for D = 1) */
- Thread.Method = (char) ThreadData.Method;
-
-
- /* Index Field appears always, except for frame threads
- using methods F3/4/5 */
- if (!(Thread.Type == 'F' && Thread.Method > 2))
- IndexSize = GetVarLengthIdx(RecordP, &Thread.ListIndex);
- else
- Thread.ListIndex = -1; /* none */
-
- Output(Message, AnalysisFH, "\n %s Thread # : %d\n",
- Thread.Type == 'F' ? "Frame" : "Target",
- (int) Thread.ID);
-
- /* The Method field (combined with D) gives linker method
- to identify T/F. DefList is applicable xxxDEF list to r
- efer to via Index */
- Thread.DefList = GetThreadFixupMethod((int) ThreadData.Method,
- (int) ThreadData.D, RecordP - 1);
-
- if (Thread.ListIndex > 0) {
- ThreadName = GetListNode(*(Thread.DefList),
- Thread.ListIndex)->InfoP;
- Output(Message, AnalysisFH, " %s Thread Index: %u -- %s\n",
- Thread.Type == 'F' ? "Frame" : "Target",
- Thread.ListIndex, ThreadName);
- RecLength += IndexSize; /* Record Length in bytes */
- }
-
- PutThread(Thread);
- return (RecLength); /* Record Length in bytes */
- }
-
- /*------------------------------------------------------------------
- * GetThreadFixupMethod -- Interpret Method / D fields of Thread FIXUPP rec
- *------------------------------------------------------------------*/
- PRIVATE LNODE *GetThreadFixupMethod(unsigned int Method, unsigned int D,
- char *RecordP)
- {
- if (D) { /* Frame Thread */
- Output(Message, AnalysisFH, " Frame ID Method : F%u -- ",
- Method);
- switch(Method) {
- case 0 :
- Output(Message, AnalysisFH,
- "SEGDEF index: Highest #ered Frame cont. segm\n");
- return (&ListSEGDEF);
- case 1 :
- Output(Message, AnalysisFH, "GRPDEF index\n");
- return (&ListGRPDEF);
- case 2 :
- Output(Message, AnalysisFH, "EXTDEF index\n");
- return (&ListEXTDEF);
- case 3 :
- Output(Message, AnalysisFH, "Frame Number\n");
- return (NULL);
- case 4 :
- Output(Message, AnalysisFH,
- "Highest #ered Frame cont. segm of fixup loc\n");
- return (NULL);
- case 5 :
- Output(Message, AnalysisFH, "Same as target frame\n");
- return (NULL);
- default:
- Output(Warning, AnalysisFH,
- "\n%04X -- FIXUPP: Bad Frame Thread Method Value\n",
- GetRecordRelPos(RecordP));
- return (NULL);
- }
- }
- else { /* Target Thread */
- Output(Message, AnalysisFH, " Target ID Method : T%u -- ",
- Method);
- switch (Method) {
- case 0 :
- Output(Message, AnalysisFH, "SEGDEF index and offset\n");
- return (&ListSEGDEF);
- case 1 :
- Output(Message, AnalysisFH, "GRPDEF index and offset\n");
- return (&ListGRPDEF);
- case 2 :
- Output(Message, AnalysisFH, "EXTDEF index and offset\n");
- return (&ListEXTDEF);
- case 3 :
- Output(Message, AnalysisFH, "Frame Number and offset\n");
- return (NULL);
- case 4 :
- Output(Message, AnalysisFH, "SEGDEF index only.");
- Output(Message, AnalysisFH, "Target at Segment beginning\n");
- return (&ListSEGDEF);
- case 5 :
- Output(Message, AnalysisFH, "GRPDEF index only\n");
- return (&ListGRPDEF);
- case 6 :
- Output(Message, AnalysisFH, "EXTDEF index only\n");
- return (&ListEXTDEF);
- case 7 :
- Output(Message, AnalysisFH, "Frame Number only\n");
- return (NULL);
- default:
- Output(Warning, AnalysisFH,
- "\n%04X -- FIXUPP: Bad Target Thread Method Value\n",
- GetRecordRelPos(RecordP));
- return (NULL);
- }
- }
- }
-
- /*---------------------------------------------------------------
- * GetThread -- Retrieve a thread from the thread data table
- * If no valid thread, return NULL.
- *--------------------------------------------------------------*/
- PRIVATE FIXUPTHREAD *GetThread(unsigned char ThreadID, char ThreadType,
- char *RecordP)
- {
- int Idx;
-
- if (ThreadID <= 3) {
- /* In table, we store Frame threads first then Target threads */
- Idx = (int) (ThreadType == 'F' ? ThreadID :
- ThreadID + (char) THREADMAX);
- if (ThreadTable[Idx].ListIndex != -1)
- return (&ThreadTable[Idx]);
- }
-
- /* If we get here, we're in trouble! */
- Output(Warning, AnalysisFH,
- "\n%04X -- FIXUPP: Bad Thread Reference\n",
- GetRecordRelPos(RecordP));
- return (NULL);
- }
-
- /*--------------------------------------------------------
- * PutThread -- Save a thread in the thread data table
- *-------------------------------------------------------*/
- PRIVATE void PutThread(FIXUPTHREAD NewThread)
- {
- int Idx;
-
- /* In table, we store Frame threads first then Target threads */
- Idx = (int) (NewThread.Type == 'F' ? NewThread.ID :
- NewThread.ID + (char) THREADMAX);
- ThreadTable[Idx] = NewThread;
- }
-
- /*-------------------------------------------------------
- * InstThreadTable -- Instantiate the Thread Table
- *------------------------------------------------------*/
- PRIVATE void InstThreadTable()
- {
- int i;
-
- for (i = 0; i < THREADMAX * 2; i++)
- ThreadTable[i].ID = -1;
- }
-
- /*-------------------------------------------------------
- * GetExplicitFixupp -- Explicit FIXUPP records
- *-------------------------------------------------------*/
- PRIVATE int GetExplicitFixupp(unsigned char *RecordP)
- {
- int RecordLength;
-
- union {
- struct {
- unsigned DataRecOffset : 10; /* LOCATION position in LxDATA rec */
- unsigned Loc : 3; /* location type to be fixed up */
- unsigned S : 1; /* unused, should be 0 */
- unsigned Mode : 1; /* segment-relative vs self-relative */
- unsigned FixupType : 1; /* explicit or thread */
- } Word;
- char Byte[2];
- } Locat;
-
- Output(Message, AnalysisFH, "\n%04X -- Explicit FIXUPP :\n",
- GetRecordRelPos(RecordP));
-
- Locat.Byte[1] = *RecordP++; /* read bit fields */
- Locat.Byte[0] = *RecordP++; /* in reverse order */
-
- /* Mode bit */
- Output(Message, AnalysisFH, "\n Fixup Relativity : %s \n",
- Locat.Word.Mode ? "SEGMENT" : "SELF");
-
- GetFixupLocation((int) Locat.Word.Loc, RecordP - 2); /* Loc field */
-
- /* Data Rec Offset in previous LxDATA */
- Output(Message, AnalysisFH, " Location Offset : %Xx\n",
- (int) Locat.Word.DataRecOffset);
-
- RecordLength = GetFixDatField(RecordP);
-
- return (RecordLength);
- }
-
- /*----------------------------------------------------------
- * GetFixupLocation -- Determine location to be fixed up.
- * (Explicit FIXUPP record)
- *----------------------------------------------------------*/
- PRIVATE void GetFixupLocation(unsigned int Loc, char *RecordP)
- {
- Output(Message, AnalysisFH, " Fixup Location : ");
- switch (Loc) {
- case 0 :
- Output(Message, AnalysisFH, "Low-Order Byte\n");
- break;
- case 5 : /* Loc = 5 is treated as Loc - 1 by linker */
- Output(Message, AnalysisFH, "Loader-resolved Offset/");
- case 1 :
- Output(Message, AnalysisFH, "Ptr-Offset (16-bit)\n");
- break;
- case 2 :
- Output(Message, AnalysisFH, "Ptr-Segment (16-bit)\n");
- break;
- case 3 :
- Output(Message, AnalysisFH, "FAR Pointer (32-bit)\n");
- break;
- case 4 :
- Output(Message, AnalysisFH, "High-Order Byte\n");
- break;
- default:
- Output(Warning, AnalysisFH,
- "\n%04X -- FIXUPP: Bad Loc field %04X\n",
- GetRecordRelPos(RecordP), Loc);
- break;
- }
- }
-
- /*-----------------------------------------------------------------
- * GetFixDatField -- Interpret the FixDat field in explicit FIXUPP
- * record and its equivalent, the EndDat in MODEND.
- *----------------------------------------------------------------*/
- PRIVATE int GetFixDatField(unsigned char *RecordP)
- {
- struct fd {
- unsigned Targt : 2; /* data record offset */
- unsigned P : 1;
- unsigned T : 1;
- unsigned Frame : 3;
- unsigned F : 1;
- } FixDat;
-
- LNODE *FrameList;
- LNODE *TargetList;
- FIXUPTHREAD *ThreadP;
- int FrameMethod;
- int TargetMethod;
- int FrameDatum;
- int TargetDatum;
- int DatumSize;
- int RecordLength;
- /* F/Frame fields */
- FixDat = *(struct fd *) RecordP++;
- if (FixDat.F) { /* F = 1 => frame in previous thread */
- Output(Message, AnalysisFH, " Frame Reference : THREAD\n");
- ThreadP = GetThread((char) FixDat.Frame, 'F', RecordP - 1);
- Output(Message, AnalysisFH,
- " Frame ID Method : Thread # %u -- %s\n",
- (int) FixDat.Frame,
- GetListNode(*ThreadP->DefList, ThreadP->ListIndex)->InfoP);
- }
- else { /* F = 0 => explicit frame */
- Output(Message, AnalysisFH, " Frame Reference : EXPLICIT\n");
- FrameMethod = (int) FixDat.Frame;
- FrameList = GetThreadFixupMethod(FrameMethod, 1, RecordP - 1);
- }
-
- /* T field */
- if (FixDat.T) /* T = 1 => target in prev. thread */
- Output(Message, AnalysisFH, " Target Reference : THREAD\n");
- else /* T = 0 => target explicit in FUP */
- Output(Message, AnalysisFH, " Target Reference : EXPLICIT\n");
-
- /* P field */
- if (FixDat.P) /* P = 1 => target spec 2ndary way */
- Output(Message, AnalysisFH,
- " Target Specific. : SECONDARY -- IDX / NO OFFSET\n");
- else
- Output(Message, AnalysisFH,
- " Target Specific. : PRIMARY -- IDX / OFFSET\n");
-
- /* Target field */
- if (FixDat.T) { /* T = 1 => thread target spec */
- ThreadP = GetThread((char) FixDat.Targt, 'T', RecordP - 1);
- Output(Message, AnalysisFH,
- " Target ID Method : Thread # %u -- %s\n",
- (int) FixDat.Targt,
- GetListNode(*ThreadP->DefList, ThreadP->ListIndex)->InfoP);
- }
- else { /* T = 0 => explicit target spec */
- /* Target = method of identifying target */
- TargetMethod = (int) ((FixDat.P) ? (FixDat.Targt + 4) : FixDat.Targt);
- TargetList = GetThreadFixupMethod(TargetMethod, 0, RecordP - 1);
- }
- RecordLength = 3;
-
- /* Frame Datum */
- if (FixDat.F == 0 && FrameMethod < 4) {
- DatumSize = GetVarLengthIdx(RecordP, &FrameDatum);
- Output(Message, AnalysisFH,
- " Frame Datum : %d -- %s\n",
- FrameDatum, (FrameList != NULL) ?
- GetListNode(*FrameList, FrameDatum)->InfoP : " ");
- RecordP += DatumSize;
- RecordLength += DatumSize;
- }
-
- /* Target Datum */
- if (FixDat.T == 0) {
- DatumSize = GetVarLengthIdx(RecordP, &TargetDatum);
- Output(Message, AnalysisFH,
- " Target Datum : %d -- %s\n",
- TargetDatum, (TargetList != NULL) ?
- GetListNode(*TargetList, TargetDatum)->InfoP : " ");
- RecordP += DatumSize;
- RecordLength += DatumSize;
- }
-
- /* Target Displacement */
- if (FixDat.P == 0) {
- Output(Message, AnalysisFH, " Target Displacement: %Xx\n",
- *(int *) RecordP);
- RecordP += 2;
- RecordLength += 2;
- }
- return (RecordLength);
- }
-
- /*===========================
- * 6. Debugging info:
- * LINNUM 0x94
- *==========================*/
-
- /*----------------------------------------------------
- * DoLINNUM -- Line Numbers record: relates source code line
- * numbers to OBJ code addresses.
- *---------------------------------------------------*/
- PUBLIC void DoLINNUM(unsigned char *RecordP, int RecordLength)
- {
- int GroupIndex;
- int SegmentIndex;
- char IndexSize;
- LNODE *ListNodeP;
- int LineNumber;
- unsigned int LineNumberOffset;
-
- /* The Line Number Base (Group Index/Segment Index) describes the
- segment to which the line number refers.
- Group containing this code (always 0 for MS translators) */
- if ((GroupIndex = (int) *RecordP++) != 0) {
- ListNodeP = GetListNode(ListLNAMES, GroupIndex);
- Output(Message, AnalysisFH, " Group Name Index : %u -- %s\n",
- GroupIndex, (ListNodeP != NULL) ? ListNodeP->InfoP : " ");
- }
- else
- Output(Message, AnalysisFH,
- " Group Name Index : %u -- NO GROUP\n", GroupIndex);
- RecordLength--;
-
- /* Segment Index refers to a previous SEGDEF record. */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- if (SegmentIndex != 0) {
- ListNodeP = GetListNode(ListSEGDEF, SegmentIndex);
- Output(Message, AnalysisFH, " Segment Name Index : %u -- %s\n",
- SegmentIndex, (ListNodeP != NULL) ? ListNodeP->InfoP : " ");
- }
- else
- Output(Message, AnalysisFH,
- " Segment Name Index : %u -- NO SEGMENT\n",
- SegmentIndex);
-
- while (RecordLength > 0) {
- /* Line Number: source code line number (0 <= n <= 32,767) */
- LineNumber = *(int *) RecordP;
- Output(Message, AnalysisFH, " Line Number : %d\n",
- LineNumber);
- RecordP += 2;
-
- /* Line Number Offset: offset into code (in segment specified
- by Line Number Base) to which line number refers */
- LineNumberOffset = *(unsigned int *) RecordP;
- Output(Message, AnalysisFH, " Line # Offset : %Xx\n\n",
- LineNumberOffset);
- RecordP += 2;
- RecordLength -= 4;
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "LINNUM record not recognized. Terminating\n");
- }
-
- /*================================
- * 7. Obsolete record types
- * BLKDEF 0x7A
- * BLKEND 0x7C
- * LHEADR 0x82
- *===============================*/
-
- /*----------------------------------------
- * DoBLKDEF -- Block Definition record
- *----------------------------------------*/
- PUBLIC void DoBLKDEF()
- {
- Output(Warning, AnalysisFH, "BLKDEF not implemented\n");
- }
-
- /*----------------------------------------
- * DoBLKEND -- Block End Record
- *----------------------------------------*/
- PUBLIC void DoBLKEND()
- {
- Output(Message, AnalysisFH, "\nBLOCK END\n");
- }
-
- /*----------------------------------------
- * DoLHEADR -- Translator Header Record (L-module)
- * NOTE: MUST always appear as the first record in OBJ module
- *---------------------------------------*/
- PUBLIC void DoLHEADR(unsigned char *RecordP)
- {
- char *ModuleName;
-
- ModuleName = MakeASCIIZ(RecordP);
-
- Output(Message, AnalysisFH, "Module Name:\n %s\n", ModuleName);
- free(ModuleName);
- }
-
- /*===============================================
- * 8. Microsoft extensions
- * BAKPAT 0xB2 (0xB3, for 32-bit offsets)
- * LEXTDEF 0xB4
- * LPUBDEF 0xB6 (0xB7, for 32-bit offsets)
- * LCOMDEF 0xB8
- *===============================================*/
-
- /*-------------------------------------------------------
- ** DoBAKPAT -- Back Patch record: Supplementary to FIXUPP records,
- * BAKPAT handles back patches to locations that a regular fix-up
- * record cannot easily deal with, e.g. forward references in
- * one-pass compilers. This record is specific to Quick C.
- *-------------------------------------------------------*/
- PUBLIC void DoBAKPAT(unsigned char *RecordP, int RecordLength)
- {
- int SegmentIndex;
- int IndexSize;
- LNODE *ListNodeP;
- char LocTyp;
- unsigned int Offset;
- int PatchValue;
-
- /* Segment Index refers to a previous SEGDEF record. */
- IndexSize = GetVarLengthIdx(RecordP, &SegmentIndex);
- RecordP += IndexSize;
- RecordLength -= IndexSize;
- ListNodeP = GetListNode(ListSEGDEF, SegmentIndex);
- Output(Message, AnalysisFH, " Segment Name Index : %u -- %s\n",
- SegmentIndex, (ListNodeP != NULL) ? ListNodeP->InfoP : " ");
-
- /* LocTyp indicates type of location to patch: 0 -> low-byte,
- ** 1 -> word offset, 32 -> double-word offset */
- LocTyp = *RecordP++;
- RecordLength--;
- Output(Message, AnalysisFH, " Location Type : %d\n",
- LocTyp);
-
- /* The remainder of the record is a repeatable pair of Offset into
- segment to patch, and value to add to patched Location */
- while (RecordLength > 0) {
- Offset = *(unsigned int *) RecordP;
- Output(Message, AnalysisFH, " Offset : %04Xx\n",
- Offset);
- RecordP += 2;
-
- PatchValue = *(int *) RecordP;
- Output(Message, AnalysisFH, " Patch Value : %04Xx\n\n",
- PatchValue);
- RecordP += 2;
- RecordLength -= 4;
- }
-
- if (RecordLength)
- Output(Error, AnalysisFH,
- "BAKPAT record not recognized. Terminating\n");
- }
-
- #define OTRANGE 32
- #define LOREC 0x7A
- #define HIREC 0xB8
-
- PRIVATE char ObjTypes[OTRANGE][OMFNAMELENGTH] = {
- { "BLKDEF" }, /* 0x7A */
- { "BLKEND" }, /* 0x7C */
- { "" }, /* 0x7E */
- { "THEADR" }, /* 0x80 */
- { "" }, /* 0x82 */
- { "" }, /* 0x84 */
- { "" }, /* 0x86 */
- { "COMENT" }, /* 0x88 */
- { "MODEND" }, /* 0x8A */
- { "EXTDEF" }, /* 0x8C */
- { "TYPDEF" }, /* 0x8E */
- { "PUBDEF" }, /* 0x90 */
- { "" }, /* 0x92 */
- { "LINNUM" }, /* 0x94 */
- { "LNAMES" }, /* 0x96 */
- { "SEGDEF" }, /* 0x98 */
- { "GRPDEF" }, /* 0x9A */
- { "FIXUPP" }, /* 0x9C */
- { "" }, /* 0x9E */
- { "LEDATA" }, /* 0xA0 */
- { "LIDATA" }, /* 0xA2 */
- { "" }, /* 0xA4 */
- { "" }, /* 0xA6 */
- { "" }, /* 0xA8 */
- { "" }, /* 0xAA */
- { "" }, /* 0xAC */
- { "" }, /* 0xAE */
- { "COMDEF" }, /* 0xB0 */
- { "BAKPAT" }, /* 0xB2 */
- { "LEXTDEF" }, /* 0xB4 */
- { "LPUBDEF" }, /* 0xB6 */
- { "LCOMDEF" } /* 0xB8 */
- };
-
- /*---------------------------------------------------------------------
- * GetObjRecordName -- Supply an OBJ record type number, receive the
- * record-type name. NOTE: this table has been tailored to a subset
- * of Intel records plus extensions as used by Microsoft.
- *--------------------------------------------------------------------*/
- PUBLIC RC GetObjRecordName(unsigned char ObjRecType, char ObjRecName[])
- {
- if (ObjRecType < LOREC || ObjRecType > HIREC) {
- ObjRecName[0] = '\0';
- return (!OK);
- }
-
- strcpy(ObjRecName, ObjTypes[(ObjRecType - LOREC) / 2]);
- if (ObjRecName[0] == '\0')
- return (!OK);
- return (OK);
- }
-
- /*-------------------------------------------------------------------
- * GetRecordRelPos -- Get an OBJ record's relative position in the
- * OBJ module. Note : The return type is unsigned int, assuming a
- * a maximum OBJ module size of 64K.
- *------------------------------------------------------------------*/
- PUBLIC unsigned int GetRecordRelPos(char *CurrentPosition)
- {
- return (CurrentPosition - ObjBase);
- }
-
- /*-------------------------------------------------------------------
- * GetVarLengthIdx -- Indexes are variable length: 0-7Fh is fit into
- * one byte; 80-7FFF (the max index), is fit into two bytes.
- * A two byte field is indicated by the high bit being set,
- * and is non-INTEL byte order.
- * Example: 8283 equals 283h.
- * Returns: Length of index in bytes
- *-------------------------------------------------------------------*/
- PRIVATE char GetVarLengthIdx(char *RecordP, int *Index)
- {
- #define BYTE 1
- #define WORD 2
-
- union {
- char Byte[2];
- int Word;
- } Int;
-
- if (*RecordP & 0x80) { /* we're dealing with TWO bytes */
- /* Clear high bit, and make this index's high byte */
- Int.Byte[1] = *RecordP++ & (char) 0x7F;
- Int.Byte[0] = *RecordP;
- *Index = Int.Word;
- return (WORD);
- }
- else { /* simple byte 0 - 7Fh */
- *Index = (int) *RecordP;
- return (BYTE);
- }
- }