/*
* PERWAPI - An API for Reading and Writing PE Files
*
* Copyright (c) Diane Corney, Queensland University of Technology, 2004.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the PERWAPI Copyright as included with this
* distribution in the file PERWAPIcopyright.rtf.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY as is explained in the copyright notice.
*
* The author may be contacted at d.corney@qut.edu.au
*
* Version Date: 26/01/07
*/
using System;
namespace QUT.PERWAPI
{
///
/// Diagnostic
///
public class Diag
{
///
/// Flag for diagnostic output.
///
public static bool DiagOn = false;
}
public static class BlobUtil
{
public static byte[] CompressInt(int val)
{
// This code is based on a revised version of the
// ECMA-335 spec which clarifies the encoding of
// array lower bounds. (kjg 2008-Feb-22 )
//
uint uVal = ((uint)val) << 1;
uint sign = (val < 0 ? (uint)1 : 0);
if (-64 <= val && val <= 63)
{
uVal = uVal & 0x7f | sign;
return new byte[] { (byte)uVal };
}
else if (-8192 <= val && val <= 8191)
{
uVal = uVal & 0x3fff | 0x8000 | sign;
return new byte[] { (byte)(uVal >> 8), (byte)uVal };
}
else if (-268435456 <= val && val <= 268435455)
{
uVal = uVal & 0x1fffffff | 0xc0000000 | sign;
return new byte[] {
(byte)(uVal >> 24),
(byte)(uVal >> 16),
(byte)(uVal >> 8),
(byte)uVal };
}
else
throw new OverflowException("Value cannot be compressed");
}
public static byte[] CompressUInt(uint val)
{
if (val > 0x1fffffff)
throw new OverflowException("Value cannot be compressed");
return CompressNum(val);
}
private static byte[] CompressNum(uint num)
{
byte[] rslt = null;
if (num <= 0x7f)
{
rslt = new byte[1];
rslt[0] = (byte)num;
}
else if (num <= 0x3fff)
{
rslt = new byte[2];
rslt[0] = (byte)((num >> 8) | 0x80);
rslt[1] = (byte)(num & 0xff);
}
else
{
rslt = new byte[4];
rslt[0] = (byte)((num >> 24) | 0xc0);
rslt[1] = (byte)((num >> 16) & 0xff);
rslt[2] = (byte)((num >> 8) & 0xff);
rslt[3] = (byte)(num & 0xff);
}
return rslt;
}
}
///
/// Facilities for outputting hexadecimal strings
///
public class Hex
{
readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F'};
readonly static uint[] iByteMask = { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 };
readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
0x0000000000FF0000, 0x00000000FF000000,
0x000000FF00000000, 0x0000FF0000000000,
0x00FF000000000000, 0xFF00000000000000 };
readonly static uint nibble0Mask = 0x0000000F;
readonly static uint nibble1Mask = 0x000000F0;
///
/// Derives a hexadecimal string for a byte value
///
/// the byte value
/// hex string for the byte value
public static String Byte(int b)
{
char[] str = new char[2];
uint num = (uint)b;
uint b1 = num & nibble0Mask;
uint b2 = (num & nibble1Mask) >> 4;
str[0] = hexDigit[b2];
str[1] = hexDigit[b1];
return new String(str);
}
///
/// Derives a hexadecimal string for a short value
///
/// the short value
/// hex string for the short value
public static String Short(int b)
{
char[] str = new char[4];
uint num1 = (uint)b & iByteMask[0];
uint num2 = ((uint)b & iByteMask[1]) >> 8;
uint b1 = num1 & nibble0Mask;
uint b2 = (num1 & nibble1Mask) >> 4;
uint b3 = num2 & nibble0Mask;
uint b4 = (num2 & nibble1Mask) >> 4;
str[0] = hexDigit[b4];
str[1] = hexDigit[b3];
str[2] = hexDigit[b2];
str[3] = hexDigit[b1];
return new String(str);
}
///
/// Derives a hexadecimal string for an int value
///
/// the int value
/// hex string for the int value
public static String Int(int val)
{
char[] str = new char[8];
uint num = (uint)val;
int strIx = 7;
for (int i = 0; i < iByteMask.Length; i++)
{
uint b = num & iByteMask[i];
b >>= (i * 8);
uint b1 = b & nibble0Mask;
uint b2 = (b & nibble1Mask) >> 4;
str[strIx--] = hexDigit[b1];
str[strIx--] = hexDigit[b2];
}
return new String(str);
}
///
/// Derives a hexadecimal string for an unsigned int value
///
/// the unsigned int value
/// hex string for the unsigned int value
public static String Int(uint num)
{
char[] str = new char[8];
int strIx = 7;
for (int i = 0; i < iByteMask.Length; i++)
{
uint b = num & iByteMask[i];
b >>= (i * 8);
uint b1 = b & nibble0Mask;
uint b2 = (b & nibble1Mask) >> 4;
str[strIx--] = hexDigit[b1];
str[strIx--] = hexDigit[b2];
}
return new String(str);
}
///
/// Derives a hexadecimal string for a long value
///
/// the long value
/// hex string for the long value
public static String Long(long lnum)
{
ulong num = (ulong)lnum;
return Long(num);
}
///
/// Derives a hexadecimal string for an unsigned long value
///
/// the unsigned long value
/// hex string for the unsigned long value
public static String Long(ulong num)
{
char[] str = new char[16];
int strIx = 15;
for (int i = 0; i < lByteMask.Length; i++)
{
ulong b = num & lByteMask[i];
b >>= (i * 8);
ulong b1 = b & nibble0Mask;
ulong b2 = (b & nibble1Mask) >> 4;
str[strIx--] = hexDigit[b1];
str[strIx--] = hexDigit[b2];
}
return new String(str);
}
}
///
/// Exception for features yet to be implemented
///
public class NotYetImplementedException : System.Exception
{
///
/// constructor
///
///
public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
}
///
/// Error in a type signature
///
public class TypeSignatureException : System.Exception
{
///
/// constructor
///
///
public TypeSignatureException(string msg) : base(msg) { }
}
///
/// Error with a CIL instruction
///
public class InstructionException : System.Exception
{
IType iType;
uint op;
internal InstructionException(IType iType, uint op)
{
this.iType = iType;
this.op = op;
}
internal string AddMethodName(string name)
{
string istr = " ";
switch (iType)
{
case (IType.fieldOp): istr += (FieldOp)op; break;
case (IType.methOp): istr += (MethodOp)op; break;
case (IType.specialOp): istr += (SpecialOp)op; break;
case (IType.typeOp): istr += (TypeOp)op; break;
default: break;
}
return "NullPointer in instruction" + istr + " for method " + name;
}
}
///
/// Error with descriptor types
///
public class DescriptorException : System.Exception
{
///
/// exception
///
///
public DescriptorException(string msg)
:
base("Descriptor for " + msg + " already exists") { }
///
/// exception
///
public DescriptorException()
:
base("Descriptor is a Def when a Ref is required") { }
}
///
/// Error for invalid PE file
///
public class PEFileException : System.Exception
{
///
/// PEFile exception constructor
///
///
public PEFileException(string msg) : base("Error in PE File: " + msg) { }
}
///
/// When the maximum stack depth could not be found dynamically.
///
public class CouldNotFindMaxStackDepth : System.Exception
{
///
/// Constructor
///
public CouldNotFindMaxStackDepth() : base("Not able to find the maximum stack depth.") { }
}
///
/// When the stack depth is not valid for the current position.
///
public class InvalidStackDepth : System.Exception
{
///
/// Constructor
///
public InvalidStackDepth(string msg) : base("Invalid stack depth reached: " + msg) { }
}
}