public FormatSplitAddress(DisasmProject project, TypedRangeSet selection,
                                  Formatter formatter)
        {
            InitializeComponent();

            mProject   = project;
            mFormatter = formatter;
            mSelection = selection;

            mOutputReady = false;
        }
        public FormatAddressTable(Window owner, DisasmProject project, TypedRangeSet selection,
                                  Formatter formatter)
        {
            InitializeComponent();
            Owner       = owner;
            DataContext = this;

            mProject   = project;
            mFormatter = formatter;
            mSelection = selection;
            IsValid    = false;

            OutputPreviewList = new ObservableCollection <OutputPreviewItem>();
        }
Esempio n. 3
0
        /// <summary>
        /// Creates an UndoableChange for a type hint update.  Rather than adding a
        /// separate UndoableChange for each affected offset -- which could span the
        /// entire file -- we use range sets to record the before/after state.
        /// </summary>
        /// <param name="undoSet">Current values.</param>
        /// <param name="newSet">New values.</param>
        /// <returns>Change record.</returns>
        public static UndoableChange CreateTypeHintChange(TypedRangeSet undoSet,
                                                          TypedRangeSet newSet)
        {
            if (newSet.Count == 0)
            {
                Debug.WriteLine("Empty hint change?");
            }
            UndoableChange uc = new UndoableChange();

            uc.Type     = ChangeType.SetTypeHint;
            uc.Offset   = -1;
            uc.OldValue = undoSet;
            uc.NewValue = newSet;
            // Any hint change can affect whether something is treated as code.
            // Either we're deliberately setting it as code or non-code, or we're
            // setting it to "no hint", which means the code analyzer gets
            // to make the decision now.  This requires a full code+data re-analysis.
            uc.ReanalysisRequired = ReanalysisScope.CodeAndData;
            return(uc);
        }
Esempio n. 4
0
        /// <summary>
        /// Serializes a DisasmProject into an augmented JSON string.
        /// </summary>
        /// <param name="proj">Project to serialize.</param>
        /// <returns>Augmented JSON string.</returns>
        public static string SerializeProject(DisasmProject proj)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(MAGIC);   // augment with version string, which will be stripped
            sb.Append("\r\n");  // will be ignored by deserializer; might get converted to \n

            SerializableProjectFile1 spf = new SerializableProjectFile1();

            spf._ContentVersion = ProjectFile.CONTENT_VERSION;

            Debug.Assert(proj.FileDataLength == proj.FileData.Length);
            spf.FileDataLength = proj.FileDataLength;
            spf.FileDataCrc32  = (int)proj.FileDataCrc32;

            // Convert AddressMap to serializable form.
            spf.AddressMap = new List <SerAddressMap>();
            foreach (AddressMap.AddressMapEntry ent in proj.AddrMap)
            {
                spf.AddressMap.Add(new SerAddressMap(ent));
            }

            // Reduce TypeHints to a collection of ranges.  Output the type enum as a string
            // so we're not tied to a specific value.
            spf.TypeHints = new List <SerTypeHintRange>();
            TypedRangeSet trs = new TypedRangeSet();

            for (int i = 0; i < proj.TypeHints.Length; i++)
            {
                trs.Add(i, (int)proj.TypeHints[i]);
            }
            IEnumerator <TypedRangeSet.TypedRange> iter = trs.RangeListIterator;

            while (iter.MoveNext())
            {
                if (iter.Current.Type == (int)CodeAnalysis.TypeHint.NoHint)
                {
                    continue;
                }
                spf.TypeHints.Add(new SerTypeHintRange(iter.Current.Low, iter.Current.High,
                                                       ((CodeAnalysis.TypeHint)iter.Current.Type).ToString()));
            }

            // Convert StatusFlagOverrides to serializable form.  Just write the state out
            // as an integer... not expecting it to change.  If it does, we can convert.
            spf.StatusFlagOverrides = new Dictionary <string, int>();
            for (int i = 0; i < proj.StatusFlagOverrides.Length; i++)
            {
                if (proj.StatusFlagOverrides[i] == Asm65.StatusFlags.DefaultValue)
                {
                    continue;
                }
                spf.StatusFlagOverrides.Add(i.ToString(), proj.StatusFlagOverrides[i].AsInt);
            }

            // Convert Comments to serializable form.
            spf.Comments = new Dictionary <string, string>();
            for (int i = 0; i < proj.Comments.Length; i++)
            {
                if (string.IsNullOrEmpty(proj.Comments[i]))
                {
                    continue;
                }
                spf.Comments.Add(i.ToString(), proj.Comments[i]);
            }

            // Convert multi-line comments to serializable form.
            spf.LongComments = new Dictionary <string, SerMultiLineComment>();
            foreach (KeyValuePair <int, MultiLineComment> kvp in proj.LongComments)
            {
                spf.LongComments.Add(kvp.Key.ToString(), new SerMultiLineComment(kvp.Value));
            }

            // Convert multi-line notes to serializable form.
            spf.Notes = new Dictionary <string, SerMultiLineComment>();
            foreach (KeyValuePair <int, MultiLineComment> kvp in proj.Notes)
            {
                spf.Notes.Add(kvp.Key.ToString(), new SerMultiLineComment(kvp.Value));
            }

            // Convert user-defined labels to serializable form.
            spf.UserLabels = new Dictionary <string, SerSymbol>();
            foreach (KeyValuePair <int, Symbol> kvp in proj.UserLabels)
            {
                spf.UserLabels.Add(kvp.Key.ToString(), new SerSymbol(kvp.Value));
            }

            // Convert operand and data item format descriptors to serializable form.
            spf.OperandFormats = new Dictionary <string, SerFormatDescriptor>();
            foreach (KeyValuePair <int, FormatDescriptor> kvp in proj.OperandFormats)
            {
                spf.OperandFormats.Add(kvp.Key.ToString(), new SerFormatDescriptor(kvp.Value));
            }

            spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);

            JavaScriptSerializer ser = new JavaScriptSerializer();
            string cereal            = ser.Serialize(spf);

            sb.Append(cereal);

            // Stick a linefeed at the end.  Makes git happier.
            sb.Append("\r\n");

            return(sb.ToString());
        }
