#!/bin/sh
#*=====================================================================*/
#*    serrano/prgm/project/bigloo/autoconf/patch                       */
#*    -------------------------------------------------------------    */
#*    Author      :  Manuel Serrano                                    */
#*    Creation    :  Thu Dec 27 06:26:38 2007                          */
#*    Last change :  Fri Jun  2 10:50:55 2017 (serrano)                */
#*    Copyright   :  2007-17 Manuel Serrano                            */
#*    -------------------------------------------------------------    */
#*    Check if self-modifying code can be supported.                   */
#*=====================================================================*/

#*---------------------------------------------------------------------*/
#*    flags                                                            */
#*---------------------------------------------------------------------*/
cflags=
libs=

#*---------------------------------------------------------------------*/
#*    We parse the arguments                                           */
#*---------------------------------------------------------------------*/
while : ; do
  case $1 in
    "")
      break;;

    --cflags=*|-cflags=*)
      cflags="`echo $1 | sed 's/^[-a-z]*=//'`";;

    --libs=*|-libs=*)
      libs="`echo $1 | sed 's/^[-a-z]*=//'`";;

    -*)
      echo "Unknown option \"$1\", ignored" >&2;;
  esac
  shift
done


file=$TMP/actest$USER
aout=$TMP/Xactest$USER

#*---------------------------------------------------------------------*/
#*    compile                                                          */
#*---------------------------------------------------------------------*/
compile="$CC $cflags $file.c -o $aout $libs >/dev/null"

#*---------------------------------------------------------------------*/
#*    The test C file                                                  */
#*---------------------------------------------------------------------*/
if( test -f $file.c ); then
   rm -f $file.c || exit $?
fi

#*---------------------------------------------------------------------*/
#*    Test                                                             */
#*---------------------------------------------------------------------*/
cat > $file.c <<EOF
#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stdlib.h>

#define PATCHABLE_FUNCTION_BEGIN \
asm goto ("" : : : : END_OF_PATCHABLE_FUNCTION)

#define PATCHABLE_FUNCTION_END \
END_OF_PATCHABLE_FUNCTION: asm (" .quad 0x0f1e2d3c4b5a6978")

#define END_OF_PATCHABLE_FUNCTION_MARKER 0x0f1e2d3c4b5a6978LL

int main() {
   PATCHABLE_FUNCTION_BEGIN;

#ifdef linux
   void *start = (void*)(((uint64_t)__start) & ~4095);
   void *end = (void*)((4095+(uint64_t)__etext) & ~4095);
   int len = (uint64_t)end - (uint64_t)start;

#else
   extern uint8_t _mh_execute_header;
   void *start = (void*)(((uint64_t)__start) & ~4095);
   void *end = (void*)((50*4096+4095+(uint64_t)__start) & ~4095);
   int len = (uint64_t)end - (uint64_t)start;

#endif

   if (mprotect(start, len, PROT_READ|PROT_EXEC|PROT_WRITE)) {
     printf("mprotect failed\n");
     exit(1);
   }

   return 0;

   PATCHABLE_FUNCTION_END;
}
EOF

#*---------------------------------------------------------------------*/
#*    Compilation test                                                 */
#*---------------------------------------------------------------------*/
if eval "$BUILDSH $compile"; then
   echo "yes"
else
   echo "no"
fi

\rm -f $file.*
\rm -f $aout
\rm -f $aout*

exit 0
