johnsonjh/duma

View on GitHub
Attic/kduma/createconf.c

Summary

Maintainability
Test Coverage
/*
 * KDUMA - Red-Zone memory allocator.
 *
 * Copyright (C) 2006 Michael Eddington <meddington@gmail.com>
 * Copyright (C) 2002-2005 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
 * Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
 *
 * License: GNU GPL (GNU General Public License, see COPYING-GPL)
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * FILE CONTENTS:
 * --------------
 * This is a small tool to generate the "duma_config.h" configuration file.
 * Its purpose is to allow fixed size memory allocation on stack, which can
 * get protected calling page protection functions.
 * Also its nice for the user to be able to see the page size.
 */

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <stdarg.h>

#ifdef _MSC_VER
#include <direct.h>
#endif

#ifndef WIN32
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#else
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <winbase.h>

typedef LPVOID caddr_t;
typedef unsigned u_int;
#endif


/*
* retrieve page size
* size_t  Page_Size(void)
*/
static size_t
Page_Size(void)
{
#if defined(WIN32)
    SYSTEM_INFO SystemInfo;
    GetSystemInfo( &SystemInfo );
    return (size_t)SystemInfo.dwPageSize;
#elif defined(_SC_PAGESIZE)
    return (size_t)sysconf(_SC_PAGESIZE);
#elif defined(_SC_PAGE_SIZE)
    return (size_t)sysconf(_SC_PAGE_SIZE);
#else
    /* extern int    getpagesize(); */
    return getpagesize();
#endif
}

int initattr_ok = 0;

void
#ifdef __GNUC__
__attribute ((constructor))
#endif
init_function(void)
{
    initattr_ok = 1;
}



typedef struct
{
    int  id;
    int  size;
    char *type;
}
DataType_T;


DataType_T  sIntTypes[] =
{
    { 0, sizeof(char)     , "char"      }
    , { 1, sizeof(short int), "short int" }
    , { 2, sizeof(int)      , "int"       }
    , { 3, sizeof(long int) , "long int"  }
    /* hier zusaetzliche compiler-spezifische datentypen hinzufuegen */
#ifdef _MSC_VER
    , { 4, sizeof(__int64), "__int64"     }
#endif
#ifdef __GNUC__
    , { 5, sizeof(long long int), "long long int" }
#endif
};


/* test access to each data type */
void testAlignment(int addrIdx, char * buffer, int alignment, int max_sizeof)
{
    int offset;

    switch ( sIntTypes[addrIdx].id )
    {
    case 0:
#define TYPE unsigned char
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
    case 1:
#undef TYPE
#define TYPE unsigned short int
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
    case 2:
#undef TYPE
#define TYPE unsigned int
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
    case 3:
#undef TYPE
#define TYPE unsigned long int
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
#ifdef _MSC_VER
    case 4:
#undef TYPE
#define TYPE unsigned __int64
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
#endif
#ifdef __GNUC__
    case 5:
#undef TYPE
#define TYPE unsigned long long int
        for(offset=0; offset < max_sizeof; ++offset)
        {
            TYPE addr = (TYPE)(buffer) + offset;
            if ( addr % alignment == 0 )
            {
                *( (unsigned char *)     addr ) = 0;
                *( (unsigned short int*) addr ) = 0;
                *( (unsigned int *)      addr ) = 0;
                *( (unsigned long int *) addr ) = 0L;
                *( (float *)             addr ) = 0.0F;
                *( (double *)            addr ) = 0.0;
                *( (long double *)       addr ) = 0.0;
#ifdef _MSC_VER
                *( (unsigned __int64 *) addr ) = 0L;
#endif
#ifdef __GNUC__
                *( (unsigned long long int *) addr ) = 0L;
#endif
            }
        }
        break;
#endif
        ;
    }
}



