예제 #1
0
        public void AddResourcesToImageMap(
            Address addrLoad,
            MemoryArea mem,
            SegmentMap segmentMap,
            List <ImageSymbol> entryPoints,
            SortedList <Address, ImageSymbol> symbols)
        {
            JumpTable jt       = null;
            var       codeSegs = new Dictionary <int, ImageSegment>();

            foreach (ResourceType type in ResourceTypes)
            {
                foreach (ResourceReference rsrc in type.References)
                {
                    uint uSegOffset  = rsrc.DataOffset + rsrcDataOff;
                    int  segmentSize = mem.ReadBeInt32(uSegOffset);

                    // Skip the size longword at the beginning of the segment, and an extra 4
                    // if it is a code segement other than CODE#0.
                    int bytesToSkip = 4;
                    if (type.Name == "CODE" && rsrc.ResourceID != 0)
                    {
                        bytesToSkip += 4;
                    }
                    var abSegment = new byte[segmentSize];
                    Array.Copy(mem.Bytes, uSegOffset + bytesToSkip, abSegment, 0, segmentSize);

                    Address addrSegment = addrLoad + uSegOffset + bytesToSkip;    //$TODO pad to 16-byte boundary?
                    var     memSeg      = new MemoryArea(addrSegment, abSegment);
                    var     segment     = segmentMap.AddSegment(new ImageSegment(
                                                                    ResourceDescriptiveName(type, rsrc),
                                                                    memSeg,
                                                                    AccessMode.Read));
                    if (type.Name == "CODE")
                    {
                        if (rsrc.ResourceID == 0)
                        {
                            jt = ProcessJumpTable(memSeg, symbols);
                        }
                        else
                        {
                            codeSegs.Add(rsrc.ResourceID, segment);
                            var macsBug   = new MacsBugSymbolScanner(arch, segment.MemoryArea);
                            var mbSymbols = macsBug.ScanForSymbols();
                            foreach (var symbol in mbSymbols)
                            {
                                symbols[symbol.Address] = symbol;
                            }
                        }
                    }
                }
            }

            // We have found a jump table, so we allocate an A5World.
            if (jt != null)
            {
                // Find an address beyond all known segments.
                var addr    = segmentMap.Segments.Values.Max(s => s.Address + s.Size).Align(0x10);
                var a5world = LoadA5World(jt, addr, codeSegs, symbols);
                platform.A5World  = a5world;
                platform.A5Offset = jt.BelowA5Size;
                segmentMap.AddSegment(a5world);

                // Find first (and only!) segment containing the name %A5Init.
                var a5dataSegment = segmentMap.Segments.Values.SingleOrDefault(SegmentNamedA5Init);
                if (a5dataSegment == null)
                {
                    return;
                }

                // Get an image reader to the start of the data.
                var a5dr = GetA5InitImageReader(a5dataSegment);
                if (a5dr == null)
                {
                    return;
                }

                var a5hdroffset = a5dr.Offset;
                var a5dbelow    = a5dr.ReadBeUInt32();
                var a5dbankSize = a5dr.ReadBeUInt32();
                var a5doffset   = a5dr.ReadBeUInt32();
                var a5dreloc    = a5dr.ReadBeUInt32();
                var a5dhdrend   = a5dr.ReadBeUInt32();
                if (a5dbankSize != 0x00010000)
                {
                    // bank size not supported for compressed global data
                    return;
                }
                A5Expand(a5dr, a5dbelow);
                a5dr.Seek(a5hdroffset + a5dreloc, System.IO.SeekOrigin.Begin);
                var relocator = new A5Relocator(platform, a5dr, a5dbelow);
                relocator.Relocate();
            }
        }
