1forrest1
1forrest1

Reputation: 83

Display contents (in hex) of 16 bytes at the specified address

I'm attempting to display the contents of a specific address, given a char* to that address. So far I had attempted doing it using the following implementation

int mem_display(char *arguments) {
    int address = *arguments; 
    int* contents_pointer = (int*)address;
    int contents = *contents_pointer;
    printf("Address %p: contents %16x\n", contents_pointer, contents);              
}

But I keep getting a "Segmentation Fault (Core Dumped)" error. I attempted to make a dummy pointer to test on

char foo = 6;  
char *bar = &foo;

But the error still persists

Upvotes: 2

Views: 5055

Answers (6)

Kajienk
Kajienk

Reputation: 111

For quite a long time I use following function for printing content of memory area:

    /*************************************************************/
    /**
      * Function to dump memory area
      * \param address     start address
      * \param len         length of memory area
      */
    /*************************************************************/
    void dump( void* address, int len ) noexcept{
        int i;
      printf("dump from 0x%lX (%d bytes)\n",(long)address, len);
      printf("=============================================");
      for(i=0; i<len; i++){
        if(i%16==0){printf("\n");}
         printf("%2X ",(*((char*)address+i))&0xFF);
      }
      printf("\n=============================================\n");
    }

For C programs delete the noexcept keyword.

Upvotes: 0

Ped7g
Ped7g

Reputation: 16596

I think you are either overcomplicating it, or you didn't describe enough what is the actual input. Is it pointer to pointer?

Anyway, to do it in simple way with some pointer to memory, you can do it like this for example (C-like C++, sorry, done in hurry online at web cpp.sh ):

#include <iostream>

const unsigned char fakeData[] = { 1, 13, 0, 255 };

void mem_display(
    std::FILE* file,
    const unsigned char* memoryPtr,
    const size_t size)
{
    fprintf(file, "Address %p:", (const void*)memoryPtr);
    for (size_t i = 0; i < size; ++i) fprintf(file, " %02hhx", memoryPtr[i]);
    fprintf(file, "\n");
}


int main()
{
    mem_display(stdout, fakeData, 4);
}

Output:

Address 0x4008e6: 01 0d 00 ff

To print 16 bytes just change the size argument.

I can't think of common type having 16 bytes, so I'm not sure why you are trying to print it out as single number, usually the single-byte output like above is used in debuggers (until the user requests different size unit).

Upvotes: 1

zwol
zwol

Reputation: 140659

If you already have a pointer to the address you want to print the contents of, you can feed that straight to printf, like this:

void print_16_bytes_at(const char *arguments)
{
   printf("Address %p: contents", (const void *)arguments);
   for (int i = 0; i < 16; i++)
       printf(" %02x", (unsigned int)(unsigned char)arguments[i]);
   putchar('\n');
}

If arguments isn't a pointer to the memory you want to print the contents of, then I don't understand what it actually is and I need you to explain better.

Notes on the above sample code:

  1. To use %p without provoking undefined behavior, you must explicitly cast the pointer to [const] void * unless it is already [const] void *. Because printf takes a variable number of arguments, the compiler does not know the expected types of its arguments, so it doesn't insert this conversion for you, as it would with a normal function that takes a [const] void * argument.
  2. The double cast (unsigned int)(unsigned char) forces the char read from arguments[i] to be zero-extended rather than sign-extended to the width of unsigned int. If you don't do that, values from 0x80 on up are liable to be printed with a bunch of leading Fs (e.g. ffffff80) which is probably not what you want.
  3. This will still segfault if there aren't 16 bytes of readable memory at the supplied address. In your example

    char foo = 6;
    print_16_bytes_at(&foo);
    

    there is only guaranteed to be one byte of readable memory at the address of foo. (It will probably work on any computer you can readily get at, but it's still allowed to crash per the letter of the C standard.)

Upvotes: 2

Zalman Stern
Zalman Stern

Reputation: 3191

There are a few issues with the original code. First, it is indirecting the passed in pointer twice. It is treating arguments as a pointer to a pointer to the contents to be printed. Since arguments is a pointer to char, this is definitely wrong. (It will end up reading from a very small address, which is a definite segmentation violation or other crash on most architectures.)

Second, unless you know the arguments pointer is aligned appropriately, loading an int via that pointer may crash due to an unaligned access. (Which may well show up as a segmentation violation.) You likely cannot assume proper alignment for this routine.

Third, if you need to print 16 bytes, then an int will (typically) only get 4 or 8 of them. It will be trickier to use standard printing routines to concatenate all the pieces than to write a byte by byte loop. (See above answer for an example of such a loop.)

Upvotes: 1

gsamaras
gsamaras

Reputation: 73376

You need to iterate over the contents of the address, and print each one separately, until you reach 16. Example code:

#include <stdio.h>

void mem_display(unsigned char *arguments) {
    printf("Address %p: ", arguments);
    int i =0;
    unsigned char* byte_array = arguments;
    while (i < 16)
    {
        printf("%02hhx", byte_array[i]);
        i++;
    }            
}

int main(void) {
    unsigned char foo = 6;  
    unsigned char *bar = &foo;
    mem_display(bar);

    return 0;
}

Output:

Address 0x7ffe5b86a777: 0677A7865BFE7F000060054000000000

Upvotes: 2

melpomene
melpomene

Reputation: 85777

I'm finding it hard to explain what the problem is because almost every single line in your code is wrong.

Here's what I would do:

void mem_display(const void *address) {
    const unsigned char *p = address;
    for (size_t i = 0; i < 16; i++) {
        printf("%02hhx", p[i]);
    }
    putchar('\n');
}

Upvotes: 5

Related Questions