/// <summary>
 /// Analyzes code starting from the given location. That location
 /// should be the entry point of a procedure, or otherwise the
 /// analysis may not work correctly.
 /// </summary>
 /// <param name="entryPoint">Specifies the location to start analysis.
 /// This location is relative to the beginning of the image.</param>
 /// <param name="entryType">Type of entry, should usually be JMP or
 /// CALL.</param>
 public virtual void Analyze(Address entryPoint, XRefType entryType)
 {
     GenerateBasicBlocks(entryPoint, entryType);
     GenerateControlFlowGraph();
     GenerateProcedures();
     AddBasicBlocksToProcedures();
 }
示例#2
0
 public XRef(XRefType type, Address source, Address target, Address dataLocation)
 {
     this.Source       = source;
     this.Target       = target;
     this.Type         = type;
     this.DataLocation = dataLocation;
 }
        protected virtual BasicBlockType GetBasicBlockType(XRefType flowType)
        {
            switch (flowType)
            {
            case XRefType.ConditionalJump:
                return(BasicBlockType.Branch);

            case XRefType.NearJump:
            case XRefType.FarJump:
            case XRefType.NearIndexedJump:
                return(BasicBlockType.Jump);

            case XRefType.Interrupt:
            case XRefType.NearCall:
            case XRefType.FarCall:
                return(BasicBlockType.Call);

            case XRefType.NearReturn:
            case XRefType.FarReturn:
            case XRefType.InterruptReturn:
                return(BasicBlockType.Return);

            case XRefType.Halt:
                return(BasicBlockType.Halt);

            default:
                return(BasicBlockType.Unknown);
            }
        }
 /// <summary>
 /// Analyzes code starting from the given location. That location
 /// should be the entry point of a procedure, or otherwise the
 /// analysis may not work correctly.
 /// </summary>
 /// <param name="entryPoint">Specifies the location to start analysis.
 /// This location is relative to the beginning of the image.</param>
 /// <param name="entryType">Type of entry, should usually be JMP or
 /// CALL.</param>
 public virtual void Analyze(Address entryPoint, XRefType entryType)
 {
     GenerateBasicBlocks(entryPoint, entryType);
     GenerateControlFlowGraph();
     GenerateProcedures();
     AddBasicBlocksToProcedures();
 }
示例#5
0
 public ReferenceType(XRefType type, string id) : base()
 {
     if (type == XRefType.Unknown)
     {
         throw new ArgumentNullException(nameof(type));
     }
     this.XRefType = type;
     if (string.IsNullOrWhiteSpace(id))
     {
         throw new ArgumentNullException(nameof(id));
     }
     this.XRefId = id;
 }
        protected virtual XRef CreateBranchJumpCallXRef(
            XRefType type, Address source, Instruction instruction)
        {
            Address target = ResolveFlowInstructionTarget(instruction.Operands[0]);

            if (target == Address.Invalid)
            {
                AddError(source, ErrorCode.DynamicTarget,
                         "Cannot determine the target of {0} instruction.", instruction.Operation);
            }
            return(new XRef(
                       type: type,
                       source: source,
                       target: target
                       ));
        }
        /// <summary>
        /// Determines whether the given cross reference may possibly fall
        /// through to a "default" flow path such as "branch not taken" or
        /// "return from call".
        /// </summary>
        /// <param name="xrefType">Type of cross reference.</param>
        /// <returns></returns>
        /// <remarks>
        /// This method assumes that the program is well-formed, such that
        /// a "fall-through" path is always possible to be taken.
        ///
        /// In particular, if the instruction is a conditional jump, we
        /// assume that the condition may be true or false, so that both
        /// "jump" and "no jump" is a reachable branch. If the code is
        /// malformed such that one of the branches will never execute, the
        /// analysis may not work correctly.
        ///
        /// Likewise, if the instruction is a procedure call, we assume that
        /// the procedure being called will eventually return. If the
        /// procedure never returns, the analysis may not work correctly.
        /// </remarks>
        protected virtual bool CanFallThrough(XRefType xrefType)
        {
            switch (xrefType)
            {
            case XRefType.FarJump:
            case XRefType.NearJump:
            case XRefType.NearIndexedJump:
            case XRefType.FarReturn:
            case XRefType.NearReturn:
            case XRefType.InterruptReturn:
            case XRefType.Halt:
                return(false);

            default:
                return(true);
            }
        }
        protected virtual bool NeedsActiveXRef(XRefType flowType)
        {
            switch (flowType)
            {
            case XRefType.ConditionalJump:
            case XRefType.FarCall:
            case XRefType.NearCall:
            //case XRefType.Interrupt:
            case XRefType.FarJump:
            case XRefType.NearJump:
            case XRefType.NearIndexedJump:
                return(true);

            default:
                return(false);
            }
        }
        protected virtual XRef CreateFlowXRef(
            XRefType xrefType, Address source, Instruction instruction)
        {
            switch (xrefType)
            {
            case XRefType.ConditionalJump:
            case XRefType.FarJump:
            case XRefType.NearJump:
            case XRefType.FarCall:
            case XRefType.NearCall:
                return(CreateBranchJumpCallXRef(xrefType, source, instruction));

            case XRefType.NearIndexedJump:
                throw new NotImplementedException();

            default:
                return(null);
            }
        }
