Thread overview
Little memdump
Mar 13, 2007
Tom
Mar 13, 2007
David L.Davis
Mar 14, 2007
Tom
Mar 14, 2007
Derek Parnell
Mar 14, 2007
Tom
Mar 15, 2007
Jeff McGlynn
Mar 15, 2007
Bill Baxter
Mar 15, 2007
Jeff McGlynn
March 13, 2007
Hi people,

  I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.

Kind regards,
--
Tom;

void memdump(void* from, uint length)
{
	uint plen= 0;
	ubyte* adr(uint i) { return cast(ubyte*)from+i+plen; }
	char   chr(uint i) { return cast(char)*(cast(ubyte*)from+i+plen); }
	ubyte  byt(uint i) { return cast(ubyte)*(cast(ubyte*)from+i+plen); }

	while (length>0) {		
		printf("+-----------+-----------+-----------+-----------+\n|");
		for (uint i=0; i<16; i+=4) {
			printf("0x%08X |", adr(i));
		}
		printf("\n|");
		for (uint i=0, j=0; i<16; i++, j=(j+1)%4) {
			if (i < length) {
				if (chr(i) < 14) printf("  "); else printf(" %c", chr(i));
			} else
				printf("  ");
			if (j==3) printf("|"); else printf(" ");
		}
		printf("\n|");
		for (uint i=0, j=0; i<16; i++, j=(j+1)%4) {
			if (i < length)
				printf("%02X", byt(i));
			else
				printf("  ");
			if (j==3) printf("|"); else printf(" ");
		}
		printf("\n");

		if (length > 16)
			length-= 16;
		else
			length= 0;

		plen+= 16;
	}
	printf("+-----------+-----------+-----------+-----------+\n");
}
March 13, 2007
Tom Wrote:

> Hi people,
> 
>    I just wanted to share with you a *very-humble* memdump procedure
> that has been very helpful to me in my tedious D-debugging nights.
> 
> Kind regards,
> --
> Tom;
> 

Hi Tom,

    Thanks for sharing your useful code...hope you don't mind that I've replaced the 'C' printf()s with 'D' writef()s functions, and added some test data to it.

// To compile the test example: dmd memdump.d -version=memdump
// To compile: dmd MySource.d memdump.d
private import io = std.stdio;

void memdump(void* from, uint length)
{
    uint   plen = 0;
    ubyte* adr(uint i) { return cast(ubyte*)from + i + plen; }
    char   chr(uint i)
    { return cast(char)*(cast(ubyte*)from + i + plen); }
    ubyte  byt(uint i)
    { return cast(ubyte)*(cast(ubyte*)from + i + plen); }
    char   c = '\0';

    while (length > 0)
    {
        io.writef("+-----------+-----------+-----------+-----------+\n|");

        for (uint i = 0; i < 16; i += 4)
            io.writef("0x%0.8X |", adr(i));

        io.writef("\n|");

        for (uint i = 0, j = 0; i < 16; i++, j = (j + 1) % 4)
        {
            if (i < length)
            {
            	c = chr(i);

                if (c < 14 || c > 127)
                    io.writef("  ");
                else
                    io.writef(" %s", chr(i));
            }
            else
                io.writef("  ");

            if (j == 3)
                io.writef("|");
            else
                io.writef(" ");
        }

        io.writef("\n|");

        for (uint i = 0, j = 0; i < 16; i++, j = (j + 1) % 4)
        {
            if (i < length)
                io.writef("%0.2X", byt(i));
            else
                io.writef("  ");

            if (j == 3)
                io.writef("|");
            else
                io.writef(" ");
        }

        io.writef("\n");

        if (length > 16)
            length -= 16;
        else
            length = 0;

        plen += 16;
    }

    io.writef("+-----------+-----------+-----------+-----------+\n");
}

version(memdump)
{
void main()
{
    char[]  s =
        "This is a text message for memdump to use as test data.";

    ubyte[] b = [0x4D, 0x5A, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00,
                      0x04, 0x00, 0x10, 0x00, 0xFF, 0xFF, 0x00, 0x00,
                      0xFE, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
                      0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73,
                      0x20, 0x57, 0x69, 0x6E, 0x33, 0x32, 0x00, 0x00];

    io.writefln("dump string data...");
    memdump(cast(void*)s, s.length);
    io.writefln();

    io.writefln("dump binary data...");
    memdump(cast(void*)b, b.length);
}
}

Take Care,
    David L.

March 14, 2007
David L.Davis escribió:
> Tom Wrote:
> 
>> Hi people,
>>
>>    I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.
>>
>> Kind regards,
>> --
>> Tom;
>>
> 
> Hi Tom,
> 
>     Thanks for sharing your useful code...hope you don't mind that I've replaced the 'C' printf()s with 'D' writef()s functions, and added some test data to it.

