Esempio n. 1
0
// 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;
      }
   }
}