Exemple #1
0
        public void A5Relocator_Skip_Repeat()
        {
            Given_Relocator();
            var w = new BeImageWriter(mem.Bytes, 0);

            w.WriteByte(0x00);  // Skip 2 halfwords.
            w.WriteByte(0x02);
            w.WriteByte(0x03);  // Repeat 3

            w = new BeImageWriter(mem.Bytes, 1024);
            w.WriteBeUInt32(0xFFFF0000u);
            w.WriteBeUInt32(0x00010000);
            w.WriteBeUInt32(0x00010004);
            w.WriteBeUInt32(0x00010008);
            w.WriteBeUInt32(0xFFFF0000u);

            relocator.Relocate();

            var r = mem.CreateBeReader(1024);

            Assert.AreEqual(0xFFFF0000u, r.ReadBeUInt32());
            Assert.AreEqual(0x00110800u, r.ReadBeUInt32());
            Assert.AreEqual(0x00110804u, r.ReadBeUInt32());
            Assert.AreEqual(0x00110808u, r.ReadBeUInt32());
            Assert.AreEqual(0xFFFF0000u, r.ReadBeUInt32());
        }
Exemple #2
0
        private byte[] FlattenSymbolTable()
        {
            var syms = new BeImageWriter();

            foreach (var sym in symbols)
            {
                syms.WriteBeUInt32(sym.st_name);
                syms.WriteBeUInt32(sym.st_value);
                syms.WriteBeUInt32(sym.st_size);
                syms.WriteByte(sym.st_info);
                syms.WriteByte(sym.st_other);
                syms.WriteBeUInt16(sym.st_shndx);
            }
            return(syms.ToArray());
        }
Exemple #3
0
        /// <summary>
        /// Builds the MacOS A5World, based on the contents of the jump table in CODE#0.
        /// </summary>
        /// <param name="jt"></param>
        /// <param name="addr"></param>
        /// <param name="codeSegs"></param>
        /// <returns></returns>
        public ImageSegment LoadA5World(
            JumpTable jt,
            Address addr,
            Dictionary <int, ImageSegment> codeSegs,
            SortedList <Address, ImageSymbol> symbols)
        {
            var size = jt.BelowA5Size + jt.AboveA5Size;
            var mem  = new MemoryArea(addr, new byte[size]);
            var w    = new BeImageWriter(mem, jt.BelowA5Size + jt.JumpTableOffset);
            int i    = 0;

            foreach (var entry in jt.Entries)
            {
                w.WriteBeUInt16(entry.RoutineOffsetFromSegmentStart);
                int iSeg      = (ushort)entry.Instruction;
                var targetSeg = codeSegs[iSeg];
                var addrDst   = targetSeg.Address + entry.RoutineOffsetFromSegmentStart;
                if (!symbols.ContainsKey(addrDst))
                {
                    symbols.Add(addrDst, ImageSymbol.Procedure(arch, addrDst));
                }
                w.WriteBeUInt16(0x4EF9);            // jmp (xxxxxxxxx).L
                w.WriteBeUInt32(addrDst.ToUInt32());
                ++i;
            }
            return(new ImageSegment("A5World", mem, AccessMode.ReadWriteExecute));
        }
Exemple #4
0
        private static void WriteString(string s, BeImageWriter w)
        {
            if (s.Length <= 0)
            {
                w.WriteBeUInt32(0);
                return;
            }
            byte[] ab        = enc.GetBytes(s);
            int    padLength = (ab.Length + 3) & ~3;

            w.WriteBeUInt32((uint)padLength / 4);
            w.WriteBytes(ab);
            int cPad = padLength - ab.Length;

            while (--cPad >= 0)
            {
                w.WriteByte(0);
            }
        }
Exemple #5
0
 private void Given_BE32_GOT(params uint[] aPointers)
 {
     var writer = new BeImageWriter();
     foreach (var ptr in aPointers)
     {
         writer.WriteBeUInt32(ptr);
     }
     var mem = new MemoryArea(Address.Ptr32(0x10000000), writer.ToArray());
     program.SegmentMap.AddSegment(mem,  ".got", AccessMode.ReadWriteExecute);
     arch.Setup(a => a.CreateImageReader(
         It.IsNotNull<MemoryArea>(),
         mem.BaseAddress))
         .Returns(new BeImageReader(mem, 0));
 }
Exemple #6
0
        public void A5Relocator_One()
        {
            Given_Relocator();
            var w = new BeImageWriter(mem.Bytes, 0);

            w.WriteByte(0x80);  // Skip 0.
            w.WriteByte(0x00);

            w = new BeImageWriter(mem.Bytes, 1024);
            w.WriteBeUInt32(0x00123400);

            relocator.Relocate();

            var r          = mem.CreateBeReader(1024);
            var uRelocated = r.ReadBeUInt32();

            Assert.AreEqual(0x00223C00u, uRelocated);
        }
