[Mono-list] RESULT: 0 from mono, not from mint.

Peter M. Lemmen peter@lemmen.org
Fri, 29 Mar 2002 15:53:32 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_0003_01C1D739.E0D9C380
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hi again,

I updated the scripts and the c program with a GPL statement which I copied
from the bottom of one of those COPYING files. I hope that fixes the licensing
bit.

I also took a good look at information about the Portable Executable layout
after t3rmin4t0r's remarks and rewrote most of the ismonobin program. It now
parses the PE Header and Optional Header, looking for a Data Dictionary Entry
that signifies a .NET binary. It should now correctly identify between .NET and
non-.NET binaries. My previous assumptions were a bit overly simple. ;-)

Regards,

Peter.

> -----Original Message-----
> From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com]On
> Behalf Of Peter M. Lemmen
> Sent: Friday, March 29, 2002 11:34
> To: Miguel de Icaza; Peter M. Lemmen
> Cc: Mono-List Mailing List
> Subject: RE: [Mono-list] RESULT: 0 from mono, not from mint.
>
>
> Hi,
>
> > -----Original Message-----
> > From: Miguel de Icaza [mailto:miguel@ximian.com]
> > Sent: Friday, March 29, 2002 07:10
> > To: Peter M. Lemmen
> > Cc: Ulrich Kunitz; Mono-List Mailing List
> > Subject: RE: [Mono-list] RESULT: 0 from mono, not from mint.
> >
> >
> > Hello Peter!
> >
> > > I've written two little scripts and a small c program to wrap
> > around the whole
> > > binary execution thing.
> >
> > These are awesome!  Would you mind licensing those scripts under the
> > GPL, LGPL or X11 licenses and allow us to distribute those as part of
> > Mono?
>
> No problem. How do I do that, and which license do you suggest?
>
> >
> >
> > > The default locations for the scripts right now is /usr/bin/local.
> > I hope this
> > > is ok. After placing them in there and running binfmt_misc_mono
> > you should be
> > > able to try the following for yourself:
> >
> > Ideally if we integrate this into the build, we will have configure
> > automatically generate the correct paths that will be embedded.
>
> I'm going to work the suggestions of t3rmin4t0r into ismonobin, then I'll see
> if I can figure out how to couple it to configure. :-)
>
> > <SNIP>
> >
>
>
>
> _______________________________________________
> Mono-list maillist  -  Mono-list@ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list
>

------=_NextPart_000_0003_01C1D739.E0D9C380
Content-Type: application/octet-stream;
	name="ismonobin.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="ismonobin.c"

