Esempio n. 1
0
        public void CollectTypes()
        {
            CollectGlobalType();
            CollectUserGlobalVariableTypes();
            CollectImageSymbols();
            int cProc = program.Procedures.Count;
            int i     = 0;

            foreach (Procedure proc in program.Procedures.Values)
            {
                eventListener.ShowProgress("Collecting data types.", i++, cProc);
                CollectProcedureSignature(proc);
                foreach (Statement stm in proc.Statements)
                {
                    if (eventListener.IsCanceled())
                    {
                        return;
                    }
                    try
                    {
                        this.stmCur = stm;
                        stm.Instruction.Accept(this);
                    }
                    catch (Exception ex)
                    {
                        eventListener.Error(
                            eventListener.CreateStatementNavigator(program, stm),
                            ex,
                            "An error occurred while processing the statement {0}.",
                            stm);
                    }
                }
            }
        }
Esempio n. 2
0
        public void CollectTypes()
        {
            desc.MeetDataType(program.Globals, factory.CreatePointer(
                                  factory.CreateStructureType(),
                                  program.Platform.PointerType.BitSize));
            CollectUserGlobalVariableTypes(store.SegmentTypes);
            int cProc = program.Procedures.Count;
            int i     = 0;

            foreach (Procedure proc in program.Procedures.Values)
            {
                eventListener.ShowProgress("Collecting data types.", i++, cProc);
                CollectProcedureSignature(proc);
                foreach (Statement stm in proc.Statements)
                {
                    if (eventListener.IsCanceled())
                    {
                        return;
                    }
                    try
                    {
                        this.stmCur = stm;
                        stm.Instruction.Accept(this);
                    }
                    catch (Exception ex)
                    {
                        eventListener.Error(
                            eventListener.CreateStatementNavigator(program, stm),
                            ex,
                            "An error occurred while processing the statement {0}.",
                            stm);
                    }
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Performs a shingle scan of the executable segments of the program,
        /// returning the interprocedural control flow graph (ICFG) and locations
        /// of likely call destinations.
        /// </summary>
        /// <returns></returns>
        public ScanResults ScanNew()
        {
            ICodeLocation location = null;
            Exception     error;

            try
            {
                var q = ScanExecutableSegments();
            }
            catch (AddressCorrelatedException aex)
            {
                location = eventListener.CreateAddressNavigator(program, aex.Address);
                error    = aex;
            }
            catch (Exception ex)
            {
                location = new NullCodeLocation("");
                error    = ex;
            }
            if (location != null)
            {
                eventListener.Error(location, "An error occurred while scanning {0}.");
            }
            return(new ScanResults
            {
                ICFG = new DiGraph <RtlBlock>(),
                DirectlyCalledAddresses = this.sr.DirectlyCalledAddresses,
                KnownProcedures = sr.KnownProcedures,
            });
        }
Esempio n. 4
0
        private static RekoEventsAPI Evaluate(
            TextWriter outputWriter,
            DecompilerEventListener eventListener,
            IConfigurationService cfgSvc,
            IFileSystemService fsSvc,
            string script,
            string filename)
        {
            var engine = CreateEngine(outputWriter);

            outputWriter.WriteLine($"Evaluating {filename}");
            var pythonAPI = new PythonAPI(cfgSvc, fsSvc, engine);
            var eventsAPI = new RekoEventsAPI(engine);
            var scope     = CreateRekoVariable(engine, pythonAPI, eventsAPI);
            var src       = engine.CreateScriptSourceFromString(script, filename);

            try
            {
                src.Execute(scope);
            }
            catch (Exception ex)
            {
                var scriptError = CreateError(
                    filename,
                    ex,
                    "An error occurred while evaluating the Python script.",
                    engine);
                eventListener.Error(scriptError);
                DumpPythonStack(outputWriter, ex, engine);
                return(new RekoEventsAPI(engine));
            }
            return(eventsAPI);
        }
Esempio n. 5
0
        private IPlatform MakePlatform()
        {
            string envName;

            switch (this.hdr.os_type)
            {
            case TargetOS.OS2:
                envName = "os2-32";
                break;

            case TargetOS.Win32:
                if (hdr.module_flags.HasFlag(ModuleFlags.VirtualDeviceDriver))
                {
                    envName = "win-vmm";
                }
                else
                {
                    envName = "win32";
                }
                break;

            default:
                listener.Error($"Unsupported operating environment {this.hdr.os_type}.");
                return(new DefaultPlatform(this.Services, this.arch));
            }
            var platform = Services.RequireService <IConfigurationService>()
                           .GetEnvironment(envName)
                           .Load(Services, arch);

            return(platform);
        }
Esempio n. 6
0
 public void CollectTypes()
 {
     desc.MeetDataType(program.Globals, factory.CreatePointer(
                           factory.CreateStructureType(),
                           program.Platform.PointerType.Size));
     CollectSegmentTypes();
     foreach (Procedure p in program.Procedures.Values)
     {
         proc = p;
         CollectProcedureSignature(p);
         foreach (Statement stm in p.Statements)
         {
             if (eventListener.IsCanceled())
             {
                 return;
             }
             try
             {
                 stm.Instruction.Accept(this);
             }
             catch (Exception ex)
             {
                 eventListener.Error(
                     eventListener.CreateStatementNavigator(program, stm),
                     ex,
                     "An error occurred while processing the statement {0}.",
                     stm);
             }
         }
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Processes procedures individually, building complex expression
        /// trees out of the simple, close-to-the-machine code generated by
        /// the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            eventListener.ShowProgress("Building expressions.", 0, program.Procedures.Count);
            foreach (var sst in this.ssts)
            {
                var ssa = sst.SsaState;
                try
                {
                    DumpWatchedProcedure("Before expression coalescing", ssa.Procedure);

                    // Procedures should be untangled from each other. Now process
                    // each one separately.
                    DeadCode.Eliminate(ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.
                    var coa = new Coalescer(ssa);
                    coa.Transform();
                    DeadCode.Eliminate(ssa);

                    var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                    vp.Transform();

                    DumpWatchedProcedure("After expression coalescing", ssa.Procedure);

                    var liv = new LinearInductionVariableFinder(
                        ssa,
                        new BlockDominatorGraph(
                            ssa.Procedure.ControlGraph,
                            ssa.Procedure.EntryBlock));
                    liv.Find();

                    foreach (var de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    DeadCode.Eliminate(ssa);
                    DumpWatchedProcedure("After strength reduction", ssa.Procedure);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(program, ssa, program.InductionVariables, eventListener);
                    web.Transform();
                    ssa.ConvertBack(false);

                    DumpWatchedProcedure("After data flow analysis", ssa.Procedure);
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        eventListener.CreateProcedureNavigator(program, ssa.Procedure),
                        ex,
                        "An internal error occurred while building the expressions of {0}",
                        ssa.Procedure.Name);
                }
                eventListener.Advance(1);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Loads the image into memory at the specified address, using the provided
        /// <seealso cref="IProcessorArchitecture"/> and <seealso cref="IPlatform"/>.
        /// Used when loading raw files; not all image loaders can support this.
        /// </summary>
        /// <param name="addrLoad">Loading address *IGNORED*.</param>
        /// <param name="arch">Processor architecture.</param>
        /// <param name="platform">Platform/operating environment.</param>
        /// <returns>
        /// A <see cref="Program"/> instance.
        /// </returns>
        public override Program Load(Address addrLoad, IProcessorArchitecture arch, IPlatform platform)
        {
            listener = Services.RequireService <DecompilerEventListener>();
            var     memChunks = new MemoryChunksList();
            Address addrEp    = null;

            using (var rdr = new IntelHexReader(new MemoryStream(RawImage)))
            {
                try
                {
                    for (; ;)
                    {
                        if (!rdr.TryReadRecord(out uint address, out byte[] data))
                        {
                            break;
                        }
                        if (data != null)
                        {
                            memChunks.AddData(address, data);
                            continue;
                        }
                    }
                    addrEp = rdr.StartAddress;
                }
                catch (IntelHexException ex)
                {
                    listener.Error(new NullCodeLocation(""), ex.Message);
                    return(null);
                }
            }

            var segs = new SegmentMap(PreferredBaseAddress);

            // Generate the image segments with fake names.
            int i = 0;

            foreach (var mchk in memChunks)
            {
                var mem = new MemoryArea(mchk.BaseAddress, mchk.Datum.ToArray());
                var seg = new ImageSegment($"CODE_{i++:d2}", mem, AccessMode.ReadExecute);
                segs.AddSegment(seg);
            }

            var prog = new Program()
            {
                SegmentMap = segs, Architecture = arch, Platform = platform
            };

            if (addrEp != null)
            {
                prog.EntryPoints.Add(addrEp, new Core.ImageSymbol(addrEp)
                {
                    Type = SymbolType.Procedure
                });
            }
            return(prog);
        }
Esempio n. 9
0
 public override void FireEvent(ScriptEvent @event, Program program)
 {
     try
     {
         var programAPI     = new RekoProgramAPI(program);
         var programWrapper = pythonAPI.CreateProgramWrapper(
             programAPI);
         eventsAPI.FireEvent(@event, programWrapper);
     }
     catch (Exception ex)
     {
         eventListener.Error(
             new NullCodeLocation(Filename),
             ex,
             "An error occurred while running the Python script.");
         DumpPythonStack(ex, engine);
     }
 }
Esempio n. 10
0
        /// <summary>
        /// Loads the image into memory at the specified address, using the provided
        /// <seealso cref="IProcessorArchitecture"/> and <seealso cref="IPlatform"/>.
        /// Used when loading raw files; not all image loaders can support this.
        /// </summary>
        /// <param name="addrLoad">Loading address *IGNORED*.</param>
        /// <param name="arch">Processor architecture.</param>
        /// <param name="platform">Platform/operating environment.</param>
        /// <returns>
        /// A <see cref="Program"/> instance.
        /// </returns>
        public override Program LoadProgram(Address addrLoad, IProcessorArchitecture arch, IPlatform platform)
        {
            listener = Services.RequireService <DecompilerEventListener>();
            var     memChunks = new MemoryChunksList();
            Address?addrEp    = null;
            Address addrBase  = MakeZeroAddress(arch);

            using (var rdr = new IntelHexReader(new MemoryStream(RawImage), addrBase))
            {
                try
                {
                    for (; ;)
                    {
                        if (!rdr.TryReadRecord(out Address address, out byte[] data))
                        {
                            break;
                        }
                        if (data != null)
                        {
                            memChunks.AddData(address, data);
                            continue;
                        }
                    }
                    addrEp = rdr.StartAddress;
                }
                catch (IntelHexException ex)
                {
                    listener.Error(ex.Message);
                    return(null !);
                }
            }

            var segs = new SegmentMap(PreferredBaseAddress);

            // Generate the image segments with fake names.
            int i = 0;

            foreach (var mchk in memChunks)
            {
                var mem = arch.CreateMemoryArea(mchk.BaseAddress, mchk.Datum.ToArray());
                var seg = new ImageSegment($"CODE_{i:d2}", mem, AccessMode.ReadExecute);
                ++i;
                segs.AddSegment(seg);
            }

            var program = new Program(segs, arch, platform);

            if (addrEp != null)
            {
                program.EntryPoints.Add(addrEp, ImageSymbol.Procedure(arch, addrEp));
            }
            return(program);
        }
Esempio n. 11
0
 /// <summary>
 /// Main entry point of the decompiler. Loads, decompiles, and outputs the results.
 /// </summary>
 public void Decompile(string filename)
 {
     try
     {
         Load(filename);
         ScanPrograms();
         AnalyzeDataFlow();
         ReconstructTypes();
         StructureProgram();
         WriteDecompilerProducts();
     }
     catch (Exception ex)
     {
         eventListener.Error(
             new NullCodeLocation(filename),
             ex,
             "An internal error occurred while decompiling.");
     }
     finally
     {
         eventListener.ShowStatus("Decompilation finished.");
     }
 }
Esempio n. 12
0
        private void PopulateImports()
        {
            BeImageReader memRdr = new BeImageReader(xexData.memoryData);

            for (int i = 0; i < xexData.import_records.Count; i++)
            {
                UInt32 tableAddress = xexData.import_records[i];

                UInt32 memOffset = tableAddress - xexData.exe_address;
                if (memOffset > xexData.memorySize)
                {
                    throw new BadImageFormatException($"XEX: invalid import record offset: 0x{memOffset}");
                }

                UInt32 value = memRdr.ReadAt <UInt32>(memOffset, rdr => rdr.ReadUInt32());

                XexImportType type     = (XexImportType)((value & 0xFF000000) >> 24);
                byte          libIndex = (byte)((value & 0x00FF0000) >> 16);

                if (type > XexImportType.Function)
                {
                    decompilerEventListener.Error(
                        $"XEX: Unsupported import type {type}, value: 0x{value:X}");
                    continue;
                }

                if (libIndex >= xexData.libNames.Count)
                {
                    throw new BadImageFormatException($"XEX: invalid import record lib index ({libIndex}, max:{xexData.libNames.Count})");
                }

                UInt32    importOrdinal = (value & 0xFFFF);
                string    importLibName = xexData.libNames[libIndex];
                Address32 importAddress = new Address32(xexData.import_records[i]);

                SymbolType symbolType = SymbolType.Unknown;
                switch (type)
                {
                case XexImportType.Data:
                    symbolType = SymbolType.Data;
                    break;

                case XexImportType.Function:
                    symbolType = SymbolType.ExternalProcedure;
                    break;
                }
                imports.Add(importAddress, new OrdinalImportReference(importAddress, importLibName, (int)importOrdinal, symbolType));
            }
        }
Esempio n. 13
0
        private bool ProcessLine(string line, int num, MemoryStream loaded)
        {
            line = line.TrimEnd();
            if (line.Length == 0 || line[0] != ':')
            {
                listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                return(false);
            }
            uint?byteCount = Unhex(line, 1, 2);

            if (byteCount == null)
            {
                // Invalid byte count.
                listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                return(false);
            }
            if (line.Length != 1 + 2 * (1 + 2 + 1 + byteCount + 1))
            {
                // Invalid line length
                listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                return(false);
            }
            uint?address = Unhex(line, 3, 4);

            if (address == null)
            {
                // Invalid address
                listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                return(false);
            }
            uint?recordType = Unhex(line, 7, 2);

            if (recordType == null)
            {
                // Invalid record type
                listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                return(false);
            }
            for (int i = 0; i < byteCount; ++i)
            {
                uint?b = Unhex(line, 9 + i * 2, 2);
                if (b == null)
                {
                    // invalid data
                    listener.Error(new NullCodeLocation(""), "Line {0} is invalid.", num);
                    return(false);
                }
                loaded.WriteByte((byte)b);
            }
            return(true);
        }
Esempio n. 14
0
 /// <summary>
 /// Rewrites indirect call statements to applications using
 /// user-defined data. Also generates statements that adjust
 /// the stack pointer according to the calling convention.
 /// </summary>
 /// <returns>True if statements were changed.</returns>
 public bool Rewrite()
 {
     changed = false;
     foreach (Statement stm in proc.Statements.ToList())
     {
         if (stm.Instruction is CallInstruction ci)
         {
             try
             {
                 RewriteCall(stm, ci);
             }
             catch (Exception ex)
             {
                 eventListener.Error(
                     eventListener.CreateStatementNavigator(program, stm),
                     ex,
                     "Indirect call rewriter encountered an error while processing the statement {0}.",
                     stm);
             }
         }
     }
     return(changed);
 }
Esempio n. 15
0
 public void Rewrite()
 {
     foreach (Statement stm in proc.Statements)
     {
         CallInstruction ci = stm.Instruction as CallInstruction;
         if (ci != null)
         {
             try
             {
                 RewriteCall(stm, ci);
                 throw new NotImplementedException("bleh");      //$DEBUG
             }
             catch (Exception ex)
             {
                 eventListener.Error(
                     eventListener.CreateStatementNavigator(program, stm),
                     ex,
                     "Indirect call rewriter encountered an error while processing the statement {0}.",
                     stm);
             }
         }
     }
 }
Esempio n. 16
0
        public void Transform()
        {
            foreach (var s in ssaIds.ToList())
            {
                sidGrf = s;
                if (!IsLocallyDefinedFlagGroup(sidGrf))
                {
                    continue;
                }
                if (sidGrf.DefStatement !.Instruction is AliasAssignment)
                {
                    continue;
                }
                var uses = new HashSet <Statement>();
                this.aliases.Clear();
                ClosureOfUsingStatements(sidGrf, uses, aliases);
                trace.Inform("CCE: Tracing {0}", sidGrf.DefStatement.Instruction);

                foreach (var u in uses)
                {
                    try
                    {
                        useStm = u;

                        trace.Inform("CCE:   used {0}", useStm.Instruction);
                        useStm.Instruction.Accept(this);
                        trace.Inform("CCE:    now {0}", useStm.Instruction);
                    }
                    catch (Exception ex)
                    {
                        var loc = listener.CreateStatementNavigator(program, u);
                        listener.Error(loc, ex, "An error occurred while eliminating condition codes in procedure {0}.", ssa.Procedure.Name);
                    }
                }
            }
        }
Esempio n. 17
0
        public override void FireEvent(ScriptEvent @event, Program program)
        {
            var eventsAPI = this.eventsAPI;
            var engine    = eventsAPI.Engine;

            try
            {
                var pythonAPI      = new PythonAPI(cfgSvc, fsSvc, engine);
                var programAPI     = new RekoProgramAPI(program);
                var programWrapper = pythonAPI.CreateProgramWrapper(
                    programAPI);
                eventsAPI.FireEvent(@event, programWrapper);
            }
            catch (Exception ex)
            {
                var scriptError = CreateError(
                    Location.FilesystemPath,
                    ex,
                    "An error occurred while running the Python script.",
                    engine);
                eventListener.Error(scriptError);
                DumpPythonStack(outputWriter, ex, engine);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Processes procedures individually, building complex expression trees out
        /// of the simple, close-to-the-machine code generated by the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            int i = 0;

            foreach (Procedure proc in program.Procedures.Values)
            {
                eventListener.ShowProgress("Building complex expressions.", i, program.Procedures.Values.Count);
                ++i;

                try
                {
                    var larw = new LongAddRewriter(proc, program.Architecture);
                    larw.Transform();

                    Aliases alias = new Aliases(proc, program.Architecture, flow);
                    alias.Transform();

                    var doms = new DominatorGraph <Block>(proc.ControlGraph, proc.EntryBlock);
                    var sst  = new SsaTransform(flow, proc, importResolver, doms);
                    var ssa  = sst.SsaState;

                    var cce = new ConditionCodeEliminator(ssa.Identifiers, program.Platform);
                    cce.Transform();
                    //var cd = new ConstDivisionImplementedByMultiplication(ssa);
                    //cd.Transform();

                    DeadCode.Eliminate(proc, ssa);

                    var vp = new ValuePropagator(program.Architecture, ssa.Identifiers, proc);
                    vp.Transform();
                    DeadCode.Eliminate(proc, ssa);


                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.

                    var coa = new Coalescer(proc, ssa);
                    coa.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    var liv = new LinearInductionVariableFinder(
                        proc,
                        ssa.Identifiers,
                        new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock));
                    liv.Find();

                    foreach (KeyValuePair <LinearInductionVariable, LinearInductionVariableContext> de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    var opt = new OutParameterTransformer(proc, ssa.Identifiers);
                    opt.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables);
                    web.Transform();
                    ssa.ConvertBack(false);
                }
                catch (StatementCorrelatedException stex)
                {
                    eventListener.Error(
                        eventListener.CreateBlockNavigator(program, stex.Statement.Block),
                        stex,
                        "An error occurred during data flow analysis.");
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        new NullCodeLocation(proc.Name),
                        ex,
                        "An error occurred during data flow analysis.");
                }
            }
        }
Esempio n. 19
0
 public void Error(Address addr, string message, params object[] args)
 {
     eventListener.Error(eventListener.CreateAddressNavigator(Program, addr), message, args);
 }
Esempio n. 20
0
        /// <summary>
        /// Apply relocations to a segment.
        /// </summary>
        private bool ApplyRelocations(EndianImageReader rdr, int cRelocations, NeSegment seg)
        {
            Address           address = null;
            NeRelocationEntry rep;

            Debug.Print("== Relocating segment {0}", seg.Address);
            for (int i = 0; i < cRelocations; i++)
            {
                rep = new NeRelocationEntry
                {
                    address_type    = (NE_RADDR)rdr.ReadByte(),
                    relocation_type = (NE_RELTYPE)rdr.ReadByte(),
                    offset          = rdr.ReadLeUInt16(),
                    target1         = rdr.ReadLeUInt16(),
                    target2         = rdr.ReadLeUInt16(),
                };
                Debug.Print("  {0}", WriteRelocationEntry(rep));

                // Get the target address corresponding to this entry.

                // If additive, there is no target chain list. Instead, add source
                //  and target.
                bool additive = (rep.relocation_type & NE_RELTYPE.ADDITIVE) != 0;
                Tuple <Address, ImportReference> impRef;
                uint   lp;
                string module = "";
                switch (rep.relocation_type & (NE_RELTYPE)3)
                {
                case NE_RELTYPE.ORDINAL:
                    module = moduleNames[rep.target1 - 1];
                    // Synthesize an import
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new OrdinalImportReference(address, module, rep.target2, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.NAME:
                    module = moduleNames[rep.target1 - 1];
                    uint offName      = lfaNew + this.offImportedNamesTable + rep.target2;
                    var  nameRdr      = new LeImageReader(RawImage, offName);
                    byte fnNameLength = nameRdr.ReadByte();
                    var  abFnName     = nameRdr.ReadBytes(fnNameLength);
                    // Synthesize the import.
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        string fnName = Encoding.ASCII.GetString(abFnName);
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new NamedImportReference(address, module, fnName, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.INTERNAL:
                    if ((rep.target1 & 0xff) == 0xff)
                    {
                        address = this.entryPoints[rep.target2 - 1].Address;
                    }
                    else
                    {
                        address = segments[rep.target1 - 1].Address + rep.target2;
                    }
                    Debug.Print("    {0}: {1:X4}:{2:X4} {3}",
                                i + 1,
                                address.Selector.Value,
                                address.Offset,
                                "");
                    break;

                case NE_RELTYPE.OSFIXUP:
                    /* Relocation type 7:
                     *
                     *    These appear to be used as fixups for the Windows
                     * floating point emulator.  Let's just ignore them and
                     * try to use the hardware floating point.  Linux should
                     * successfully emulate the coprocessor if it doesn't
                     * exist.
                     */
                    /*
                     * TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                     *   i + 1, rep->relocation_type, rep->offset,
                     *   rep->target1, rep->target2,
                     *   NE_GetRelocAddrName( rep->address_type, additive ) );
                     */
                    continue;
                }
                ushort offset = rep.offset;

                // Apparently, high bit of address_type is sometimes set;
                // we ignore it for now.
                if (rep.address_type > NE_RADDR.OFFSET32)
                {
                    listener.Error(
                        string.Format(
                            "Module {0}: unknown relocation address type {1:X2}. Please report",
                            module, rep.address_type));
                    return(false);
                }

                if (additive)
                {
                    var sp = seg.Address + offset;
                    Debug.Print("    {0} (contains: {1:X4})", sp, mem.ReadLeUInt16(sp));
                    byte   b;
                    ushort w;
                    switch (rep.address_type & (NE_RADDR)0x7f)
                    {
                    case NE_RADDR.LOWBYTE:
                        b = mem.ReadByte(sp);
                        mem.WriteByte(sp, (byte)(b + address.Offset));
                        break;

                    case NE_RADDR.OFFSET16:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        break;

                    case NE_RADDR.POINTER32:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                        break;

                    case NE_RADDR.SELECTOR:
                        // Borland creates additive records with offset zero. Strange, but OK.
                        w = mem.ReadLeUInt16(sp);
                        if (w != 0)
                        {
                            listener.Error(string.Format("Additive selector to {0:X4}. Please report.", w));
                        }
                        else
                        {
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                        }
                        break;

                    default:
                        goto unknown;
                    }
                }
                else
                {
                    // Non-additive fixup.
                    do
                    {
                        var    sp          = seg.Address + offset;
                        ushort next_offset = mem.ReadLeUInt16(sp);
                        Debug.Print("    {0} (contains: {1:X4})", sp, next_offset);
                        switch (rep.address_type & (NE_RADDR)0x7f)
                        {
                        case NE_RADDR.LOWBYTE:
                            mem.WriteByte(sp, (byte)address.Offset);
                            break;

                        case NE_RADDR.OFFSET16:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            break;

                        case NE_RADDR.POINTER32:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                            break;

                        case NE_RADDR.SELECTOR:
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                            break;

                        default:
                            goto unknown;
                        }
                        if (next_offset == offset)
                        {
                            break;                         // avoid infinite loop
                        }
                        if (next_offset >= seg.Alloc)
                        {
                            break;
                        }
                        offset = next_offset;
                    } while (offset != 0xffff);
                }
            }
            return(true);

unknown:
            listener.Warn("{0}: unknown ADDR TYPE {1},  " +
                          "TYPE {2},  OFFSET {3:X4},  TARGET {4:X4} {5:X4}",
                          seg.Address.Selector, rep.address_type, rep.relocation_type,
                          rep.offset, rep.target1, rep.target2);
            return(false);
        }
Esempio n. 21
0
 public void Error(Address addr, string message)
 {
     eventListener.Error(eventListener.CreateAddressNavigator(program, addr), message);
 }
Esempio n. 22
0
        /// <summary>
        /// Processes procedures individually, building complex expression
        /// trees out of the simple, close-to-the-machine code generated by
        /// the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            eventListener.ShowProgress("Building expressions.", 0, program.Procedures.Count);
            foreach (var sst in this.ssts !)
            {
                var ssa = sst.SsaState;
                try
                {
                    if (program.User.AggressiveBranchRemoval)
                    {
                        // This ends up being very aggressive and doesn't replicate the original
                        // binary code. See discussion on https://github.com/uxmal/reko/issues/932
                        DumpWatchedProcedure("urb", "Before unreachable block removal", ssa.Procedure);
                        var urb = new UnreachableBlockRemover(ssa, eventListener);
                        urb.Transform();
                    }

                    DumpWatchedProcedure("precoa", "Before expression coalescing", ssa.Procedure);

                    // Procedures should be untangled from each other. Now process
                    // each one separately.
                    DeadCode.Eliminate(ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.
                    var coa = new Coalescer(ssa);
                    coa.Transform();
                    DeadCode.Eliminate(ssa);

                    var vp = new ValuePropagator(program.SegmentMap, ssa, program.CallGraph, dynamicLinker, eventListener);
                    vp.Transform();

                    DumpWatchedProcedure("postcoa", "After expression coalescing", ssa.Procedure);

                    var liv = new LinearInductionVariableFinder(
                        ssa,
                        new BlockDominatorGraph(
                            ssa.Procedure.ControlGraph,
                            ssa.Procedure.EntryBlock));
                    liv.Find();

                    foreach (var de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    DeadCode.Eliminate(ssa);
                    DumpWatchedProcedure("sr", "After strength reduction", ssa.Procedure);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(program, ssa, program.InductionVariables, eventListener);
                    web.Transform();
                    ssa.ConvertBack(false);

                    DumpWatchedProcedure("dfa", "After data flow analysis", ssa.Procedure);
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        eventListener.CreateProcedureNavigator(program, ssa.Procedure),
                        ex,
                        "An internal error occurred while building the expressions of {0}",
                        ssa.Procedure.Name);
                }
                eventListener.Advance(1);
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Processes procedures individually, building complex expression trees out
        /// of the simple, close-to-the-machine code generated by the disassembly.
        /// </summary>
        /// <param name="rl"></param>
        public void BuildExpressionTrees()
        {
            int i = 0;

            foreach (Procedure proc in program.Procedures.Values)
            {
                if (eventListener.IsCanceled())
                {
                    break;
                }
                eventListener.ShowProgress("Building complex expressions.", i, program.Procedures.Values.Count);
                ++i;

                try
                {
                    var sst = BuildSsaTransform(proc);
                    var ssa = sst.SsaState;

                    var fuser = new UnalignedMemoryAccessFuser(ssa);
                    fuser.Transform();

                    var vp = new ValuePropagator(program.SegmentMap, ssa, importResolver, eventListener);

                    sst.RenameFrameAccesses = true;
                    var icrw = new IndirectCallRewriter(program, ssa, eventListener);
                    while (!eventListener.IsCanceled() && icrw.Rewrite())
                    {
                        vp.Transform();
                        sst.Transform();
                    }
                    var cce = new ConditionCodeEliminator(ssa, program.Platform);
                    cce.Transform();
                    //var cd = new ConstDivisionImplementedByMultiplication(ssa);
                    //cd.Transform();

                    DeadCode.Eliminate(proc, ssa);

                    vp.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Build expressions. A definition with a single use can be subsumed
                    // into the using expression.

                    var coa = new Coalescer(proc, ssa);
                    coa.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    vp.Transform();

                    var liv = new LinearInductionVariableFinder(
                        proc,
                        ssa.Identifiers,
                        new BlockDominatorGraph(proc.ControlGraph, proc.EntryBlock));
                    liv.Find();

                    foreach (KeyValuePair <LinearInductionVariable, LinearInductionVariableContext> de in liv.Contexts)
                    {
                        var str = new StrengthReduction(ssa, de.Key, de.Value);
                        str.ClassifyUses();
                        str.ModifyUses();
                    }
                    var opt = new OutParameterTransformer(proc, ssa.Identifiers);
                    opt.Transform();
                    DeadCode.Eliminate(proc, ssa);

                    // Definitions with multiple uses and variables joined by PHI functions become webs.
                    var web = new WebBuilder(proc, ssa.Identifiers, program.InductionVariables);
                    web.Transform();
                    ssa.ConvertBack(false);
                }
                catch (StatementCorrelatedException stex)
                {
                    eventListener.Error(
                        eventListener.CreateStatementNavigator(program, stex.Statement),
                        stex,
                        "An error occurred during data flow analysis.");
                }
                catch (Exception ex)
                {
                    eventListener.Error(
                        new NullCodeLocation(proc.Name),
                        ex,
                        "An error occurred during data flow analysis.");
                }
            }
        }