public FixupRecord(RecordReader reader, RecordContext context) : base(reader, context) { List <FixupThreadDefinition> threads = new List <FixupThreadDefinition>(); List <FixupDefinition> fixups = new List <FixupDefinition>(); while (!reader.IsEOF) { byte b = reader.PeekByte(); if ((b & 0x80) == 0) { FixupThreadDefinition thread = ParseThreadSubrecord(reader); threads.Add(thread); if (thread.Kind == FixupThreadKind.Target) { context.TargetThreads[thread.ThreadNumber] = thread; } else { context.FrameThreads[thread.ThreadNumber] = thread; } } else { FixupDefinition fixup = ParseFixupSubrecord(reader, context); fixups.Add(fixup); if (context.LastRecord is LEDATARecord) { var r = (LEDATARecord)context.LastRecord; fixup.DataOffset += (ushort)r.DataOffset; r.Segment.Fixups.Add(fixup); } else if (context.LastRecord is LIDATARecord) { } else if (context.LastRecord is COMDATRecord) { } else { throw new InvalidDataException("FIXUPP record must follow LEDATA, LIDATA, or COMDAT record."); } } } this.Threads = threads.ToArray(); this.Fixups = fixups.ToArray(); }
private FixupThreadDefinition ParseThreadSubrecord(RecordReader reader) { FixupThreadDefinition thread = new FixupThreadDefinition(); byte b = reader.ReadByte(); thread.Kind = ((b & 0x40) == 0) ? FixupThreadKind.Target : FixupThreadKind.Frame; thread.Method = (byte)((b >> 2) & 3); thread.ThreadNumber = (byte)(b & 3); if (thread.Method <= 2) // TBD: should be 3 for intel { thread.IndexOrFrame = reader.ReadIndex(); } thread.IsDefined = true; return(thread); }
private FixupThreadDefinition ParseThreadSubrecord(RecordReader reader) { FixupThreadDefinition thread = new FixupThreadDefinition(); byte b = reader.ReadByte(); thread.Kind = ((b & 0x40) == 0) ? FixupThreadKind.Target : FixupThreadKind.Frame; thread.Method = (byte)((b >> 2) & 3); thread.ThreadNumber = (byte)(b & 3); if (thread.Method <= 2) // TBD: should be 3 for intel thread.IndexOrFrame = reader.ReadIndex(); thread.IsDefined = true; return thread; }
private FixupDefinition ParseFixupSubrecord(RecordReader reader, RecordContext context) { FixupDefinition fixup = new FixupDefinition(); byte b1 = reader.ReadByte(); byte b2 = reader.ReadByte(); UInt16 w = (UInt16)((b1 << 8) | b2); // big endian fixup.Mode = (w & 0x4000) != 0 ? FixupMode.SegmentRelative : FixupMode.SelfRelative; fixup.Location = (FixupLocation)((w >> 10) & 0x0F); fixup.DataOffset = (UInt16)(w & 0x03FF); byte b = reader.ReadByte(); bool useFrameThread = (b & 0x80) != 0; if (useFrameThread) { int frameNumber = (b >> 4) & 0x3; FixupThreadDefinition thread = context.FrameThreads[frameNumber]; if (!thread.IsDefined) { throw new InvalidDataException("Frame thread " + frameNumber + " is not defined."); } FixupFrame spec = new FixupFrame(); spec.Method = (FixupFrameMethod)thread.Method; spec.IndexOrFrame = thread.IndexOrFrame; fixup.Frame = spec; } else { FixupFrame spec = new FixupFrame(); spec.Method = (FixupFrameMethod)((b >> 4) & 7); if ((int)spec.Method <= 3) { spec.IndexOrFrame = reader.ReadIndex(); } fixup.Frame = spec; } bool useTargetThread = (b & 0x08) != 0; if (useTargetThread) { bool hasTargetDisplacement = (b & 0x04) != 0; int targetNumber = b & 3; FixupThreadDefinition thread = context.TargetThreads[targetNumber]; if (!thread.IsDefined) { throw new InvalidDataException("Target thread " + targetNumber + " is not defined."); } FixupTargetMethod method = (FixupTargetMethod)((int)thread.Method & 3); if (hasTargetDisplacement) { method |= (FixupTargetMethod)4; } FixupTarget spec = new FixupTarget(); spec.Referent = ResolveFixupReferent(context, method, thread.IndexOrFrame); if ((int)method <= 3) { spec.Displacement = reader.ReadUInt16Or32(); } fixup.Target = spec; } else { FixupTargetMethod method = (FixupTargetMethod)(b & 7); UInt16 indexOrFrame = reader.ReadIndex(); FixupTarget spec = new FixupTarget(); spec.Referent = ResolveFixupReferent(context, method, indexOrFrame); if ((int)method <= 3) { spec.Displacement = reader.ReadUInt16Or32(); } fixup.Target = spec; } return(fixup); }