Tag: c

  • Fun With GDB, Gnu’s Debugger

    Here’s a pretty compact version of strcmp:

    int bstrcmp(char *s1,char *s2) {
       while(*s1 == *s2++) {
          if(*s1++ == 0){ return 0; }
       }
       return (*(unsigned char *)s1 - *(unsigned char*)--s2);
    }
    

    The source that I used for compiling and calling this version of strcmp is here.

    Compile that code using:
    gcc -o strcmp -g strcmp.c

    Fire up the debugger using:
    gdb strcmp

    You’ll get the gdb prompt:
    (gdb)

    Set a break point at the start:
    b main

    The debugger will echo something like:
    Breakpoint 1 at 0x80483d5: file strcmp.c, line 6.
    (gdb)

    Then run the program:
    run

    The debugger will print out something like:
    Starting program: /home/somedude/bin/strcmp

    Breakpoint 1, main () at strcmp.c:6
    6 {
    (gdb)

    If you type n a few times, you’ll eventually get to some variable assignments.

    (gdb) n
    8	char s1[] = "better";
    (gdb) n
    9	char s2[] = "better than"; /* than this";*/
    (gdb) n
    11	int i_result = 0;
    (gdb) n
    13	i_result = bstrcmp(s1,s2);
    

    If you want to the values of these variables type:
    p i_result

    You get back:
    (gdb) p i_result
    $1 = 0

    To step into a function, type s:

    (gdb) s
    bstrcmp (s1=0xbf86b469 "better", s2=0xbf86b474 "better than") at strcmp.c:26
    26		while(*s1 == *s2++) { 
    (gdb) n
    27			if(*s1++ == 0){ return 0; } 
    (gdb) n
    26		while(*s1 == *s2++) { 
    (gdb) n
    27			if(*s1++ == 0){ return 0; } 
    (gdb) n
    26		while(*s1 == *s2++) { 
    (gdb) 
    

    At this point you can type things like:
    p s1
    p *s1
    p s2
    p *s2

    And you’ll get back the value of the pointers and what’s in memory.

    Next time we’ll go over how to do this with PHP running single threaded on debug mode on Apache.

  • How to Make Your Own PHP Extension… Quick and Dirty

    This is a cheat sheet on how to extend PHP. I’m learning how to fix bugs in C within the PHP source code right now using what’s google-able, the #php chat room in irc.freenode.net and “Extending and Embedding PHP” by Sara Goleman.

    Preliminaries: make sure you have the right tools for building php from source. Right now these tools are:

    • autoconf: 2.13
    • automake: 1.4+
    • libtool: 1.4.x+ (except 1.4.2)
    • bison: 1.28, 1.35, 1.75, 2.0 or higher
    • flex: 2.5.4 (not higher)
    • re2c: 0.9.11+ (0.12.0+ for HEAD)
    • Get the latest php stable version. as of this blog posting it’s php-5.2.6
    • unpack the file using something like bunzip2 -c < php-5.2.6.tar.bz2 | tar xvf -
    • ./configure –prefix=/usr/local –enable-debug (I’m really old school and like to put my stuff in /usr/local . YMMV.)
    • make ; make install

    If that worked now we’re ready to make a module. Feel free to substitute barce or BARCE in the code below with whatever you want the module name to be.

    • cd ext (if you type ls you’ll see the extensions that come with php.)
    • mkdir barce (I’m a narcissistic, buddhist, nihilist.)
    • create a config.m4 file with this code:
    PHP_ARG_ENABLE(barce,
            [Whether to enable the "barce" extension],
            [  --enable-barce       Enable "barce" extension support])
    
    if test $PHP_BARCE != "no"; then
            PHP_SUBST(BARCE_SHARED_LIBADD)
            PHP_NEW_EXTENSION(barce, barce.c, $ext_shared)
    fi
    
    • then create a php_barce.h file:
    #ifndef PHP_BARCE_H
    /* Prevent double inclusion */
    #define PHP_BARCE_H
    
    /* Define extension properties */
    #define PHP_BARCE_EXTNAME "barce"
    #define PHP_BARCE_EXTVER "1.0"
    
    /* Import configure options
     * when building outside of the 
     * PHP source tree */
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    /* Include PHP standard Header */
    #include "php.h"
    /*
     * define the entry point symbole
     * Zend will use when loading this module
     */
    extern zend_module_entry barce_module_entry;
    #define phpext_barce_ptr &barce_module_entry
    
    #endif /* PHP_BARCE_H */
    
    
    • create a barce.c file with your functions that you are creating for PHP
    #include "php_barce.h"
    
    PHP_FUNCTION(barce_thinks_youre_cool)
    {
            char *name;
            int name_len;
    
            if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 
                    &name, &name_len) == FAILURE)
            {
                    RETURN_NULL();
            }
    
            php_printf("Barce thinks you're cool, ");
            PHPWRITE(name, name_len);
            php_printf("!\n");
    }
    
    
    static function_entry php_barce_functions[] = {
            PHP_FE(barce_thinks_youre_cool, NULL)
            { NULL, NULL, NULL }
    };
    
    zend_module_entry barce_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
            STANDARD_MODULE_HEADER,
    #endif
            PHP_BARCE_EXTNAME,
            php_barce_functions, /* Functions */
            NULL, /* MINIT */
            NULL, /* MSHUTDOWN */
            NULL, /* RINIT */
            NULL, /* RSHUTDOWN */
            NULL, /* MINFO */
    #if ZEND_MODULE_API_NO >= 20010901
            PHP_BARCE_EXTVER,
    #endif
            STANDARD_MODULE_PROPERTIES
    };
    
    #ifdef COMPILE_DL_BARCE
    ZEND_GET_MODULE(barce)
    #endif
    
    

    Now let’s build this puppy.

    • phpize
    • ./configure –enable-barce
    • make
    • there should now be a modules directory. copy it to /usr/local/lib/php/modules/ .
    • edit php.ini and add two lines:
      • extension_dir = “/usr/local/lib/php/modules”
      • extension = “barce.so”

    Let’s test and see if it worked:

    php -r “barce_thinks_youre_cool(‘Put your name here’);”