// MakeSegmentList void COMF2ASM::MakeSegmentList() { // Make Sections list in Disasm int32 SegNum; // Segment number int32 Segment; // Segment number in OMF record uint32 RecNum; // OMF record number uint32 LastDataRecord; // OMF record number of last LEDATA record uint32 RecOffset; // Segment offset of LEDATA, LIDATA record uint32 RecSize; // Data size of LEDATA, LIDATA record uint32 LastDataRecordSize; // Last RecSize uint32 LastOffset; // Last RecOffset int8 * LastDataRecordPointer; // Point to last raw data uint32 BufOffset; // Offset of segment into SegmentData buffer CMemoryBuffer TempBuf; // Temporary buffer for building raw data // Loop through segments for (SegNum = 1; SegNum <= NumSegments; SegNum++) { // Get size uint32 SegmentSize = Segments[SegNum].Size; if (SegmentSize == 0) continue; // Empty segment // Allocate temporary data buffer and reset it TempBuf.SetSize(SegmentSize + 16); int FillByte = 0; // Byte to fill memory with if (Segments[SegNum].Type == 1) { // Code segment. Fill any unused bytes with NOP opcode = 0x90 FillByte = 0x90; } memset(TempBuf.Buf(), FillByte, SegmentSize + 16);// Reset to all 0 or NOP LastDataRecord = 0; LastDataRecordSize = 0; LastDataRecordPointer = 0; LastOffset = 0; int comdatsSoFar = 0; // Search for LEDATA, LIDATA and FIXUPP records for this segment for (RecNum = 0; RecNum < NumRecords; RecNum++) { if (Records[RecNum].Type2 == OMF_LEDATA) { // LEDATA record Records[RecNum].Index = 3; // Initialize record reading Segment = Records[RecNum].GetIndex();// Read segment number if ((Segment & 0xC000) == 0x4000) { // Refers to Borland communal section Segment = (Segment & ~0x4000) + FirstComDatSection - 1; } if (Segment != SegNum) continue; // Does not refer to this segment RecOffset = Records[RecNum].GetNumeric();// Read offset of this record RecSize = Records[RecNum].End - Records[RecNum].Index; // Calculate size of data LastDataRecord = RecNum; // Save for later FIXUPP that refers to this record if (RecOffset < LastOffset + LastDataRecordSize && LastOffset < RecOffset + RecSize) { // Overlapping data records if (RecOffset + 8 < LastOffset + LastDataRecordSize || Segments[SegNum].Type != 1) { // Overlapping data by more than 7 bytes or not executable code err.submit(1207); } else { // Possibly backpatched code err.submit(1208); // Warning err.ClearError(1208); // Report only once } } LastDataRecordSize = RecSize; LastDataRecordPointer = Records[RecNum].buffer + Records[RecNum].FileOffset + Records[RecNum].Index; LastOffset = RecOffset; // Save offset for subsequent FIXUPP records // Check if data within segment if (RecOffset + RecSize > SegmentSize) { err.submit(2309, GetSegmentName(Segment)); continue; } // Put raw data into temporary buffer memcpy(TempBuf.Buf() + RecOffset, LastDataRecordPointer, RecSize); } // Finished with LEDATA record if (Records[RecNum].Type2 == OMF_LIDATA) { // LIDATA record Records[RecNum].Index = 3; // Initialize record reading Segment = Records[RecNum].GetIndex(); if (Segment != SegNum) continue; // Does not refer to this segment LastDataRecord = RecNum; // Save for later FIXUPP that refers to this record RecOffset = Records[RecNum].GetNumeric();// Read offset if (RecOffset > SegmentSize) { err.submit(2310); continue; // Error: outside bounds } // Unpack LIDATA blocks recursively RecSize = Records[RecNum].UnpackLIDATABlock(TempBuf.Buf() + RecOffset, SegmentSize - RecOffset); if (RecOffset < LastOffset + LastDataRecordSize && LastOffset < RecOffset + RecSize) { // Overlapping data records err.submit(1207); // Warning } LastDataRecordSize = RecSize; // Save data size LastOffset = RecOffset; // Save offset for subsequent FIXUPP records } // Finished with LIDATA record if (Records[RecNum].Type2 == OMF_COMDAT) { // COMDAT record. Records[RecNum].Index = 3; // Initialize record reading uint16 flags = Records[RecNum].GetByte(); if ((flags&1)==0) { // not a continuation ++comdatsSoFar; LastDataRecord = RecNum; // Save for later FIXUPP that refers to this record } Segment = FirstComDatSection + comdatsSoFar-1; if (SegNum != Segment) continue; uint16 attribs = Records[RecNum].GetByte(); Records[RecNum].GetByte(); // align (ignore) RecOffset = Records[RecNum].GetNumeric(); Records[RecNum].GetIndex(); // type (ignore) if ((attribs&0xF)==0) { Records[RecNum].GetIndex(); // public base uint16 publicSegment = Records[RecNum].GetIndex(); if (publicSegment==0) Records[RecNum].GetIndex(); // public frame (ignore) } Records[RecNum].GetIndex(); // public name (ignore) RecSize = Records[RecNum].End - Records[RecNum].Index; // Calculate size of data LastDataRecord = RecNum; // Save for later FIXUPP that refers to this record LastDataRecordSize = RecSize; LastDataRecordPointer = Records[RecNum].buffer + Records[RecNum].Index+Records[RecNum].FileOffset; LastOffset = RecOffset; // Put raw data into temporary buffer memcpy(TempBuf.Buf() + RecOffset, LastDataRecordPointer, RecSize); } // Finished with COMDAT record if (Records[RecNum].Type2 == OMF_FIXUPP) { // FIXUPP record if (Segment != SegNum) continue; // Does not refer to this segment Records[RecNum].Index = 3; if (Records[LastDataRecord].Type2 == OMF_LEDATA) { // FIXUPP for last LEDATA record // Make relocation records MakeRelocations(Segment, RecNum, LastOffset, LastDataRecordSize, (uint8*)TempBuf.Buf()); } else if (Records[RecNum].Index < Records[RecNum].End) { // Non-empty FIXUPP record does not refer to LEDATA record if (Records[LastDataRecord].Type2 == OMF_COMDAT) { // FIXUPP for last COMDAT record // Make relocation records MakeRelocations(Segment, RecNum, LastOffset, LastDataRecordSize, (uint8*)TempBuf.Buf()); } else if (Records[LastDataRecord].Type2 == OMF_LIDATA) { err.submit(2311); // Error: Relocation of iterated data not supported } else { err.submit(2312); // Does not refer to data record } } } } // End of loop to search for LEDATA, LIDATA and FIXUPP records for this segment // Transfer raw data from TempBuf to SegmentData buffer BufOffset = SegmentData.Push(TempBuf.Buf(), SegmentSize); // Remember offset into SegmentData Segments[SegNum].BufOffset = BufOffset; } // End of first loop through segments // We must put all segments into SegmentData buffer before we assign pointers to // the raw data because otherwise the SegmentData buffer might me reallocated // when it grows and the pointers become invalid. This is the reasons why we // have two loops through the segments here. // Second loop through segments int totalcodesize=0; for (SegNum = 1; SegNum <= NumSegments; SegNum++) { // Pointer to merged raw data uint8 * RawDatap = (uint8*)SegmentData.Buf() + Segments[SegNum].BufOffset; // Size of raw data uint32 InitSize = (Segments[SegNum].Type == 3) ? 0 : Segments[SegNum].Size; // Define segment const char * SegmentName = NameBuffer.Buf() + Segments[SegNum].NameO; Disasm.AddSection(RawDatap, InitSize, Segments[SegNum].Size, Segments[SegNum].Offset, Segments[SegNum].Type, Segments[SegNum].Align, Segments[SegNum].WordSize, SegmentName); if (Segments[SegNum].Type == 1 || Segments[SegNum].Type == 0x1001) { totalcodesize += Segments[SegNum].Size; } } }