Exemple #7
0
        private void Given_Code(params uint [] uInstrs)
        {
            var writer = new BeImageWriter();

            foreach (uint uInstr in uInstrs)
            {
                writer.WriteBeUInt32(uInstr);
            }
            var mem     = new ByteMemoryArea(Address.Ptr64(0x0010_0000), writer.ToArray());
            var seg     = new ImageSegment("code", mem, AccessMode.ReadWriteExecute);
            var segmap  = new SegmentMap(mem.BaseAddress, seg);
            var program = new Program(segmap, arch, new DefaultPlatform(sc, arch));

            var envEmu = new DefaultPlatformEmulator();

            emu = (Reko.Arch.PowerPC.PowerPcEmulator)arch.CreateEmulator(segmap, envEmu);
            emu.InstructionPointer = program.ImageMap.BaseAddress;
            emu.ExceptionRaised   += (sender, e) => { throw e.Exception; };
        }
Exemple #8
0
        public void MacOS_ResolveIndirectCall()
        {
            var macOS = new MacOSClassic(null, new M68kArchitecture("m68k"));
            var a5    = new Identifier(Registers.a5.Name, Registers.a5.DataType, Registers.a5);

            var a5world = new MemoryArea(Address.Ptr32(0x00100000), new byte[0x0300]);

            macOS.A5World  = new ImageSegment("A5World", a5world, AccessMode.ReadWrite);
            macOS.A5Offset = 0x0100u;
            const int  jumpTableOffset = 0x0032;
            const uint uAddrDirect     = 0x00123400u;
            var        w = new BeImageWriter(a5world, macOS.A5Offset + jumpTableOffset);

            w.WriteBeUInt16(0x4EF9);        // jmp... (not really necessary for the test but hey....);
            w.WriteBeUInt32(uAddrDirect);

            var m     = new RtlEmitter(null);
            var instr = new RtlCall(m.IAdd(a5, jumpTableOffset), 4, RtlClass.Call);
            var addr  = macOS.ResolveIndirectCall(instr);

            Assert.AreEqual(uAddrDirect, addr.ToUInt32());
        }
Exemple #9
0
        protected void BuildObjectFile32()
        {
            // Add symbol table
            if (symbols.Count > 0)
            {
                Given_Section(".symtab", SectionHeaderType.SHT_SYMTAB, ElfLoader.SHF_ALLOC, FlattenSymbolTable());
                var os = objectSections[objectSections.Count - 1];
                os.ElementSize = Elf32_Sym.Size;
                os.Link        = (ushort)objectSections.Count;
                Given_Section(".strtab", SectionHeaderType.SHT_STRTAB, ElfLoader.SHF_ALLOC, symbolStringtab.ToArray());
            }

            var bin = new BeImageWriter();

            bin.WriteByte(0x7F);
            bin.WriteBytes(new byte[] { 0x45, 0x4C, 0x46 });
            bin.WriteByte(1);     // 32-bit
            bin.WriteByte(2);     // big-endian
            bin.WriteByte(1);     // ELF version
            bin.WriteByte(0);     // OS ABI
            bin.WriteByte(0);     // OS version
            bin.WriteBytes(0, 7); // pad

            // ELF header

            bin.WriteBeUInt16(1);                            // relocatable
            bin.WriteBeUInt16((ushort)ElfMachine.EM_SPARC);
            bin.WriteBeUInt32(1);                            // version
            bin.WriteBeUInt32(0);                            // entry point (none in reloc file)
            bin.WriteBeUInt32(0);                            // program segment table offset (none in reloc file)
            bin.WriteBeUInt32((uint)bin.Position + 20);      // point to section table.

            bin.WriteBeUInt32(0);                            // e_flags;
            bin.WriteBeUInt16(0);                            // e_ehsize;
            bin.WriteBeUInt16((ushort)Elf32_PHdr.Size);      // e_phentsize;
            bin.WriteBeUInt16((ushort)progHeaders.Count);    // e_phnum;
            bin.WriteBeUInt16(0);                            // e_shentsize;
            bin.WriteBeUInt16((ushort)objectSections.Count); // e_shnum;
            bin.WriteBeUInt16(1);                            // e_shstrndx;

            // Build string table.

            var strtab      = new MemoryStream();
            var mpOsToiName = new Dictionary <ObjectSection, int>();

            foreach (var os in this.objectSections)
            {
                mpOsToiName[os] = (int)strtab.Position;
                var bytes = Encoding.ASCII.GetBytes(os.Name);
                strtab.Write(bytes, 0, bytes.Length);
                strtab.WriteByte(0);
            }

            // Reserve space for program header table and
            // section table.
            var iProgHdrTable = (uint)bin.Position;
            var iShTable      = (uint)bin.Position + (uint)(progHeaders.Count * Elf32_PHdr.Size);
            var iStrTable     = iShTable + (uint)(40 * objectSections.Count);

            // Write string table
            var aStrtable = strtab.ToArray();

            objectSections[1].Content = aStrtable;
            var iContent = iStrTable;

            // Place remaining sections.
            foreach (var section in objectSections.Skip(1))
            {
                section.Offset = iContent;
                iContent       = Align((uint)(iContent + section.Content.Length));
            }

            // Write the program header table
            foreach (var ph in this.progHeaders)
            {
                bin.WriteBeUInt32((uint)ph.Type);
                bin.WriteBeUInt32(ph.Offset);
                bin.WriteBeUInt32(ph.VirtualAddress);
                bin.WriteBeUInt32(0);
                bin.WriteBeUInt32((uint)ph.Content.Length);
                bin.WriteBeUInt32(ph.AllocateSize);
                bin.WriteBeUInt32(ph.Flags);
                bin.WriteBeUInt32(ph.Alignment);
            }

            // Write the section table.
            foreach (var os in this.objectSections)
            {
                bin.WriteBeUInt32((uint)mpOsToiName[os]);
                bin.WriteBeUInt32((uint)os.Type);
                bin.WriteBeUInt32(os.Flags);
                bin.WriteBeUInt32(0);

                bin.WriteBeUInt32(os.Offset);
                bin.WriteBeUInt32(os.Content != null ? (uint)os.Content.Length : 0u);
                bin.WriteBeUInt32(os.Link);
                bin.WriteBeUInt32(0);

                bin.WriteBeUInt32(0);
                bin.WriteBeUInt32(os.ElementSize);
            }

            // write the non-null sections.
            foreach (var section in objectSections.Skip(1))
            {
                bin.WriteBytes(section.Content);
                Align(bin);
            }
            this.rawBytes = bin.ToArray();
        }