Esempio n. 5
0
        /// <summary>
        /// Edits the data file, essentially putting the jump table entries into the
        /// "loaded" state.
        /// </summary>
        /// <remarks>
        /// We don't use ent.Segment.Relocs, as that is expected to be empty.
        /// </remarks>
        private bool RelocJumpTable(SegmentMapEntry ent, byte[] data, int bufOffset,
                                    ChangeSet cs)
        {
            const int ENTRY_LEN = 14;

            if (ent.Segment.Relocs.Count != 0)
            {
                Debug.WriteLine("WEIRD: jump table has reloc data?");
            }

            byte[] srcData = ent.Segment.GetConstData();
            Array.Copy(srcData, 0, data, bufOffset, srcData.Length);

            // For no documented reason, jump tables start with 8 zero bytes.
            for (int i = 0; i < 8; i++)
            {
                if (data[bufOffset + i] != 0)
                {
                    Debug.WriteLine("JumpTab: missing 8-byte header");
                    return(false);
                }
            }

            TypedRangeSet newSet  = new TypedRangeSet();
            TypedRangeSet undoSet = new TypedRangeSet();

            for (int i = 8; i + 4 <= ent.Segment.Length; i += ENTRY_LEN)
            {
                //int userId = RawData.GetWord(data, bufOffset + i, 2, false);
                int fileNum = RawData.GetWord(data, bufOffset + i + 2, 2, false);

                if (fileNum == 0)
                {
                    // A zero file number indicates end of table.
                    Debug.WriteLine("JumpTab: found fileNum=0 at offset " + i + ", len=" +
                                    ent.Segment.Length);
                    break;
                }
                else if (fileNum != 1)
                {
                    // External file, ignore entry.
                    Debug.WriteLine("JumpTab: ignoring entry with FileNum=" + fileNum);
                    continue;
                }
                else if (i + ENTRY_LEN > ent.Segment.Length)
                {
                    // Make sure the rest fits.
                    Debug.WriteLine("JumpTab: overran buffer");
                    return(false);
                }

                // Note: segment might end right after FileNum, so don't try to read further
                // until we've confirmed that FileNum != 0.

                int segNum = RawData.GetWord(data, bufOffset + i + 4, 2, false);
                int segOff = RawData.GetWord(data, bufOffset + i + 6, 4, false);

                if (segNum < 0 || segNum >= mSegmentMap.Count || mSegmentMap[segNum] == null)
                {
                    Debug.WriteLine("JumpTab: invalid SegNum=" + segNum);
                    return(false);
                }
                if (data[bufOffset + i + 10] != 0x22)
                {
                    Debug.WriteLine("JumpTab: did not find expected JSL at off=" + i);
                    return(false);
                }

                int addr      = mSegmentMap[segNum].Address + segOff;
                int jmlOffset = bufOffset + i + 10;
                data[jmlOffset]     = 0x5c; // JML
                data[jmlOffset + 1] = (byte)addr;
                data[jmlOffset + 2] = (byte)(addr >> 8);
                data[jmlOffset + 3] = (byte)(addr >> 16);
                //Debug.WriteLine("JumpTab: off=" + i + " -> " +
                //    mFormatter.FormatAddress(addr, true));

                // It seems to be fairly common for jump table entries to not be referenced
                // from the program, which can leave whole dynamic segments unreferenced.  Set
                // a code start tag on the JML instruction.
                undoSet.Add(jmlOffset, (int)CodeAnalysis.AnalyzerTag.None);
                newSet.Add(jmlOffset, (int)CodeAnalysis.AnalyzerTag.Code);
            }

            UndoableChange uc = UndoableChange.CreateAnalyzerTagChange(undoSet, newSet);

            cs.Add(uc);

            return(true);
        }