3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
29 using System
.Reflection
;
30 using System
.Runtime
.InteropServices
;
32 namespace Mono
.PEToolkit
{
34 public sealed class PEUtils
{
41 unsafe internal static string GetString (sbyte* data
, int start
, int len
, Encoding encoding
)
43 byte[] data_array
= new byte[len
-start
];
45 for (int i
=start
; i
<len
; i
++)
46 data_array
[i
-start
] = (byte)*data
++;
48 return encoding
.GetString (data_array
);
52 /// Reads structure from the input stream preserving its endianess.
54 /// <param name="reader"></param>
55 /// <param name="pStruct"></param>
56 /// <param name="len"></param>
57 unsafe internal static void ReadStruct(BinaryReader reader
, void* pStruct
, int len
)
59 byte* p
= (byte*) pStruct
;
61 if (System
.BitConverter
.IsLittleEndian
) {
62 // On a little-endian machine read data in 64-bit chunks,
63 // this won't work on big-endian machine because
64 // BinaryReader APIs are little-endian while
65 // memory writes are platform-native.
66 // This seems faster than ReadBytes/Copy method
67 // in the "else" clause, especially if used often
68 // (no extra memory allocation for byte[]?).
72 for (int i
= whole
; --i
>= 0;) {
73 long qw
= reader
.ReadInt64();
74 Marshal
.WriteInt64((IntPtr
) p
, qw
);
77 for (int i
= rem
; --i
>= 0;) {
78 *p
++ = (byte) reader
.ReadByte();
81 byte [] buff
= reader
.ReadBytes(len
);
82 Marshal
.Copy(buff
, 0, (IntPtr
) p
, len
);
87 /// Reads structure from the input stream
88 /// changing its endianess if required
89 /// (if running on big-endian hardware).
91 /// <param name="reader"></param>
92 /// <param name="pStruct"></param>
93 /// <param name="len"></param>
94 /// <param name="type"></param>
95 unsafe internal static void ReadStruct(BinaryReader reader
, void* pStruct
, int len
, Type type
)
97 ReadStruct(reader
, pStruct
, len
);
98 if (!System
.BitConverter
.IsLittleEndian
) {
99 ChangeStructEndianess(pStruct
, type
);
104 unsafe private static int SwapByTypeCode(byte* p
, TypeCode tcode
)
108 case TypeCode
.Int16
:
109 short* sp
= (short*) p
;
111 sx
= LEBitConverter
.SwapInt16(sx
);
113 inc
= sizeof (short);
115 case TypeCode
.UInt16
:
116 ushort* usp
= (ushort*) p
;
118 usx
= LEBitConverter
.SwapUInt16(usx
);
120 inc
= sizeof (ushort);
122 case TypeCode
.Int32
:
125 ix
= LEBitConverter
.SwapInt32(ix
);
129 case TypeCode
.UInt32
:
130 uint* uip
= (uint*) p
;
132 uix
= LEBitConverter
.SwapUInt32(uix
);
136 case TypeCode
.Int64
:
137 long* lp
= (long*) p
;
139 lx
= LEBitConverter
.SwapInt64(lx
);
143 case TypeCode
.UInt64
:
144 ulong* ulp
= (ulong*) p
;
146 ulx
= LEBitConverter
.SwapUInt64(ulx
);
148 inc
= sizeof (ulong);
151 case TypeCode
.SByte
:
160 unsafe internal static int ChangeStructEndianess(void* pStruct
, Type type
)
162 if (type
== null || !type
.IsValueType
) return 0;
163 if (!type
.IsLayoutSequential
&& !type
.IsExplicitLayout
) {
164 throw new Exception("Internal error: struct must have explicit or sequential layout.");
167 bool seq
= type
.IsLayoutSequential
;
168 byte* p
= (byte*) pStruct
;
171 FieldInfo
[] fields
= type
.GetFields(BindingFlags
.Instance
| BindingFlags
.NonPublic
| BindingFlags
.Public
);
173 foreach (FieldInfo fi
in fields
) {
174 if (!seq
) offs
= Marshal
.OffsetOf(type
, fi
.Name
).ToInt32 ();
175 Type ft
= fi
.FieldType
;
176 TypeCode tcode
= Type
.GetTypeCode(ft
);
177 if (tcode
== TypeCode
.Object
) {
178 // not a primitive type, process recursively.
179 inc
= ChangeStructEndianess(p
+ offs
, ft
);
181 inc
= SwapByTypeCode(p
+ offs
, tcode
);
183 if (seq
) offs
+= inc
;