diff --git a/src/Core/Memory/ByteMemoryArea.cs b/src/Core/Memory/ByteMemoryArea.cs index a0d6789294..cf9ece0e14 100644 --- a/src/Core/Memory/ByteMemoryArea.cs +++ b/src/Core/Memory/ByteMemoryArea.cs @@ -20,12 +20,10 @@ using Reko.Core.Expressions; using Reko.Core.Lib; -using Reko.Core.Memory; using Reko.Core.Output; using Reko.Core.Types; using System; -using System.Diagnostics; -using System.IO; +using System.Buffers.Binary; namespace Reko.Core.Memory { @@ -336,15 +334,8 @@ public static bool TryReadBeInt64(byte[] image, long off, out long value) { if (off + 8 <= image.Length) { - value = - ((long)image[off] << 56) | - ((long)image[off + 1] << 48) | - ((long)image[off + 2] << 40) | - ((long)image[off + 3] << 32) | - ((long)image[off + 4] << 24) | - ((long)image[off + 5] << 16) | - ((long)image[off + 6] << 8) | - ((long)image[off + 7]); + var span = image.AsSpan((int) off, 8); + value = BinaryPrimitives.ReadInt64BigEndian(span); return true; } else @@ -358,15 +349,8 @@ public static bool TryReadBeUInt64(byte[] image, long off, out ulong value) { if (off + 8 <= image.Length) { - value = - ((ulong)image[off] << 56) | - ((ulong)image[off + 1] << 48) | - ((ulong)image[off + 2] << 40) | - ((ulong)image[off + 3] << 32) | - ((ulong)image[off + 4] << 24) | - ((ulong)image[off + 5] << 16) | - ((ulong)image[off + 6] << 8) | - ((ulong)image[off + 7]); + var span = image.AsSpan((int) off, 8); + value = BinaryPrimitives.ReadUInt64BigEndian(span); return true; } else @@ -375,31 +359,19 @@ public static bool TryReadBeUInt64(byte[] image, long off, out ulong value) return false; } } + public static long ReadBeInt64(byte[] image, long off) { - return ((long)image[off] << 56) | - ((long)image[off + 1] << 48) | - ((long)image[off + 2] << 40) | - ((long)image[off + 3] << 32) | - ((long)image[off + 4] << 24) | - ((long)image[off + 5] << 16) | - ((long)image[off + 6] << 8) | - ((long)image[off + 7]); + var span = image.AsSpan((int) off, 8); + return BinaryPrimitives.ReadInt64BigEndian(span); } public static bool TryReadLeInt64(byte[] image, long off, out long value) { if (off + 8 <= image.Length) { - value = - (long)image[off] | - ((long)image[off + 1] << 8) | - ((long)image[off + 2] << 16) | - ((long)image[off + 3] << 24) | - ((long)image[off + 4] << 32) | - ((long)image[off + 5] << 40) | - ((long)image[off + 6] << 48) | - ((long)image[off + 7] << 56); + var span = image.AsSpan((int) off, 8); + value = BinaryPrimitives.ReadInt64LittleEndian(span); return true; } else @@ -413,15 +385,8 @@ public static bool TryReadLeUInt64(byte[] image, long off, out ulong value) { if (off + 8 <= image.Length) { - value = - (ulong)image[off] | - ((ulong)image[off + 1] << 8) | - ((ulong)image[off + 2] << 16) | - ((ulong)image[off + 3] << 24) | - ((ulong)image[off + 4] << 32) | - ((ulong)image[off + 5] << 40) | - ((ulong)image[off + 6] << 48) | - ((ulong)image[off + 7] << 56); + var span = image.AsSpan((int) off, 8); + value = BinaryPrimitives.ReadUInt64LittleEndian(span); return true; } else @@ -430,17 +395,11 @@ public static bool TryReadLeUInt64(byte[] image, long off, out ulong value) return false; } } + public static long ReadLeInt64(byte[] image, long off) { - return - (long) image[off] | - ((long)image[off+1] << 8) | - ((long)image[off+2] << 16) | - ((long)image[off+3] << 24) | - ((long)image[off+4] << 32) | - ((long)image[off+5] << 40) | - ((long)image[off+6] << 48) | - ((long)image[off+7] << 56); + var span = image.AsSpan((int) off, 8); + return BinaryPrimitives.ReadInt64LittleEndian(span); } //$REVIEW: consider making this an extension method hosted in x86. @@ -458,23 +417,16 @@ public static bool TryReadLeReal80(byte[] image, long off, out Float80 value) public static int ReadBeInt32(byte[] abImage, long off) { - int u = - ((int)abImage[off] << 24) | - ((int)abImage[off + 1] << 16) | - ((int)abImage[off + 2] << 8) | - abImage[off + 3]; - return u; + var span = abImage.AsSpan((int) off, 4); + return BinaryPrimitives.ReadInt32BigEndian(span); } public static bool TryReadBeInt32(byte[] abImage, long off, out int value) { if (off <= abImage.Length - 4) { - value = - ((int)abImage[off] << 24) | - ((int)abImage[off + 1] << 16) | - ((int)abImage[off + 2] << 8) | - abImage[off + 3]; + var span = abImage.AsSpan((int) off, 4); + value = BinaryPrimitives.ReadInt32BigEndian(span); return true; } else @@ -488,10 +440,8 @@ public static bool TryReadLeInt32(byte [] abImage, uint off, out int value) { if (off <= abImage.Length - 4) { - value = abImage[off] | - ((int)abImage[off + 1] << 8) | - ((int)abImage[off + 2] << 16) | - ((int)abImage[off + 3] << 24); + var span = abImage.AsSpan((int) off, 4); + value = BinaryPrimitives.ReadInt32LittleEndian(span); return true; } else @@ -503,12 +453,10 @@ public static bool TryReadLeInt32(byte [] abImage, uint off, out int value) public static bool TryReadLeUInt32(byte[] abImage, long off, out uint value) { - if ((long) off <= abImage.Length - 4) + if (off <= abImage.Length - 4) { - value = abImage[off] | - ((uint)abImage[off + 1] << 8) | - ((uint)abImage[off + 2] << 16) | - ((uint)abImage[off + 3] << 24); + var span = abImage.AsSpan((int) off, 4); + value = BinaryPrimitives.ReadUInt32LittleEndian(span); return true; } else @@ -522,11 +470,8 @@ public static bool TryReadBeUInt32(byte[] abImage, long off, out uint value) { if ((long)off <= abImage.Length - 4) { - value = - ((uint)abImage[off] << 24) | - ((uint)abImage[off + 1] << 16) | - ((uint)abImage[off + 2] << 8) | - abImage[off + 3]; + var span = abImage.AsSpan((int) off, 4); + value = BinaryPrimitives.ReadUInt32BigEndian(span); return true; } else @@ -538,18 +483,17 @@ public static bool TryReadBeUInt32(byte[] abImage, long off, out uint value) public static int ReadLeInt32(byte[] abImage, long off) { - int u = abImage[off] | - ((int)abImage[off + 1] << 8) | - ((int)abImage[off + 2] << 16) | - ((int)abImage[off + 3] << 24); - return u; + var span = abImage.AsSpan((int) off, 4); + return BinaryPrimitives.ReadInt32LittleEndian(span); } + public static bool TryReadBeInt16(byte[] img, long offset, out short value) { if (offset <= img.Length - 2) { - value = (short)(img[offset] << 8 | img[offset + 1]); + var span = img.AsSpan((int) offset, 2); + value = BinaryPrimitives.ReadInt16BigEndian(span); return true; } else @@ -563,7 +507,8 @@ public static bool TryReadBeUInt16(byte[] img, long offset, out ushort value) { if (offset <= img.Length - 2) { - value = (ushort)(img[offset] << 8 | img[offset + 1]); + var span = img.AsSpan((int) offset, 2); + value = BinaryPrimitives.ReadUInt16BigEndian(span); return true; } else @@ -577,7 +522,8 @@ public static bool TryReadLeInt16(byte[] img, long offset, out short value) { if (offset <= img.Length - 2) { - value = (short)(img[offset] | img[offset + 1] << 8); + var span = img.AsSpan((int) offset, 2); + value = BinaryPrimitives.ReadInt16LittleEndian(span); return true; } else @@ -589,12 +535,14 @@ public static bool TryReadLeInt16(byte[] img, long offset, out short value) public static short ReadBeInt16(byte[] img, long offset) { - return (short)(img[offset] << 8 | img[offset + 1]); + var span = img.AsSpan((int) offset, 2); + return BinaryPrimitives.ReadInt16BigEndian(span); } public static short ReadLeInt16(byte[] abImage, long offset) { - return (short)(abImage[offset] + (abImage[offset + 1] << 8)); + var span = abImage.AsSpan((int) offset, 2); + return BinaryPrimitives.ReadInt16LittleEndian(span); } public static bool TryReadLeUInt16(byte[] abImage, long offset, out ushort us) diff --git a/src/UnitTests/Core/Memory/ByteMemoryAreaTests.cs b/src/UnitTests/Core/Memory/ByteMemoryAreaTests.cs index 19420e215e..150c5a840c 100644 --- a/src/UnitTests/Core/Memory/ByteMemoryAreaTests.cs +++ b/src/UnitTests/Core/Memory/ByteMemoryAreaTests.cs @@ -23,13 +23,16 @@ using Reko.Core.Expressions; using Reko.Core.Memory; using Reko.Core.Types; +using System; namespace Reko.UnitTests.Core.Memory { [TestFixture] public class ByteMemoryAreaTests { - [Test] + private static byte[] eightBytes = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 }; + + [Test] public void PriReadLiterals() { var bytes = new byte [] { @@ -87,5 +90,18 @@ public void TryReadLeNegativeInt() Assert.AreSame(PrimitiveType.Int32, c.DataType); Assert.AreEqual("-2", c.ToString()); } - } + + [Test] + public void Bma_ReadLeUInt64() + { + ulong value = ByteMemoryArea.ReadBeUInt64(eightBytes, 0); + Assert.AreEqual(0x123456789ABCDEF0, value); + } + + [Test] + public void Bma_ReadLeUInt64_Throws() + { + Assert.Throws(() => ByteMemoryArea.ReadBeUInt64(eightBytes, 4)); + } + } } \ No newline at end of file diff --git a/subjects/regression.log b/subjects/regression.log index c7669f5d2e..85883e460a 100644 --- a/subjects/regression.log +++ b/subjects/regression.log @@ -136,9 +136,9 @@ l0800_17AE: warning: Non-integral switch expression 00000004: warning: Expected sizes of arrays to have been determined by now 000000FF: error: Failed to write global variable g_t00FF. Index was outside the bounds of the array. - at Reko.Core.Memory.ByteMemoryArea.TryReadByte(Byte[] img, Int64 off, Byte& b) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 663 - at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Byte[] abImage, Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 256 - at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 208 + at Reko.Core.Memory.ByteMemoryArea.TryReadByte(Byte[] img, Int64 off, Byte& b) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 611 + at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Byte[] abImage, Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 254 + at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 206 at Reko.Core.Memory.ByteImageReader.TryReadLe(DataType dataType, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteImageReader.cs:line 222 at Reko.Core.Memory.LeImageReader.TryRead(PrimitiveType dataType, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\EndianImageReader.cs:line 245 at Reko.Core.ProcessorArchitecture.TryRead(EndianImageReader rdr, PrimitiveType dt, Constant& value) in d:\dev\uxmal\reko\master\src\Core\IProcessorArchitecture.cs:line 628 @@ -152,9 +152,9 @@ l0800_17AE: warning: Non-integral switch expression 00000004: warning: Expected sizes of arrays to have been determined by now 000000FF: error: Failed to write global variable g_t00FF. Index was outside the bounds of the array. - at Reko.Core.Memory.ByteMemoryArea.TryReadByte(Byte[] img, Int64 off, Byte& b) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 663 - at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Byte[] abImage, Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 256 - at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 208 + at Reko.Core.Memory.ByteMemoryArea.TryReadByte(Byte[] img, Int64 off, Byte& b) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 611 + at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Byte[] abImage, Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 254 + at Reko.Core.Memory.ByteMemoryArea.TryReadLe(Int64 imageOffset, DataType type, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 206 at Reko.Core.Memory.ByteImageReader.TryReadLe(DataType dataType, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteImageReader.cs:line 222 at Reko.Core.Memory.LeImageReader.TryRead(PrimitiveType dataType, Constant& c) in d:\dev\uxmal\reko\master\src\Core\Memory\EndianImageReader.cs:line 245 at Reko.Core.ProcessorArchitecture.TryRead(EndianImageReader rdr, PrimitiveType dt, Constant& value) in d:\dev\uxmal\reko\master\src\Core\IProcessorArchitecture.cs:line 628 @@ -1134,7 +1134,7 @@ fn00008FF2: error: An error occurred while rewriting procedure to high-level lan at Reko.Structure.StructureAnalysis.VirtualizeReturn(Region n) in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 310 at Reko.Structure.StructureAnalysis.ProcessUnresolvedRegions() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 283 at Reko.Structure.StructureAnalysis.Execute() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 170 - at Reko.Structure.StructureAnalysis.Structure() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 80 + at Reko.Structure.StructureAnalysis.Structure() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 95 at Reko.Decompiler.StructureProgram() in d:\dev\uxmal\reko\master\src\Decompiler\Decompiler.cs:line 551 l00009F1C: warning: Non-integral switch expression fn0000ACB0: error: Removing edge (l0000AD24, l0000B67C) caused loss of some code blocks @@ -1191,7 +1191,7 @@ Error: An error occurred while writing assembly language output. at Reko.Core.Memory.ByteImageReader..ctor(ByteMemoryArea mem, Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteImageReader.cs:line 65 at Reko.Core.Memory.EndianByteImageReader..ctor(ByteMemoryArea img, Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\Memory\EndianImageReader.cs:line 71 at Reko.Core.Memory.BeImageReader..ctor(ByteMemoryArea image, Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\Memory\EndianImageReader.cs:line 256 - at Reko.Core.Memory.ByteMemoryArea.CreateBeReader(Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 79 + at Reko.Core.Memory.ByteMemoryArea.CreateBeReader(Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\Memory\ByteMemoryArea.cs:line 77 at Reko.Core.EndianServices.BeServices.CreateImageReader(MemoryArea mem, Address addr, Int64 cUnits) in d:\dev\uxmal\reko\master\src\Core\EndianServices.cs:line 293 at Reko.Core.ProcessorArchitecture.CreateImageReader(MemoryArea mem, Address addr, Int64 cbUnits) in d:\dev\uxmal\reko\master\src\Core\IProcessorArchitecture.cs:line 622 at Reko.Core.Output.Dumper.DumpData(IProcessorArchitecture arch, MemoryArea mem, Address address, Int64 cUnits, Formatter stm) in d:\dev\uxmal\reko\master\src\Core\Output\Dumper.cs:line 181 @@ -1419,7 +1419,7 @@ fn0001B2AC: error: An error occurred while rewriting procedure to high-level lan Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') at Reko.Structure.CompoundConditionCoalescer.MaybeCoalesce(Block block) in d:\dev\uxmal\reko\master\src\Decompiler\Structure\CompoundConditionCoalescer.cs:line 95 at Reko.Structure.CompoundConditionCoalescer.Transform() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\CompoundConditionCoalescer.cs:line 62 - at Reko.Structure.StructureAnalysis.Structure() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 78 + at Reko.Structure.StructureAnalysis.Structure() in d:\dev\uxmal\reko\master\src\Decompiler\Structure\StructureAnalysis.cs:line 95 at Reko.Decompiler.StructureProgram() in d:\dev\uxmal\reko\master\src\Decompiler\Decompiler.cs:line 551 fn0001B2CC: warning: Structure analysis stopped making progress, quitting. Please report this issue at https://github.com/uxmal/reko 000171BC: warning: Expected sizes of arrays to have been determined by now @@ -1802,7 +1802,7 @@ Evaluating d:\dev\uxmal\reko\master\subjects\scripting\segmented.py 00012F40: warning: Unable to determine format string for call to 'fprintf'. 00011F6C: error: An error occurred while processing the statement word32 sp_37 = fp + 0xFFFFFF90<32> - (CONVERT(strlen(i0_25) + strlen(o1), size_t, size_t) + 9<32> & 0xFFFFFFF8<32>). Specified argument was out of the range of valid values. (Parameter 'bitSize') - at Reko.Core.Types.PrimitiveType.CreateWord(Int32 bitSize) in d:\dev\uxmal\reko\master\src\Core\Types\PrimitiveType.cs:line 141 + at Reko.Core.Types.PrimitiveType.CreateWord(Int32 bitSize) in d:\dev\uxmal\reko\master\src\Core\Types\PrimitiveType.cs:line 127 at Reko.Core.Expressions.ExpressionTypeAscenderBase.VisitBinaryExpression(BinaryExpression binExp) in d:\dev\uxmal\reko\master\src\Core\Expressions\ExpressionTypeAscenderBase.cs:line 131 at Reko.Core.Expressions.BinaryExpression.Accept[T](ExpressionVisitor`1 v) in d:\dev\uxmal\reko\master\src\Core\Expressions\BinaryExpression.cs:line 57 at Reko.Core.Expressions.ExpressionTypeAscenderBase.VisitBinaryExpression(BinaryExpression binExp) in d:\dev\uxmal\reko\master\src\Core\Expressions\ExpressionTypeAscenderBase.cs:line 100 @@ -2522,4 +2522,4 @@ varargs_test.exe: warning: Win32 X86-64 main procedure finder not implemented ye === PE\x86\VCExeSample\VCExeSample Signature of 'Microsoft Visual C++ 8' detected. -Decompiled 91 binaries in 69.55 seconds. +Decompiled 91 binaries in 71.04 seconds.