I'm glad you found it useful.
Please, feel free to enhance it (or whatever). I wrote it in 10 minutes so... ;) (it has been very useful to me for a long time now, though).

--
Tom;
March 14, 2007
On Tue, 13 Mar 2007 22:37:55 -0300, Tom wrote:

> David L.Davis escribió:
>> Tom Wrote:
>> 
>>> Hi people,
>>>
>>>    I just wanted to share with you a *very-humble* memdump procedure
>>> that has been very helpful to me in my tedious D-debugging nights.
>>>
>>> Kind regards,
>>> --
>>> Tom;
>>>
>> 
>> Hi Tom,
>> 
>>     Thanks for sharing your useful code...hope you don't mind that I've replaced the 'C' printf()s with 'D' writef()s functions, and added some test data to it.
> 
> I'm glad you found it useful.
> Please, feel free to enhance it (or whatever). I wrote it in 10 minutes
> so... ;) (it has been very useful to me for a long time now, though).

I once wrote something very similar, but not as compact as yours <g>.

import std.cstream;

// Displays a formatted memory dump.
// pFrom is the starting address
// pLength is the number of bytes to display
// pTitle is an optional Title for the display
// pDest is the destination: Either std.cstream.dout or std.cstream.derr
(default)

void format_mem(void*  pFrom,
                uint   pLength,
                char[] pTitle = "",
                CFile  pDest = derr)
{
    void* lEnd;
    void* lAddr;
    void* lRow;
    uint  lDispCnt;

    // Calc last byte address + 1
    lEnd    = cast(ubyte *)pFrom + pLength;
    // Calc starting address for display purposes.
    lAddr   = cast(void *)((cast(uint)pFrom) & 0xFFFFFFF0);

    // Show any supplied title.
    if (pTitle.length > 0)
        pDest.writefln("%s", pTitle);

    // Show the header columns.
    pDest.writefln("Memory contents at address:%08X for %d bytes\n"
                    "           "
                    "+0+1+2+3 +4+5+6+7  +8+9+A+B +C+D+E+F  "
                    " |----------------|",
                    cast(int)pFrom, pLength);

    // Repeat for groups of 16 address locations.
    while (lAddr < lEnd)
    {
        // Show the address for this line.
        pDest.writef("  %08X ", cast(uint)lAddr);
        // Calc this line's end address
        lRow = cast(ubyte *)lAddr + 16;

        // One-off code to skip over possible leading addresses not used.
        while(cast(uint)lAddr < cast(uint)pFrom)
        {
            pDest.writef("  ");
            // Show padding if needed.
            if (((cast(uint)lAddr) & 3u) == 3u) pDest.writef(" ");
            if (((cast(uint)lAddr) & 7u) == 7u) pDest.writef(" ");
            lAddr += 1;
            lDispCnt++;
        }

        // Display each byte as a 2-digit hex value.
        while( lAddr < lRow)
        {
            if (lAddr < lEnd)
            {
                pDest.writef("%02X", cast(uint)(*cast(ubyte*)lAddr));
            }
            else
            {
                pDest.writef("  ");
            }
            // Show padding if needed.
            if (((cast(uint)lAddr) & 3u) == 3u) pDest.writef(" ");
            if (((cast(uint)lAddr) & 7u) == 7u) pDest.writef(" ");
            lAddr += 1;
        }

        // Begin the 'string' display part of the line.
        pDest.writef(" |");

        //  Skip over any leading addresses not actually used.
        while(lDispCnt > 0)
        {
            pDest.writef(" ");
            lDispCnt--;
        }

        // Display each byte as an ASCII char if possible else use a dot.
        while( cast(uint)pFrom < cast(uint)lAddr)
        {
            ubyte lChar;
            char[1] lStr;
            if (pFrom < lEnd)
            {
                lChar = *cast(ubyte*)pFrom;
                if (lChar < cast(ubyte)' ')
                    pDest.writef(".");
                else if (lChar > cast(ubyte)'~')
                    pDest.writef(".");
                else
                {
                    lStr[0] = cast(char)lChar;
                    pDest.writef("%s", lStr);
                }
            }
            else
                pDest.writef(" ");

            pFrom += 1;
        }
        // End of line.
        pDest.writefln("|");
    }

    // End of dump display.
    pDest.writefln("           "
                    "------------------------------------  "
                    " |----------------|"
                   );
}


