Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read metadata from unmanaged memory #631

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)\cecil.snk</AssemblyOriginatorKeyFile>
<DefineConstants Condition=" '$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netcoreapp2.1' ">$(DefineConstants);NET_CORE</DefineConstants>
<RootNamespace></RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net40' ">
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
Expand Down
6 changes: 1 addition & 5 deletions Mono.Cecil.Cil/CodeReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,7 @@ void ReadFatMethod ()

public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
{
var position = reader.position;
var variables = reader.ReadVariables (local_var_token);
reader.position = position;

return variables;
return reader.ReadVariables (local_var_token);
}

void ReadCode ()
Expand Down
22 changes: 15 additions & 7 deletions Mono.Cecil.Metadata/BlobHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,43 @@
//

using System;
using System.Runtime.InteropServices;

namespace Mono.Cecil.Metadata {

sealed class BlobHeap : Heap {
sealed unsafe class BlobHeap : Heap {

public BlobHeap (byte [] data)
: base (data)
public BlobHeap (byte* data, uint size)
: base (data, size)
{
}

public byte [] Read (uint index)
{
if (index == 0 || index > this.data.Length - 1)
if (index == 0 || index > this.size - 1)
return Empty<byte>.Array;

int position = (int) index;
int length = (int) data.ReadCompressedUInt32 (ref position);
int length = (int) Mixin.ReadCompressedUInt32 (data, ref position);

if (length > data.Length - position)
if (length > size - position)
return Empty<byte>.Array;

var buffer = new byte [length];

Buffer.BlockCopy (data, position, buffer, 0, length);
Marshal.Copy ((IntPtr)(data + position), buffer, 0, length);

return buffer;
}

public void GetView (uint signature, out byte [] buffer, out int index, out int length)
{
buffer = Read (signature);
index = 0;
length = buffer.Length;


/*
if (signature == 0 || signature > data.Length - 1) {
buffer = null;
index = length = 0;
Expand All @@ -49,6 +56,7 @@ public void GetView (uint signature, out byte [] buffer, out int index, out int

index = (int) signature;
length = (int) buffer.ReadCompressedUInt32 (ref index);
*/
}
}
}
21 changes: 12 additions & 9 deletions Mono.Cecil.Metadata/GuidHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,31 @@
//

using System;
using System.Runtime.InteropServices;

namespace Mono.Cecil.Metadata {

sealed class GuidHeap : Heap {
sealed unsafe class GuidHeap : Heap {

public GuidHeap (byte [] data)
: base (data)
public GuidHeap (byte* data, uint size)
: base (data, size)
{
}

public Guid Read (uint index)
{
const int guid_size = 16;

if (index == 0 || ((index - 1) + guid_size) > data.Length)
if (index == 0 || ((index - 1) + guid_size) > size)
return new Guid ();

var buffer = new byte [guid_size];

Buffer.BlockCopy (this.data, (int) ((index - 1) * guid_size), buffer, 0, guid_size);

return new Guid (buffer);
if (BitConverter.IsLittleEndian) {
return *(Guid*) (data + ((index - 1) * guid_size));
} else {
var buffer = new byte [guid_size];
Marshal.Copy ((IntPtr)(data + ((index - 1) * guid_size)), buffer, 0, guid_size);
return new Guid (buffer);
}
}
}
}
12 changes: 9 additions & 3 deletions Mono.Cecil.Metadata/Heap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,23 @@
// Licensed under the MIT/X11 license.
//

using Mono.Cecil.PE;

namespace Mono.Cecil.Metadata {

abstract class Heap {
abstract unsafe class Heap {

public int IndexSize;

readonly internal byte [] data;
readonly internal byte* data;
readonly internal uint size;

public ByteSpan Span => new ByteSpan (data, size);

protected Heap (byte [] data)
protected Heap (byte* data, uint size)
{
this.data = data;
this.size = size;
}
}
}
4 changes: 2 additions & 2 deletions Mono.Cecil.Metadata/PdbHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ sealed class PdbHeap : Heap {
public long TypeSystemTables;
public uint [] TypeSystemTableRows;

public PdbHeap (byte [] data)
: base (data)
public unsafe PdbHeap (byte* data, uint size)
: base (data, size)
{
}

Expand Down
16 changes: 11 additions & 5 deletions Mono.Cecil.Metadata/StringHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@
using System;
using System.Collections.Generic;
using System.Text;
using Mono.Cecil.PE;

namespace Mono.Cecil.Metadata {

class StringHeap : Heap {
unsafe class StringHeap : Heap {

readonly Dictionary<uint, string> strings = new Dictionary<uint, string> ();

public StringHeap (byte [] data)
: base (data)
public StringHeap (byte* data, uint size)
: base (data, size)
{
}

Expand All @@ -32,7 +33,7 @@ public string Read (uint index)
if (strings.TryGetValue (index, out @string))
return @string;

if (index > data.Length - 1)
if (index > size - 1)
return string.Empty;

@string = ReadStringAt (index);
Expand All @@ -54,7 +55,12 @@ protected virtual string ReadStringAt (uint index)
length++;
}

return Encoding.UTF8.GetString (data, start, length);
#if NET_CORE
return Encoding.UTF8.GetString (this.data + start, length);
#else
var buffer = new PByteBuffer (this.data + start, (uint) length);
return Encoding.UTF8.GetString (buffer.ReadBytes (length));
#endif
}
}
}
6 changes: 3 additions & 3 deletions Mono.Cecil.Metadata/TableHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public bool IsLarge {
}
}

sealed class TableHeap : Heap {
sealed unsafe class TableHeap : Heap {

public long Valid;
public long Sorted;
Expand All @@ -91,8 +91,8 @@ public TableInformation this [Table table] {
get { return Tables [(int) table]; }
}

public TableHeap (byte [] data)
: base (data)
public TableHeap (byte* data, uint size)
: base (data, size)
{
}

Expand Down
14 changes: 10 additions & 4 deletions Mono.Cecil.Metadata/UserStringHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,29 @@
// Licensed under the MIT/X11 license.
//

using System;

namespace Mono.Cecil.Metadata {

sealed class UserStringHeap : StringHeap {
sealed unsafe class UserStringHeap : StringHeap {

public UserStringHeap (byte [] data)
: base (data)
public UserStringHeap (byte* data, uint size)
: base (data, size)
{
}

protected override string ReadStringAt (uint index)
{
int start = (int) index;

uint length = (uint) (data.ReadCompressedUInt32 (ref start) & ~1);
uint length = (uint) (Mixin.ReadCompressedUInt32 (data, ref start) & ~1);
if (length < 1)
return string.Empty;

if (BitConverter.IsLittleEndian) {
return new string ((char*)(data + start), 0, (int)length / 2);
}

var chars = new char [length / 2];

for (int i = start, j = 0; i < start + length; i += 2)
Expand Down
2 changes: 1 addition & 1 deletion Mono.Cecil.Metadata/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static partial class Mixin {
public const int TableCount = 58;
public const int CodedIndexCount = 14;

public static uint ReadCompressedUInt32 (this byte [] data, ref int position)
public static unsafe uint ReadCompressedUInt32 (byte* data, ref int position)
{
uint integer;
if ((data [position] & 0x80) == 0) {
Expand Down
Loading