Exemple #10
0
        public void Relocate()
        {
            var  memA5          = (ByteMemoryArea)platform.A5World.MemoryArea;
            var  a5belowWriter  = new BeImageWriter(memA5, 0);
            var  a5belowReader  = new BeImageReader(memA5, 0);
            uint a5globalOffset = platform.A5Offset - a5dbelow;

            var a5WorldAddress = (UInt32)((platform.A5World.Address.Offset + platform.A5Offset) & 0xFFFFFFFF);

            // set Repeat count = 1, reset after each completed copy cycle
            // byte token lower 4 bits number of words to copy from compressed data
            // byte token upper 4 bits number of words to skip in global application data space
            // if either value is 0 then get run length value which is in bytes.
            // if the new run length value for copy is 0 then it's the end of compression data.

            for (;;)
            {
                int a5repeat = 1;
                // Skip is number of 16-bit words to skip
                uint a5globalSkip = a5dr.ReadByte();
                if (a5globalSkip == 0)
                {
                    a5globalSkip = a5dr.ReadByte();
                    if (a5globalSkip == 0)
                    {
                        break;
                    }
                    if (a5globalSkip > 0x7F)
                    {
                        a5globalSkip = ((a5globalSkip & 0x7F) << 8) + a5dr.ReadByte();
                        a5globalSkip = (a5globalSkip << 16) + a5dr.ReadBeUInt16();
                    }
                    else
                    {
                        a5repeat = ResourceFork.GetRunLengthValue(a5dr, ref a5repeat);
                        //$BUG: a5repeat could return the value 0. The do-while below will
                        // decrement a5repeat before testing. This will lead to an effective
                        // repeat count of 2^32; likely not wanted.
                    }
                }
                else
                {
                    if ((a5globalSkip & 0x80) == 0x80)
                    {
                        a5globalSkip = ((a5globalSkip & 0x7F) << 8) + a5dr.ReadByte();
                    }
                }
                a5globalSkip = a5globalSkip * 2;
                do
                {
                    a5globalOffset += a5globalSkip;
                    a5belowReader.Seek(a5globalOffset, SeekOrigin.Begin);
                    uint a5ptrOffset = a5belowReader.ReadBeUInt32();
                    a5belowWriter.Position = (int)a5globalOffset;

                    // write relocated A5World pointers to absolute address in A5World segment
                    // Possible register/mark as Global pointer references to strings

                    a5belowWriter.WriteBeUInt32((a5WorldAddress + a5ptrOffset) & 0xFFFFFFFF);
                    --a5repeat;
                } while (a5repeat > 0);
            }
        }