예제 #2
0
        // References: Inside Macintosh: Processes (Segment Manager)
        public void AddResourcesToImageMap(
            Address addrLoad,
            ByteMemoryArea mem,
            Program program)
        {
            JumpTable?jt       = null;
            var       codeSegs = new Dictionary <int, ImageSegment>();

            foreach (ResourceType type in ResourceTypes)
            {
                foreach (ResourceReference rsrc in type.References)
                {
                    uint uSegOffset  = rsrc.DataOffset + rsrcDataOff;
                    int  segmentSize = mem.ReadBeInt32(uSegOffset);

                    // Skip the size longword at the beginning of the segment, and an extra 4
                    // if it is a code segement other than CODE#0.
                    int bytesToSkip = 4;
                    if (type.Name == "CODE" && rsrc.ResourceID != 0)
                    {
                        bytesToSkip += 4;
                    }
                    var abSegment = new byte[segmentSize];
                    Array.Copy(mem.Bytes, uSegOffset + bytesToSkip, abSegment, 0, segmentSize);

                    var     uAddr       = (uSegOffset + bytesToSkip) & ~1u;
                    Address addrSegment = addrLoad + uAddr;    //$TODO pad to 16-byte boundary?
                    var     memSeg      = new ByteMemoryArea(addrSegment, abSegment);
                    var     segment     = program.SegmentMap.AddSegment(new ImageSegment(
                                                                            ResourceDescriptiveName(type, rsrc),
                                                                            memSeg,
                                                                            AccessMode.Read));
                    if (type.Name == "CODE")
                    {
                        if (rsrc.ResourceID == 0)
                        {
                            jt = ProcessJumpTable(memSeg, program.ImageSymbols);
                        }
                        else
                        {
                            AddCodeSegment(program.ImageSymbols, codeSegs, rsrc, memSeg, segment);
                        }
                    }
                    if (type.Name == "INIT")
                    {
                        AddCodeSegment(program.ImageSymbols, codeSegs, rsrc, memSeg, segment);
                        var symInit = ImageSymbol.Procedure(arch, segment.Address, $"Init_{segment.Address}");
                        program.EntryPoints.Add(symInit.Address, symInit);
                    }
                    else if (type.Name == "cdev")
                    {
                        AddCodeSegment(program.ImageSymbols, codeSegs, rsrc, memSeg, segment);
                        var symInit = ImageSymbol.Procedure(arch, segment.Address, $"CDev_{segment.Address}");
                        program.EntryPoints.Add(symInit.Address, symInit);
                    }
                    else if (type.Name == "DRVR")
                    {
                        AddCodeSegment(program.ImageSymbols, codeSegs, rsrc, memSeg, segment);
                        var symInit = ImageSymbol.Procedure(arch, segment.Address, $"Drvr_{segment.Address}");
                        program.EntryPoints.Add(symInit.Address, symInit);
                        AddDriverMethods(program.ImageSymbols, memSeg);
                    }
                }
            }

            // We have found a jump table, so we allocate an A5World.
            if (jt != null)
            {
                // Find an address beyond all known segments.
                var addr    = program.SegmentMap.Segments.Values.Max(s => s.Address + s.Size).Align(0x10);
                var a5world = LoadA5World(jt, addr, codeSegs, program.ImageSymbols);
                platform.A5World  = a5world;
                platform.A5Offset = jt.BelowA5Size;
                program.SegmentMap.AddSegment(a5world);

                // Find first (and only!) segment containing the name %A5Init.
                var a5dataSegment = program.SegmentMap.Segments.Values.SingleOrDefault(SegmentNamedA5Init);
                if (a5dataSegment == null)
                {
                    return;
                }

                // Get an image reader to the start of the data.
                var a5dr = GetA5InitImageReader(a5dataSegment);
                if (a5dr == null)
                {
                    return;
                }

                var a5hdroffset = a5dr.Offset;
                var a5dbelow    = a5dr.ReadBeUInt32();
                var a5dbankSize = a5dr.ReadBeUInt32();
                var a5doffset   = a5dr.ReadBeUInt32();
                var a5dreloc    = a5dr.ReadBeUInt32();
                var a5dhdrend   = a5dr.ReadBeUInt32();
                if (a5dbankSize != 0x00010000)
                {
                    // bank size not supported for compressed global data
                    return;
                }
                A5Expand(a5dr, a5dbelow);
                a5dr.Seek(a5hdroffset + a5dreloc, System.IO.SeekOrigin.Begin);
                var relocator = new A5Relocator(platform, a5dr, a5dbelow);
                relocator.Relocate();
            }
        }