void writeFile(const char * filename, unsigned long pagesize, int addrIdx, int sizeIdx, int alignment)
{
    FILE * f = fopen(filename, "w");
    if (!f)
        return;

    fprintf(f, "/*\n");
    fprintf(f, " * WARNING: DO NOT CHANGE THIS FILE!\n");
    fprintf(f, " * This file is automatically generated from createconf\n");

#if defined(WIN32)
#if defined(_MSC_VER)
    fprintf(f, " * using Microsoft Visual C++ under MS Windows(TM) the %s\n", __DATE__ );
#else
    printf(f, " * under MS Windows(TM) the %s\n", __DATE__ );
#endif
#elif ( defined(sgi) )
    fprintf(f, " * under sgi the %s\n", __DATE__ );
#elif ( defined(_AIX) )
    fprintf(f, " * under AIX the %s\n", __DATE__ );
#elif ( defined(__linux__) )
    fprintf(f, " * under Linux the %s\n", __DATE__ );
#else
    fprintf(f, " * the %s \n", __DATE__ );
#endif

    fprintf(f, " */\n");
    fprintf(f, "\n");
    fprintf(f, "#ifndef _DUMA_CONFIG_H_\n");
    fprintf(f, "#define _DUMA_CONFIG_H_\n");

    fprintf(f, "\n");

    fprintf(f, "\n");
    fprintf(f, "/* Variable: DUMA_PAGE_SIZE\n");
    fprintf(f, " *\n");
    fprintf(f, " * Number of bytes per virtual-memory page, as returned by Page_Size().\n");
    fprintf(f, " */\n");
    fprintf(f, "#define DUMA_PAGE_SIZE %lu\n", pagesize);

    fprintf(f, "\n");
    fprintf(f, "/* Variable: DUMA_MIN_ALIGNMENT\n");
    fprintf(f, " *\n");
    fprintf(f, " * Minimum required alignment by CPU.\n");
    fprintf(f, " */\n");
    fprintf(f, "#define DUMA_MIN_ALIGNMENT %d\n", alignment);

    fprintf(f, "\n");
    fprintf(f, "/* Variable: DUMA_GNU_INIT_ATTR\n");
    fprintf(f, " *\n");
    fprintf(f, " * Build environment supports the '__attribute ((constructor))'?\n");
    fprintf(f, " */\n");
    if (initattr_ok)
        fprintf(f, "#define DUMA_GNU_INIT_ATTR 1\n");
    else
        fprintf(f, "/* #define DUMA_GNU_INIT_ATTR 0 */\n");

    fprintf(f, "\n");
    fprintf(f, "/* Type: DUMA_ADDR\n");
    fprintf(f, " *\n");
    fprintf(f, " * An integer type with same size as 'void *'\n");
    fprintf(f, " */\n");
    if (addrIdx >= 0)
        fprintf(f, "typedef unsigned %s DUMA_ADDR;\n", sIntTypes[addrIdx].type);
    else
        fprintf(f, "/* Error: No datatype for DUMA_ADDR found! */\n");

    fprintf(f, "\n");
    fprintf(f, "/* Type: DUMA_SIZE\n");
    fprintf(f, " *\n");
    fprintf(f, " * An integer type with same size as 'size_t'\n");
    fprintf(f, " */\n");
    if (sizeIdx >= 0)
        fprintf(f, "typedef unsigned %s DUMA_SIZE;\n", sIntTypes[sizeIdx].type);
    else
        fprintf(f, "/* No datatype for DUMA_SIZE found! */\n");

    fprintf(f, "\n");
    fprintf(f, "#endif /* _DUMA_CONFIG_H_ */\n");

    fclose(f);
}


int main()
{
    int iNumIntTypes, iIt;
    int addrIdx, sizeIdx;
    int alignment, max_sizeof;
    char  buffer[1024];
    char filename[1024];

    unsigned long pagesize = Page_Size();

    iNumIntTypes = sizeof( sIntTypes ) / sizeof( sIntTypes[0] );

    // detect compatible type for ADDRESS
    addrIdx = -1;
    for (iIt = 0; iIt < iNumIntTypes; ++iIt)
    {
        if ( sizeof(void*) == sIntTypes[iIt].size )
        {
            addrIdx = iIt;
            break;
        }
    }

    // detect compatible type for SIZE_T
    sizeIdx = -1;
    for (iIt = 0; iIt < iNumIntTypes; ++iIt)
    {
        if ( sizeof(size_t) == sIntTypes[iIt].size )
        {
            sizeIdx = iIt;
            break;
        }
    }

    /* detect maximum data type, which should be maximum alignment */
    max_sizeof = 0;
    for (iIt = 0; iIt < iNumIntTypes; ++iIt)
    {
        if ( max_sizeof < sIntTypes[iIt].size )
            max_sizeof = sIntTypes[iIt].size;
    }
    if ( max_sizeof < sizeof(float) )
        max_sizeof = sizeof(float);
    if ( max_sizeof < sizeof(double) )
        max_sizeof = sizeof(double);
    if ( max_sizeof < sizeof(long double) )
        max_sizeof = sizeof(long double);

#ifdef _MSC_VER
    {
        /* fix output path when started form Visual C++ IDE */
        char  directory[1024];
        char  * start;

        _getcwd( directory, 1024 ); /* get current directory */
        if ( ( start = strstr( directory, "win32-msvc" ) ) )
        {
            *start = 0;
            strcpy(filename, directory);
            strcat(filename, "duma_config.h");
        }
        else
            strcpy( filename, "duma_config.h" );
    }
#else
    strcpy( filename, "duma_config.h" );
#endif

    /* detect minimum alignment */
    alignment = max_sizeof;
    do
    {
        /* do the alignment access tests */
        testAlignment(addrIdx, buffer, alignment, max_sizeof);
        /* write whole config file. next test may crash ! */
        writeFile(filename, pagesize, addrIdx, sizeIdx, alignment);
        /* try next lower alignment */
        alignment >>= 1;
    }
    while ( alignment > 0 );

    return 0;
}