www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Little memdump

reply Tom <tom nospam.com> writes:
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");
}
Mar 12 2007
next sibling parent reply David L.Davis <SpottedTiger yahoo.com> writes:
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.
Mar 13 2007
parent reply Tom <tom nospam.com> writes:
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;
Mar 13 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
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
Mar 13 2007
parent Tom <tom nospam.com> writes:
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;

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.

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;
Mar 13 2007
prev sibling parent reply Jeff McGlynn <d jeffrules.com> writes:
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
Mar 15 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Mar 15 2007
parent Jeff McGlynn <d jeffrules.com> writes:
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
Mar 15 2007