Skip to content

Instantly share code, notes, and snippets.

@daladim
Last active July 7, 2022 13:25
Show Gist options
  • Save daladim/7f2b2b3193763b0782190291358d5aa2 to your computer and use it in GitHub Desktop.
Save daladim/7f2b2b3193763b0782190291358d5aa2 to your computer and use it in GitHub Desktop.
Snippets in various languages to provide a hex dump of a part of the memory
// Hexdump snippet
// It may be more up-to-date on https://gist.github.com/daladim/7f2b2b3193763b0782190291358d5aa2
// Adpated from Gist c527a3acb6f152796a580401057c78b4
// This code can be compiled as C++, but it is almost straight C.
// It uses default arguments for the hexdump function (which are a C++ feature)
// In case you want to use it in C code, just remove them.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void hexdump(const void *mem, unsigned int len, const char* title="", int show_base=1){
// `title` will be printed at the beginning of the dump
// If `show_base` is true, the address of `mem` will be printed at the beginning of each line
const int HEXDUMP_COLS = 16;
unsigned int i, j;
if(title && strcmp(title, "") != 0){
printf("%s:\n", title);
}
for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % HEXDUMP_COLS) : 0); i++)
{
// print (base +) offset
if(i % HEXDUMP_COLS == 0){
if(show_base){
printf("%p + ", mem);
}
printf("0x%06x: ", i);
}
// print hex data
if(i % 8 == 0){
putchar(' ');
}
if(i < len){
printf("%02x ", 0xFF & ((char*)mem)[i]);
}else{
// end of block, just aligning for ASCII dump
printf(" ");
}
// print ASCII dump
if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)){
for(j = i - (HEXDUMP_COLS - 1); j <= i; j++){
if(j % 8 == 0){
putchar(' ');
}
if(j >= len){
// end of block, not really printing
putchar(' ');
}else if(isprint(((char*)mem)[j])){
// printable char
putchar(0xFF & ((char*)mem)[j]);
}else{
// other char
putchar('.');
}
}
putchar('\n');
}
}
}
// Hexdump snippet
// It may be more up-to-date on https://gist.github.com/daladim/7f2b2b3193763b0782190291358d5aa2
// Note: these two functions could be turned into a single macro (that could also take care of defaulting length to `std::mem::size_of<T>()` in case it is not specified otherwise)
/// This dumps `len` bytes of memory starting at `mem`'s address onto stdout
///
/// `len` can be arbitrary. If you only want to see the memory inside your `T`, use `std::mem::size_of<T>()`
fn hexdump<T: ?Sized>(mem: &T, len: usize, show_base_address: bool) {
hexdump_ptr(mem as *const T, len, show_base_address);
}
/// This dumps `len` bytes of memory starting at `ptr` onto stdout
///
/// `len` can be arbitrary. If you only want to see the memory inside your `T`, use `std::mem::size_of<T>()`
fn hexdump_ptr<T: ?Sized>(ptr: *const T, len: usize, show_base_address: bool) {
use std::cmp::min;
const DUMP_WIDTH: isize = 8; // must be a power of 2
fn printable_from_ascii(a: u8) -> char {
if a < 0x20 {
return '.';
} else if a >= 0x7f {
return '.';
}
a as _
}
let data = ptr as *const u8;
let base_txt = if show_base_address { format!("{:p} + ", ptr) } else { "".into() };
let mut offset = 0;
loop {
let mut hex = String::new();
let mut ascii = String::new();
for i in offset..min(offset+DUMP_WIDTH, len as isize) {
hex.push_str( &format!("{:02x} ", unsafe {*data.offset(i)} ));
ascii.push( printable_from_ascii( unsafe {*data.offset(i)} ));
if (i+1) % (DUMP_WIDTH/2) == 0 {
hex.push(' ');
ascii.push(' ');
}
}
let hex_width = (DUMP_WIDTH * 3 + 3) as usize;
println!("{}{:06x?}: {:4$}{}", base_txt, offset, hex, ascii, hex_width);
offset = offset + DUMP_WIDTH;
if offset >= len as isize {
break;
}
}
}
Snippets in various languages to provide a hex dump of a part of the memory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment