Ejemplo n.º 1
0
        /// <summary>
        /// Marks a contiguous range of bytes as the given type, and marks
        /// the first byte in this range as a lead byte. The address range
        /// must be on the same segment.
        /// </summary>
        public void UpdateByteType(Address startAddress, Address endAddress, ByteType type)
        {
            if (startAddress.Segment != endAddress.Segment)
            {
                throw new ArgumentException("startAddress and endAddress must be on the same segment.");
            }

            ArraySegment <ByteAttribute> attrs = attributes.GetAttributes(
                startAddress, endAddress.Offset - startAddress.Offset);

            for (int i = 0; i < attrs.Count; i++)
            {
                if (attrs.Array[attrs.Offset + i].Type != ByteType.Unknown)
                {
                    // Undo
                    for (int j = i - 1; j >= 0; j--)
                    {
                        attrs.Array[attrs.Offset + j] = ByteAttribute.Empty;
                    }
                    throw new ArgumentException("[start, end) overlaps with analyzed bytes.");
                }

                ByteAttribute attr = new ByteAttribute {
                    Type       = type,
                    IsLeadByte = (i == 0),
                };
                attrs.Array[attrs.Offset + i] = attr;
            }

            OnBytesAnalyzed(startAddress, endAddress);
        }
Ejemplo n.º 2
0
 protected override void GenerateProcedures()
 {
     // Enumerate the defined names, and assign names to the procedures.
     foreach (ObjectModule module in library.Modules)
     {
         foreach (DefinedSymbol symbol in module.DefinedNames)
         {
             if (symbol.BaseSegment != null)
             {
                 Address address = new Address(symbol.BaseSegment.Id, (int)symbol.Offset);
                 if (image.IsAddressValid(address))
                 {
                     ByteAttribute b = image[address];
                     if (b.Type == ByteType.Code && b.IsLeadByte)
                     {
                         Procedure proc = Procedures.Find(address);
                         if (proc == null)
                         {
                             proc = CreateProcedure(address);
                             Procedures.Add(proc);
                         }
                         proc.Name = symbol.Name;
                     }
                 }
             }
         }
     }
 }
Ejemplo n.º 3
0
        public void SetAt(Address address, ByteAttribute attribute)
        {
            if (!image.IsAddressValid(address))
            {
                throw new ArgumentOutOfRangeException("address");
            }

            for (int i = attrs.Count; i < image.Segments.Count; i++)
            {
                attrs.Add(new ByteAttribute[image.Segments[i].OffsetBounds.End]);
            }

            attrs[address.Segment][address.Offset] = attribute;
        }
Ejemplo n.º 4
0
        public void SetAt(Address address, ByteAttribute attribute)
        {
            if (!image.IsAddressValid(address))
                throw new ArgumentOutOfRangeException("address");

            for (int i = attrs.Count; i < image.Segments.Count; i++)
            {
                attrs.Add(new ByteAttribute[image.Segments[i].OffsetBounds.End]);
            }

            attrs[address.Segment][address.Offset] = attribute;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Marks a contiguous range of bytes as the given type, and marks
        /// the first byte in this range as a lead byte. The address range
        /// must be on the same segment.
        /// </summary>
        public void UpdateByteType(Address startAddress, Address endAddress, ByteType type)
        {
            if (startAddress.Segment != endAddress.Segment)
                throw new ArgumentException("startAddress and endAddress must be on the same segment.");

            ArraySegment<ByteAttribute> attrs = attributes.GetAttributes(
                startAddress, endAddress.Offset - startAddress.Offset);

            for (int i = 0; i < attrs.Count; i++)
            {
                if (attrs.Array[attrs.Offset + i].Type != ByteType.Unknown)
                {
                    // Undo
                    for (int j = i - 1; j >= 0; j--)
                    {
                        attrs.Array[attrs.Offset + j] = ByteAttribute.Empty;
                    }
                    throw new ArgumentException("[start, end) overlaps with analyzed bytes.");
                }

                ByteAttribute attr = new ByteAttribute {
                    Type = type,
                    IsLeadByte = (i == 0),
                };
                attrs.Array[attrs.Offset + i] = attr;
            }

            OnBytesAnalyzed(startAddress, endAddress);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Gets the image associated with the segment specified by its id.
        /// </summary>
        /// <param name="segmentId">Id of the segment to resolve.</param>
        /// <returns>The image associated with the given segment, or null if
        /// the segment id is invalid.</returns>
        //protected abstract ImageChunk ResolveSegment(int segmentId);

        #region Flow Analysis Methods

        /// <summary>
        /// Analyzes a contiguous sequence of instructions that form a basic
        /// block. A basic block terminates as soon as any of the following
        /// conditions is true:
        /// - An analysis error occurs
        /// - An block terminating instructions: RET, RETF, IRET, HLT.
        /// - A b/c/j instruction: Jcc, JMP, JMPF, LOOPcc.
        /// </summary>
        /// <param name="start">Address to begin analysis.</param>
        /// <param name="xrefs">Collection to add xrefs to.</param>
        /// <returns>
        /// A new BasicBlock if one was created during the analysis.
        /// If no new BasicBlocks are created, or if an existing block was
        /// split into two, returns null.
        /// </returns>
        // TODO: should be roll-back the entire basic block if we
        // encounters an error on our way? maybe not.
        protected virtual BasicBlock AnalyzeBasicBlock(XRef start, ICollection <XRef> xrefs)
        {
            Address ip = start.Target; // instruction pointer

            if (!image.IsAddressValid(ip))
            {
                AddError(ip, ErrorCode.OutOfImage,
                         "XRef target is outside of the image (referred from {0})",
                         start.Source);
                return(null);
            }

            // Check if the entry address is already analyzed.
            ByteAttribute b = image[ip];

            if (b.Type != ByteType.Unknown)
            {
                // Fail if we ran into data or padding while expecting code.
                if (b.Type != ByteType.Code)
                {
                    AddError(ip, ErrorCode.RanIntoData,
                             "XRef target is in the middle of data (referred from {0})",
                             start.Source);
                    return(null);
                }

                // Now the byte was previously analyzed as code. We must have
                // already created a basic block that contains this byte.
                BasicBlock block = BasicBlocks.Find(ip);
                System.Diagnostics.Debug.Assert(block != null);

                // If the existing block starts at this address, we're done.
                if (block.Location == ip)
                {
                    return(null);
                }

                // TBD: recover the following in some way...
#if false
                if (image[b.BasicBlock.StartAddress].Address.Segment != pos.Segment)
                {
                    AddError(pos, ErrorCategory.Error,
                             "Ran into the middle of a block [{0},{1}) from another segment " +
                             "when processing block {2} referred from {3}",
                             b.BasicBlock.StartAddress, b.BasicBlock.EndAddress,
                             start.Target, start.Source);
                    return(null);
                }
#endif

                // Now split the existing basic block into two. This requires
                // that the cut-off point is at instruction boundary.
                if (!b.IsLeadByte)
                {
                    AddError(ip, ErrorCode.RanIntoCode,
                             "XRef target is in the middle of an instruction (referred from {0})",
                             start.Source);
                    return(null);
                }
                BasicBlock[] subBlocks = BasicBlocks.SplitBasicBlock(block, ip, image);

                // Create a xref from the previous block to this block.
                XRef xref = CreateFallThroughXRef(GetLastInstructionInBasicBlock(subBlocks[0]), ip);
                xrefs.Add(xref);

                return(null);
            }
            // TODO: Move the above into a separate procedure.

            // Analyze each instruction in sequence until we encounter
            // analyzed code, flow instruction, or an error condition.
            BasicBlockType blockType = BasicBlockType.Unknown;
            while (true)
            {
                // Decode an instruction at this location.
                Address     instructionStart = ip;
                Instruction insn             = CreateInstruction(ip, start);
                if (insn == null)
                {
                    AddError(ip, ErrorCode.BrokenBasicBlock,
                             "Basic block ended prematurally because of invalid instruction.");
                    blockType = BasicBlockType.Broken;
                    break;
                }
                Address instructionEnd = ip + insn.EncodedLength;

                // Advance the instruction pointer.
                ip = instructionEnd;

                // Determine whether this instruction affects control flow.
                XRefType flowType = GetFlowInstructionType(insn.Operation);

                if (flowType != XRefType.None)
                {
                    // Creates an active cross reference if necessary.
                    if (NeedsActiveXRef(flowType))
                    {
                        XRef xref = CreateFlowXRef(flowType, instructionStart, insn);
                        if (xref != null)
                        {
                            xrefs.Add(xref);
                        }
                    }

                    // Creates a fall-through cross reference if necessary.
                    if (CanFallThrough(flowType))
                    {
                        XRef xref = CreateFallThroughXRef(instructionStart, instructionEnd);
                        xrefs.Add(xref);
                    }

                    // Terminate the block.
                    blockType = GetBasicBlockType(flowType);
                    break;
                }

                // If the new location is already analyzed as code, create a
                // control-flow edge from the previous block to the existing
                // block, and we are done.
                if (!image.IsAddressValid(ip))
                {
                    blockType = BasicBlockType.Broken;
                    break;
                }
                if (image[ip].Type == ByteType.Code)
                {
                    System.Diagnostics.Debug.Assert(image[ip].IsLeadByte);

                    XRef xref = CreateFallThroughXRef(instructionStart, instructionEnd);
                    xrefs.Add(xref);
                    blockType = BasicBlockType.FallThrough;
                    break;
                }
            }

            // Create a basic block unless we failed on the first instruction.
            if (ip.Offset > start.Target.Offset)
            {
                BasicBlock block = new BasicBlock(start.Target, ip, blockType, image);
                BasicBlocks.Add(block);
            }
            return(null);
        }