Ejemplo n.º 1
0
        /// <summary>
        /// Adds one or more entries to the address map for the specified segment.
        /// </summary>
        private static void AddAddressEntries(DisasmProject proj, SegmentMapEntry ent,
                                              int bufOffset, ChangeSet cs)
        {
            int addr   = ent.Address;
            int segRem = ent.Segment.Length;

            while (true)
            {
                // Generate an ORG directive.
                int            origAddr = proj.AddrMap.Get(bufOffset);
                UndoableChange uc       = UndoableChange.CreateAddressChange(bufOffset,
                                                                             origAddr, addr);
                cs.Add(uc);

                // Compare amount of space in this bank to amount left in segment.
                int bankRem = 0x00010000 - (addr & 0xffff);
                if (bankRem > segRem)
                {
                    // All done, bail.
                    break;
                }

                // Advance to start of next bank.
                addr += bankRem;
                Debug.Assert((addr & 0x0000ffff) == 0);
                bufOffset += bankRem;
                segRem    -= bankRem;
                Debug.WriteLine("Adding additional ORG at " + addr);
            }
        }
Ejemplo n.º 2
0
        private void AddHeaderComment(DisasmProject proj, ChangeSet cs)
        {
            // Add header comment.
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(string.Format(Res.Strings.DEFAULT_HEADER_COMMENT_FMT,
                                        App.ProgramVersion));
            sb.AppendLine();
            foreach (SegmentMapEntry ent in mSegmentMap)
            {
                if (ent == null)
                {
                    continue;
                }
                string segCmt = string.Format(Res.Strings.OMF_SEG_HDR_COMMENT_FMT,
                                              ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.SegName,
                                              mFormatter.FormatAddress(ent.Address, true), ent.Segment.Length);
                sb.AppendLine(segCmt);
            }

            UndoableChange uc = UndoableChange.CreateLongCommentChange(
                LineListGen.Line.HEADER_COMMENT_OFFSET,
                null, new MultiLineComment(sb.ToString()));

            cs.Add(uc);
        }
Ejemplo n.º 3
0
    public static void AddAction(UndoableChange action)
    {
        redoStack.Clear();

        undoStack.Push(action);
        Debug.Log("" + undoStack.Count);
    }
Ejemplo n.º 4
0
 public static void AddBoxAction(UndoableChange action)
 {
     undoBoxes.Push(action);
 }
Ejemplo 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);
        }
Ejemplo n.º 6
0
        private bool GenerateDataAndProject()
        {
            // Sum up the segment lengths to get the total project size.
            int totalLen = 0;

            foreach (SegmentMapEntry ent in mSegmentMap)
            {
                if (ent == null)
                {
                    continue;
                }
                totalLen += ent.Segment.Length;
            }
            Debug.WriteLine("Total length of loaded binary is " + totalLen);

            byte[] data = new byte[totalLen];

            // Create the project object.
            DisasmProject proj = new DisasmProject();

            proj.Initialize(data.Length);

            // Try to get the Apple IIgs system definition.  This is fragile, because it
            // relies on the name in the JSON file, but it's optional.  (If the default CPU
            // type stops being 65816, we should be sure to set that here.)
            try {
                // TODO(maybe): encapsulate this somewhere else
                string       sysDefsPath = RuntimeDataAccess.GetPathName("SystemDefs.json");
                SystemDefSet sds         = SystemDefSet.ReadFile(sysDefsPath);
                SystemDef    sd          = sds.FindEntryByName(IIGS_SYSTEM_DEF);
                if (sd != null)
                {
                    proj.ApplySystemDef(sd);
                }
                else
                {
                    Debug.WriteLine("Unable to find Apple IIgs system definition");
                }
            } catch (Exception) {
                // never mind
                Debug.WriteLine("Failed to apply Apple IIgs system definition");
            }

            ChangeSet cs = new ChangeSet(mSegmentMap.Count * 2);

            AddHeaderComment(proj, cs);
            UndoableChange uc;

            // Load the segments, and add entries to the project.
            int bufOffset = 0;

            foreach (SegmentMapEntry ent in mSegmentMap)
            {
                if (ent == null)
                {
                    continue;
                }

                if (ent.Segment.Kind == OmfSegment.SegmentKind.JumpTable)
                {
                    if (!RelocJumpTable(ent, data, bufOffset, cs))
                    {
                        // Could treat this as non-fatal, but it really ought to work.
                        Debug.WriteLine("Jump Table reloc failed");
                        return(false);
                    }
                }
                else
                {
                    // Perform relocation.
                    if (!RelocSegment(ent, data, bufOffset))
                    {
                        return(false);
                    }
                }

                // Add one or more address entries.  (Normally one, but data segments
                // can straddle multiple pages.)
                AddAddressEntries(proj, ent, bufOffset, cs);

                if ((mFlags & Flags.AddNotes) != 0)
                {
                    // Add a comment identifying the segment and its attributes.
                    string segCmt = string.Format(Res.Strings.OMF_SEG_COMMENT_FMT,
                                                  ent.Segment.SegNum, ent.Segment.Kind, ent.Segment.Attrs, ent.Segment.SegName);
                    uc = UndoableChange.CreateLongCommentChange(bufOffset, null,
                                                                new MultiLineComment(segCmt));
                    cs.Add(uc);

                    // Add a note identifying the segment.
                    string segNote = string.Format(Res.Strings.OMF_SEG_NOTE_FMT,
                                                   ent.Segment.SegNum, mFormatter.FormatAddress(ent.Address, true),
                                                   ent.Segment.SegName);
                    uc = UndoableChange.CreateNoteChange(bufOffset, null,
                                                         new MultiLineComment(segNote));
                    cs.Add(uc);
                }

                bufOffset += ent.Segment.Length;
            }

            proj.PrepForNew(data, "new_proj");
            foreach (KeyValuePair <int, DisasmProject.RelocData> kvp in mRelocData)
            {
                proj.RelocList.Add(kvp.Key, kvp.Value);
            }

            // Enable "use reloc" in the analysis parameters.
            ProjectProperties newProps = new ProjectProperties(proj.ProjectProps);

            newProps.AnalysisParams.UseRelocData = true;
            uc = UndoableChange.CreateProjectPropertiesChange(proj.ProjectProps, newProps);
            cs.Add(uc);

            // TODO(someday): by default we apply a code start tag to offset 0 of the first
            // segment.  The placement should take the segment's ENTRY into account.

            Debug.WriteLine("Applying " + cs.Count + " changes");
            proj.ApplyChanges(cs, false, out _);

            mLoadedData = data;
            mNewProject = proj;
            return(true);
        }