示例#10
0
        public static string AsString(this XRefType enumValue)
        {
            switch (enumValue)
            {
            case XRefType.Adresse: return(XRefTypeString.Adresse);

            case XRefType.Auftraggeber: return(XRefTypeString.Auftraggeber);

            case XRefType.Kontakt: return(XRefTypeString.Kontakt);

            case XRefType.Mitarbeiter: return(XRefTypeString.Mitarbeiter);

            case XRefType.LV: return(XRefTypeString.LV);

            case XRefType.LVVariante: return(XRefTypeString.LVVariante);

            case XRefType.LVNachtrag: return(XRefTypeString.LVNachtrag);

            case XRefType.LVBieter: return(XRefTypeString.LVBieter);

            case XRefType.Projekt: return(XRefTypeString.Projekt);

            case XRefType.Objekt: return(XRefTypeString.Objekt);

            case XRefType.Position: return(XRefTypeString.Position);

            case XRefType.Hierarchiestufe: return(XRefTypeString.Hierarchiestufe);

            case XRefType.Geraet: return(XRefTypeString.Geraet);

            case XRefType.Leistung: return(XRefTypeString.Leistung);

            case XRefType.Standardleistungskatalog: return(XRefTypeString.Standardleistungskatalog);

            case XRefType.Kreditorenrechnung: return(XRefTypeString.Kreditorenrechnung);
            }
            return(XRefTypeString.Unknown);
        }
示例#11
0
        /// <summary>
        /// Analyzes code starting from the given location, and create basic
        /// blocks iteratively.
        /// </summary>
        public void GenerateBasicBlocks(Address entryPoint, XRefType entryType)
        {
            Address address = entryPoint;

            // Maintain a queue of basic block entry points to analyze. At
            // the beginning, only the user-specified entry point is in the
            // queue. As we encounter b/c/j instructions during the course
            // of analysis, we push the target addresses to the queue of
            // entry points to be analyzed later.
            PriorityQueue <XRef> xrefQueue =
                new PriorityQueue <XRef>(XRef.CompareByPriority);

            // Maintain a list of all procedure calls (with known target)
            // encountered during the analysis. After we finish analyzing
            // all the basic blocks, we update the list of procedures.
            // List<XRef> xrefCalls = new List<XRef>();

            // Create a a dummy xref entry using the user-supplied starting
            // address.
            xrefQueue.Enqueue(new XRef(
                                  type: entryType,
                                  source: Address.Invalid,
                                  target: entryPoint
                                  ));

            // Analyze each cross reference in order of their priority.
            // In particular, if the xref is an indexed jump, we delay its
            // processing until we have processed all other types of xrefs.
            // This reduces the chance that we process past the end of a
            // jump table.
            while (!xrefQueue.IsEmpty)
            {
                XRef entry = xrefQueue.Dequeue();

                // Handle jump table entry, whose Target == Invalid.
                if (entry.Type == XRefType.NearIndexedJump)
                {
                    System.Diagnostics.Debug.Assert(entry.Target == Address.Invalid);

                    // Fill the Target field to make it a static xref.
                    entry = ProcessJumpTableEntry(entry, xrefQueue);
                    if (entry == null) // end of jump table
                    {
                        continue;
                    }
                }

                // Skip other dynamic xrefs.
                if (entry.Target == Address.Invalid)
                {
                    CrossReferences.Add(entry);
                    continue;
                }

                // Process the basic block starting at the target address.
                BasicBlock block = AnalyzeBasicBlock(entry, xrefQueue);
                if (block != null)
                {
                    //int count = block.Length;
                    //int baseOffset = PointerToOffset(entry.Target);
                    //proc.CodeRange.AddInterval(baseOffset, baseOffset + count);
                    //proc.ByteRange.AddInterval(baseOffset, baseOffset + count);
                    //for (int j = 0; j < count; j++)
                    //{
                    //    image[baseOffset + j].Procedure = proc;
                    //}
#if false
                    proc.AddBasicBlock(block);
#endif
                }
                CrossReferences.Add(entry);
            }
        }