//_______________________________________________________________________=
______
//
// ismonobin v0.2, Copyright (C) 2002  Peter M. Lemmen.
//
// ismonobin tries to determine wether the passed executable is an =
Intermediate
// Language binary or not.
//
//    This program is free software; you can redistribute it and/or =
modify
//    it under the terms of the GNU General Public License as published =
by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//_______________________________________________________________________=
______
//
// 20020329, Modified - Added correct PE Header parsing as per =
t3rmin4t0r's
//                      suggestions. Also moved the checks into =
functions.
//_______________________________________________________________________=
______
//
// Includes.
//
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
//_______________________________________________________________________=
______
//
// The size of the buffer used for reads, should be large enough to host =
our
// largest read.
//
#define BUFFER_SIZE 128
//
// The 'magic' bytes starting the Mono binaries.
//
unsigned char aucMSDOSSignature[] =3D {
  0x4D, 0x5A
};
//
#define MSD_CMP_SIZE 2
//
// The PE Header bytes.
//
unsigned char aucPESignature[] =3D {
  0x50, 0x45, 0x00, 0x00
};
//
#define PEH_CMP_SIZE 4
//_______________________________________________________________________=
______
//
int display_help() {
  printf( "ismonobin v0.2, Copyright (C) 2002  Peter M. Lemmen.\n" );
  printf( "Usage: ismonobin <executable>\n" );
  printf( " ismonobin tries to determine wether the passed executable is =
an Intermediate\n" );
  printf( " Language binary or not.\n" );
  return 0;
}
//_______________________________________________________________________=
______
//
// A simple function to seek to a position in a filedescriptor and =
compare a
// range of bytes found there to those in the passed array.
//
int intCompareByteRangeAt(
  const int intFileDescriptor
, const off_t oftOffSet
, const size_t setRange
, const void *ptrCompareWith
) {
  unsigned char aucBuffer[BUFFER_SIZE];
  int intBytesRead;

  // Check if the FileDescriptor is valid.
  if (intFileDescriptor < 1)
    return -1;

  // Check if the Offset is valid.
  if (oftOffSet < (off_t)0)
    return -2;

  // Check if the Range is valid.
  if (setRange < (size_t)1)
    return -3;

  // Move to the specified location.
  if (lseek( intFileDescriptor, oftOffSet, SEEK_SET ) !=3D oftOffSet)
    return -4;

  // Read setRange bytes.
  intBytesRead =3D read( intFileDescriptor, &aucBuffer, setRange );

  // Check if the read was succesful.
  if ((size_t)intBytesRead < setRange)
    return -5;

  // Ok, compare the setRange bytes to ptrCompareWith.
  if (bcmp( aucBuffer, ptrCompareWith, setRange ) !=3D 0)
    return 1;

  // It matches.
  return 0;
}
//_______________________________________________________________________=
______
//
// A simple function to get an DWord (int32/address) from a specific =
location
// within a FileDescriptor
//
int intGetDWordAt(
  const int intFileDescriptor
, const off_t oftOffSet
) {
  int intDWord;
  int intBytesRead;

  // Check if the FileDescriptor is valid.
  if (intFileDescriptor < 1)
    return -1;

  // Check if the Offset is valid.
  if (oftOffSet < (off_t)0)
    return -2;

  // Move to the specified location.
  if (lseek( intFileDescriptor, oftOffSet, SEEK_SET ) !=3D oftOffSet)
    return -3;

  // Read 4 bytes into the Address variable.
  intBytesRead =3D read( intFileDescriptor, &intDWord, (size_t)4 );

  // Check if the read was succesful.
  if (intBytesRead < 4)
    return -4;

  // Return the Address.
  return intDWord;
}
//_______________________________________________________________________=
______
//
// A simple function to get a Word (int16) from a specific location =
within a
// FileDescriptor
//
int intGetWordAt(
  const int intFileDescriptor
, const off_t oftOffSet
) {
  int intWord;
  int intBytesRead;

  // Check if the FileDescriptor is valid.
  if (intFileDescriptor < 1)
    return -1;

  // Check if the Offset is valid.
  if (oftOffSet < (off_t)0)
    return -2;

  // Move to the specified location.
  if (lseek( intFileDescriptor, oftOffSet, SEEK_SET ) !=3D oftOffSet)
    return -3;

  // Make sure the upper bits are 0
  intWord =3D 0;

  // Read 2 bytes into the Address variable.
  intBytesRead =3D read( intFileDescriptor, &intWord, (size_t)2 );

  // Check if the read was succesful.
  if (intBytesRead < 2)
    return -4;

  // Return the Address.
  return intWord;
}
//_______________________________________________________________________=
______
//
// Program Entrypoint.
//
int main (int intArgumentCount, char *acrArgumentValues []){
  int intFileDescriptor;
  int intBaseAddress;
  int intCharacteristics;
  int intVirtualAddress;
  int intSize;

  // Check if we're being passed anything other then a single parameter.
	if ((intArgumentCount < 2)
  ||  (intArgumentCount > 2)) {
    return display_help();
  // If not, check if it isn't -h.
  } else if (strcmp( "-h", acrArgumentValues[1] ) =3D=3D 0) {
    return display_help();
  }

  // Try to open the file given on the command line.
  intFileDescriptor =3D open( acrArgumentValues[1], O_RDONLY );

  // Check if successful.
  if (intFileDescriptor < 1) {
    fprintf( stderr, "Unabled to open file %s.\n", acrArgumentValues[1] =
);
    return 0;
  }

  // Check for a valid MSDOS Signature at the start of the file.
  if (intCompareByteRangeAt( intFileDescriptor, (off_t)0, =
(size_t)MSD_CMP_SIZE, aucMSDOSSignature ) !=3D 0) {
    fprintf( stderr, "File %s does not have a valid Exe header.\n", =
acrArgumentValues[1] );
    return 0;
  }
 =20
  // Get the Base Address for the PE Header.
  intBaseAddress =3D intGetDWordAt( intFileDescriptor, (off_t)60 );

  // Check for a valid PE Signature at the Base Address.
  if (intCompareByteRangeAt( intFileDescriptor, (off_t)intBaseAddress, =
(size_t)PEH_CMP_SIZE, aucPESignature ) !=3D 0) {
    fprintf( stderr, "File %s does not have a valid PE Header.\n", =
acrArgumentValues[1] );
    return 0;
  }
 =20
  // Get the PE Characteristics at Base + 0x16.
  intCharacteristics =3D intGetWordAt( intFileDescriptor, =
(off_t)(intBaseAddress + 0x16) );

  // Check for the Executable bit.
  if ((intCharacteristics & 0x0002) !=3D 0x0002) {
    fprintf( stderr, "File %s does not have it's executable bit set.\n", =
acrArgumentValues[1] );
    return 0;
  }

  // Check for the DLL bit.
  if ((intCharacteristics & 0x2000) =3D=3D 0x2000) {
    fprintf( stderr, "File %s has it's DLL bit set.\n", =
acrArgumentValues[1] );
    return 0;
  }

  // Move to the Optional Header.
  intBaseAddress +=3D 0x18;

  // Get the Virtual Address and Size of the Com Descriptor Directory =
Entry.
  intVirtualAddress =3D intGetDWordAt( intFileDescriptor, =
(off_t)(intBaseAddress + 0xD0) );
  intSize =3D intGetDWordAt( intFileDescriptor, (off_t)(intBaseAddress + =
0xD4) );

  // If these two are zero (and I read the specs correctly) then it =
can't be an IL binary.
  if ((intVirtualAddress =3D=3D 0)
  ||  (intSize =3D=3D 0)) {
    fprintf( stderr, "File %s has no Com Descriptor Directory Entry =
set.\n", acrArgumentValues[1] );
    return 0;
  }

  // Looks like an IL binary.
  return 1;
}
//_______________________________________________________________________=
______
//

------=_NextPart_000_0003_01C1D739.E0D9C380
Content-Type: application/octet-stream;
	name="exewrapper.sh"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="exewrapper.sh"

#!/bin/bash=0A=
# exewrapper.sh v0.2, Copyright (C) 2002  Peter M. Lemmen.=0A=
#=0A=
#   This program is free software; you can redistribute it and/or modify=0A=
#   it under the terms of the GNU General Public License as published by=0A=
#   the Free Software Foundation; either version 2 of the License, or=0A=
#   (at your option) any later version.=0A=
#=0A=
#   This program is distributed in the hope that it will be useful,=0A=
#   but WITHOUT ANY WARRANTY; without even the implied warranty of=0A=
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the=0A=
#   GNU General Public License for more details.=0A=
#=0A=
#   You should have received a copy of the GNU General Public License=0A=
#   along with this program; if not, write to the Free Software=0A=
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=0A=
#=0A=
=0A=
# Define the mono and ismonobin executables.=0A=
MONO=3D/usr/local/bin/mono=0A=
ISMONOBIN=3D/usr/local/bin/ismonobin=0A=
=0A=
# Check for at least one argument.=0A=
if [ $# -lt "1" ]=0A=
then=0A=
  echo "Usage: `basename $0` <executable> [arguments]"=0A=
  exit 0=0A=
fi=0A=
=0A=
# Test of the passed argument is a Mono Binary.=0A=
$ISMONOBIN $1 2> /dev/null=0A=
=0A=
# If so, run it with the Mono JIT.=0A=
if [ $? -eq 1 ]=0A=
then=0A=
  $MONO $1 $*=0A=
  exit 0=0A=
fi=0A=
=0A=
# If not, well, do something else I suppose.=0A=
# TODO: Wine and DOSEMU support.=0A=
echo "File \"$1\" is NOT a Mono Binary."=0A=
=0A=
exit 0=0A=

------=_NextPart_000_0003_01C1D739.E0D9C380
Content-Type: application/octet-stream;
	name="binfmt_misc_mono.sh"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="binfmt_misc_mono.sh"

#!/bin/bash=0A=
# binfmt_misc_mono.sh v0.2, Copyright (C) 2002  Peter M. Lemmen.=0A=
#=0A=
#   This program is free software; you can redistribute it and/or modify=0A=
#   it under the terms of the GNU General Public License as published by=0A=
#   the Free Software Foundation; either version 2 of the License, or=0A=
#   (at your option) any later version.=0A=
#=0A=
#   This program is distributed in the hope that it will be useful,=0A=
#   but WITHOUT ANY WARRANTY; without even the implied warranty of=0A=
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the=0A=
#   GNU General Public License for more details.=0A=
#=0A=
#   You should have received a copy of the GNU General Public License=0A=
#   along with this program; if not, write to the Free Software=0A=
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=0A=
#=0A=
=0A=
# Define the register and exewrapper location.=0A=
REGISTER=3D/proc/sys/fs/binfmt_misc/register=0A=
EXEWRAPPER=3D/usr/local/bin/exewrapper.sh=0A=
MODPROBE=3D/sbin/modprobe=0A=
ECHO=3D/bin/echo=0A=
=0A=
# Create a Registration String.=0A=
REGISTRATION=3D:ExeWrapper:M::MZ::$EXEWRAPPER:=0A=
=0A=
# Load the binfmt_misc module=0A=
$MODPROBE binfmt_misc=0A=
=0A=
# Register the exewrapper =0A=
$ECHO $REGISTRATION > $REGISTER=0A=
=0A=
exit 0=0A=

------=_NextPart_000_0003_01C1D739.E0D9C380--