示例#1
0
        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();
        }
示例#2
0
        private static Fixup ConvertFixupDefinition(
            FixupDefinition def, Dictionary <object, object> objectMap)
        {
            Fixup fixup = new Fixup();

            fixup.StartIndex = def.DataOffset;
            switch (def.Location)
            {
            case FixupLocation.LowByte:
                fixup.LocationType = FixupLocationType.LowByte;
                break;

            case FixupLocation.Offset:
            case FixupLocation.LoaderResolvedOffset:
                fixup.LocationType = FixupLocationType.Offset;
                break;

            case FixupLocation.Base:
                fixup.LocationType = FixupLocationType.Base;
                break;

            case FixupLocation.Pointer:
                fixup.LocationType = FixupLocationType.Pointer;
                break;

            default:
                throw new InvalidDataException("The fixup location is not supported.");
            }
            fixup.Mode = def.Mode;

            IAddressReferent referent;

            if (def.Target.Referent is UInt16)
            {
                referent = new PhysicalAddress((UInt16)def.Target.Referent, 0);
            }
            else
            {
                referent = (IAddressReferent)objectMap[def.Target.Referent];
            }
            fixup.Target = new SymbolicTarget
            {
                Referent     = (IAddressReferent)referent,
                Displacement = def.Target.Displacement
            };
            //f.Frame = null;
            return(fixup);
        }
示例#3
0
        private static string FormatSymbolicOperand(
            X86Codec.Instruction instruction,
            X86Codec.Operand operand,
            FixupDefinition fixup,
            ObjectModule module)
        {
            if (fixup.Target.Method == FixupTargetMethod.ExternalPlusDisplacement ||
                fixup.Target.Method == FixupTargetMethod.ExternalWithoutDisplacement)
            {
                var extIndex = fixup.Target.IndexOrFrame;
                var extName  = module.ExternalNames[extIndex - 1];
                var disp     = fixup.Target.Displacement;

                //System.Diagnostics.Debug.WriteLine(string.Format(
                //    "{0} : operand {4} refers to {1}+{2} : {3}",
                //    instruction, extName, disp, fixup.Location, operand));
                return(extName.Name);
            }
            return(null);
        }
示例#4
0
        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;
        }
        private static string FormatSymbolicOperand(
            X86Codec.Instruction instruction,
            X86Codec.Operand operand,
            FixupDefinition fixup,
            ObjectModule module)
        {
            if (fixup.Target.Method == FixupTargetMethod.ExternalPlusDisplacement ||
                fixup.Target.Method == FixupTargetMethod.ExternalWithoutDisplacement)
            {
                var extIndex = fixup.Target.IndexOrFrame;
                var extName = module.ExternalNames[extIndex - 1];
                var disp = fixup.Target.Displacement;

                //System.Diagnostics.Debug.WriteLine(string.Format(
                //    "{0} : operand {4} refers to {1}+{2} : {3}",
                //    instruction, extName, disp, fixup.Location, operand));
                return extName.Name;
            }
            return null;
        }
示例#6
0
        private void UpdateImage(ObjectModule module)
        {
#if false
            // For each segment, construct a list of LEDATA/LIDATA records.
            // These records fill data into the segment.
            // It is required that the data do not overlap, and do not
            // exceed segment boundary (here we only support 16-bit segments,
            // whose maximum size is 64KB).

            // Find the first CODE segment.
            LogicalSegment codeSegment = null;
            foreach (var seg in module.Segments)
            {
                if (seg.Class == "CODE")
                {
                    codeSegment = seg;
                    break;
                }
            }
            if (codeSegment == null)
            {
                return;
            }

            // Create a BinaryImage with the code.
            BinaryImage image = new BinaryImage(codeSegment.Image.Data, new Pointer(0, 0));

            // Disassemble the instructions literally. Note that this should
            // be improved, but we don't do that yet.
            var addr = image.BaseAddress;
            for (var i = image.StartAddress; i < image.EndAddress;)
            {
                var instruction = image.DecodeInstruction(addr);

                // An operand may have zero or one component that may be
                // fixed up. Check this.
#if false
                for (int k = 0; k < instruction.Operands.Length; k++)
                {
                    var operand = instruction.Operands[k];
                    if (operand is RelativeOperand)
                    {
                        var opr        = (RelativeOperand)operand;
                        var loc        = opr.Offset.Location;
                        int j          = i - image.StartAddress + loc.StartOffset;
                        int fixupIndex = codeSegment.DataFixups[j];
                        if (fixupIndex != 0)
                        {
                            FixupDefinition fixup = codeSegment.Fixups[fixupIndex - 1];
                            if (fixup.DataOffset != j)
                            {
                                continue;
                            }

                            var target = new SymbolicTarget(fixup, module);
                            instruction.Operands[k] = new SymbolicRelativeOperand(target);
                            System.Diagnostics.Debug.WriteLine(instruction.ToString());
                        }
                    }
                }
#endif

                image.CreatePiece(addr, addr + instruction.EncodedLength, ByteType.Code);
                image[addr].Instruction = instruction;
                addr = addr.Increment(instruction.EncodedLength);

                // TODO: we need to check more accurately.

#if false
                // Check if any bytes covered by this instruction has a fixup
                // record associated with it. Note that an instruction might
                // have multiple fixup records associated with it, such as
                // in a far call.
                for (int j = 0; j < instruction.EncodedLength; j++)
                {
                    int fixupIndex = codeSegment.DataFixups[i - image.StartAddress + j];
                    if (fixupIndex != 0)
                    {
                        FixupDefinition fixup = codeSegment.Fixups[fixupIndex - 1];
                        if (fixup.DataOffset != i - image.StartAddress + j)
                        {
                            continue;
                        }

                        if (fixup.Target.Method == FixupTargetSpecFormat.ExternalPlusDisplacement ||
                            fixup.Target.Method == FixupTargetSpecFormat.ExternalWithoutDisplacement)
                        {
                            var extIndex = fixup.Target.IndexOrFrame;
                            var extName  = module.ExternalNames[extIndex - 1];
                            var disp     = fixup.Target.Displacement;

                            System.Diagnostics.Debug.WriteLine(string.Format(
                                                                   "{0} refers to {1}+{2} : {3}",
                                                                   instruction, extName, disp, fixup.Location));
                        }
                    }
                }
#endif

                i += instruction.EncodedLength;
            }
            // ...

            // Display the code in our disassmbly window.
            if (this.ListingWindow != null)
            {
                Document doc = new Document();
                doc.Image = image;
                this.ListingWindow.Document = doc;
            }
#endif
        }
示例#7
0
        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);
        }