示例#12
0
 public XRef(XRefType type, Address source, Address target)
     : this(type, source, target, Address.Invalid)
 {
 }
示例#13
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);
        }
示例#14
0
 /// <summary>
 /// Determines whether the given cross reference may possibly fall
 /// through to a "default" flow path such as "branch not taken" or
 /// "return from call".
 /// </summary>
 /// <param name="xrefType">Type of cross reference.</param>
 /// <returns></returns>
 /// <remarks>
 /// This method assumes that the program is well-formed, such that
 /// a "fall-through" path is always possible to be taken.
 ///
 /// In particular, if the instruction is a conditional jump, we
 /// assume that the condition may be true or false, so that both
 /// "jump" and "no jump" is a reachable branch. If the code is
 /// malformed such that one of the branches will never execute, the
 /// analysis may not work correctly.
 ///
 /// Likewise, if the instruction is a procedure call, we assume that
 /// the procedure being called will eventually return. If the
 /// procedure never returns, the analysis may not work correctly.
 /// </remarks>
 protected virtual bool CanFallThrough(XRefType xrefType)
 {
     switch (xrefType)
     {
         case XRefType.FarJump:
         case XRefType.NearJump:
         case XRefType.NearIndexedJump:
         case XRefType.FarReturn:
         case XRefType.NearReturn:
         case XRefType.InterruptReturn:
         case XRefType.Halt:
             return false;
         default:
             return true;
     }
 }
示例#15
0
        protected virtual XRef CreateBranchJumpCallXRef(
            XRefType type, Address source, Instruction instruction)
        {
            Address target = ResolveFlowInstructionTarget(instruction.Operands[0]);

            if (target == Address.Invalid)
            {
                AddError(source, ErrorCode.DynamicTarget,
                    "Cannot determine the target of {0} instruction.", instruction.Operation);
            }
            return new XRef(
                type: type,
                source: source,
                target: target
            );
        }
示例#16
0
 /**
  * Signals that a new XRef object (table or stream) starts.
  * @param startBytePos the offset to start at
  * @param type the type of the Xref object
  */
 public void nextXrefObj(long startBytePos, XRefType type)
 {
     bytePosToXrefMap[startBytePos] = curXrefTrailerObj = new XrefTrailerObj();
     curXrefTrailerObj.xrefType     = type;
 }
示例#17
0
 protected virtual bool NeedsActiveXRef(XRefType flowType)
 {
     switch (flowType)
     {
         case XRefType.ConditionalJump:
         case XRefType.FarCall:
         case XRefType.NearCall:
         //case XRefType.Interrupt:
         case XRefType.FarJump:
         case XRefType.NearJump:
         case XRefType.NearIndexedJump:
             return true;
         default:
             return false;
     }
 }