// Just used to test this routine.
debug(format_mem)
{
void main(char[][] pArgs)
{
    foreach(char[] s; pArgs)
        format_mem(s.ptr, s.length * s[0].sizeof, s);
    format_mem(pArgs.ptr, pArgs.length * pArgs[0].sizeof, "pArgs");

    format_mem(cast(void *)&main, 100, "main()");
    format_mem(cast(void *)&format_mem, 100, "format_mem()");

    format_mem(cast(void *)new char[80], 100 );
}
}

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
14/03/2007 1:32:03 PM
March 14, 2007
Derek Parnell escribió:
> On Tue, 13 Mar 2007 22:37:55 -0300, Tom wrote:
> 
>> David L.Davis escribió:
>>> Tom Wrote:
>>>
>>>> Hi people,
>>>>
>>>>    I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.
>>>>
>>>> Kind regards,
>>>> --
>>>> Tom;
>>>>
>>> Hi Tom,
>>>
>>>     Thanks for sharing your useful code...hope you don't mind that I've replaced the 'C' printf()s with 'D' writef()s functions, and added some test data to it.
>> I'm glad you found it useful.
>> Please, feel free to enhance it (or whatever). I wrote it in 10 minutes so... ;) (it has been very useful to me for a long time now, though).
> 
> I once wrote something very similar, but not as compact as yours <g>.

Nice. I can see why it isn't that compact, it's closer to hexdump than mine :P

Regards,
--
Tom;
March 15, 2007
On 2007-03-12 17:40:16 -0700, Tom <tom@nospam.com> said:

> Hi people,
> 
>    I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.
> 
> Kind regards,

Here is the code that I use:

import std.stdio;
import std.ctype;

void debug_dump(ubyte[] data) {
	uint len = data.length;
	writefln("=== GOT %d BYTES:", len);
	
	for(uint offset = 0; offset < len; offset += 20) {
		uint end = offset + 20;
		if (end > len) end = len;
		
		for(uint ix = offset; ix < end; ++ix) {
			writef("%02X ", data[ix]);
		}
		
		if (offset + 20 > len) {
			char[] space = new char[3 * (offset + 20 - len)];
			space[] = ' ';
			
			writef(space);
		}
		
		writef("| ");
		
		for(uint ix = offset; ix < end; ++ix) {
			if (isprint(data[ix])) {
				writef("%s", cast(char) data[ix]);
			} else {
				writef(".");
			}
		}
		
		writefln();
	}

	writefln();
}

-- 

Jeff McGlynn

March 15, 2007
Jeff McGlynn wrote:
> On 2007-03-12 17:40:16 -0700, Tom <tom@nospam.com> said:
> 
>> Hi people,
>>
>>    I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.
>>
>> Kind regards,
> 
> Here is the code that I use:
> 
> import std.stdio;
> import std.ctype;
> 
> void debug_dump(ubyte[] data) {
>     uint len = data.length;
>     writefln("=== GOT %d BYTES:", len);
>         for(uint offset = 0; offset < len; offset += 20) {
>         uint end = offset + 20;
>         if (end > len) end = len;
>                for(uint ix = offset; ix < end; ++ix) {
>             writef("%02X ", data[ix]);
>         }
>                if (offset + 20 > len) {
>             char[] space = new char[3 * (offset + 20 - len)];
>             space[] = ' ';
>                        writef(space);
>         }
>                writef("| ");
>                for(uint ix = offset; ix < end; ++ix) {
>             if (isprint(data[ix])) {
>                 writef("%s", cast(char) data[ix]);
>             } else {
>                 writef(".");
>             }
>         }
>                writefln();
>     }
> 
>     writefln();
> }
> 


Just curious -- what are you guys doing that you have to dump memory so often?

--bb
March 15, 2007
On 2007-03-15 02:03:44 -0700, Bill Baxter <dnewsgroup@billbaxter.com> said:

> Jeff McGlynn wrote:
>> On 2007-03-12 17:40:16 -0700, Tom <tom@nospam.com> said:
>> 
>>> Hi people,
>>> 
>>>    I just wanted to share with you a *very-humble* memdump procedure that has been very helpful to me in my tedious D-debugging nights.
>>> 
>>> Kind regards,
>> 
>> Here is the code that I use:
>> 
>> import std.stdio;
>> import std.ctype;
>> 
>> void debug_dump(ubyte[] data) {
>>     uint len = data.length;
>>     writefln("=== GOT %d BYTES:", len);
>>         for(uint offset = 0; offset < len; offset += 20) {
>>         uint end = offset + 20;
>>         if (end > len) end = len;
>>                for(uint ix = offset; ix < end; ++ix) {
>>             writef("%02X ", data[ix]);
>>         }
>>                if (offset + 20 > len) {
>>             char[] space = new char[3 * (offset + 20 - len)];
>>             space[] = ' ';
>>                        writef(space);
>>         }
>>                writef("| ");
>>                for(uint ix = offset; ix < end; ++ix) {
>>             if (isprint(data[ix])) {
>>                 writef("%s", cast(char) data[ix]);
>>             } else {
>>                 writef(".");
>>             }
>>         }
>>                writefln();
>>     }
>> 
>>     writefln();
>> }
>> 
> 
> 
> Just curious -- what are you guys doing that you have to dump memory so often?
> 
> --bb

I recently wrote a FastCGI server, which uses a binary protocol.  Using this allowed me to debug protocol errors without adding new code each time.

-- 

Jeff McGlynn