示例#18
0
        protected virtual BasicBlockType GetBasicBlockType(XRefType flowType)
        {
            switch (flowType)
            {
                case XRefType.ConditionalJump:
                    return BasicBlockType.Branch;

                case XRefType.NearJump:
                case XRefType.FarJump:
                case XRefType.NearIndexedJump:
                    return BasicBlockType.Jump;

                case XRefType.Interrupt:
                case XRefType.NearCall:
                case XRefType.FarCall:
                    return BasicBlockType.Call;

                case XRefType.NearReturn:
                case XRefType.FarReturn:
                case XRefType.InterruptReturn:
                    return BasicBlockType.Return;

                case XRefType.Halt:
                    return BasicBlockType.Halt;

                default:
                    return BasicBlockType.Unknown;
            }
        }
示例#19
0
        protected virtual XRef CreateFlowXRef(
            XRefType xrefType, Address source, Instruction instruction)
        {
            switch (xrefType)
            {
                case XRefType.ConditionalJump:
                case XRefType.FarJump:
                case XRefType.NearJump:
                case XRefType.FarCall:
                case XRefType.NearCall:
                    return CreateBranchJumpCallXRef(xrefType, source, instruction);

                case XRefType.NearIndexedJump:
                    throw new NotImplementedException();

                default:
                    return null;
            }
        }
示例#20
0
 /**
  *  Default constructor.
  */
 public XrefTrailerObj()
 {
     xrefType = XRefType.TABLE;
 }
示例#21
0
        /// <summary>
        /// Analyzes code starting from the given location, and create basic
        /// blocks iteratively.
        /// </summary>
        public void GenerateBasicBlocks(Address entryPoint, XRefType entryType)
        {
            Address address = entryPoint;

            // Maintain a queue of basic block entry points to analyze. At
            // the beginning, only the user-specified entry point is in the
            // queue. As we encounter b/c/j instructions during the course
            // of analysis, we push the target addresses to the queue of
            // entry points to be analyzed later.
            PriorityQueue<XRef> xrefQueue =
                new PriorityQueue<XRef>(XRef.CompareByPriority);

            // Maintain a list of all procedure calls (with known target)
            // encountered during the analysis. After we finish analyzing
            // all the basic blocks, we update the list of procedures.
            // List<XRef> xrefCalls = new List<XRef>();

            // Create a a dummy xref entry using the user-supplied starting
            // address.
            xrefQueue.Enqueue(new XRef(
                type: entryType,
                source: Address.Invalid,
                target: entryPoint
            ));

            // Analyze each cross reference in order of their priority.
            // In particular, if the xref is an indexed jump, we delay its
            // processing until we have processed all other types of xrefs.
            // This reduces the chance that we process past the end of a
            // jump table.
            while (!xrefQueue.IsEmpty)
            {
                XRef entry = xrefQueue.Dequeue();

                // Handle jump table entry, whose Target == Invalid.
                if (entry.Type == XRefType.NearIndexedJump)
                {
                    System.Diagnostics.Debug.Assert(entry.Target == Address.Invalid);

                    // Fill the Target field to make it a static xref.
                    entry = ProcessJumpTableEntry(entry, xrefQueue);
                    if (entry == null) // end of jump table
                        continue;
                }

                // Skip other dynamic xrefs.
                if (entry.Target == Address.Invalid)
                {
                    CrossReferences.Add(entry);
                    continue;
                }

                // Process the basic block starting at the target address.
                BasicBlock block = AnalyzeBasicBlock(entry, xrefQueue);
                if (block != null)
                {
                    //int count = block.Length;
                    //int baseOffset = PointerToOffset(entry.Target);
                    //proc.CodeRange.AddInterval(baseOffset, baseOffset + count);
                    //proc.ByteRange.AddInterval(baseOffset, baseOffset + count);
                    //for (int j = 0; j < count; j++)
                    //{
                    //    image[baseOffset + j].Procedure = proc;
                    //}
            #if false
                    proc.AddBasicBlock(block);
            #endif
                }
                CrossReferences.Add(entry);
            }
        }