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

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

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');
}

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

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:
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.
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.
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.)

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.)

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).

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.

Related

How to convert a byte array of size 64 to a list of double values in Arduino C++?

void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
Here result would be a list of double values with count = 8.
Your problem is two things. You have some typos and misunderstanding. And the C++ standard is somewhat broken in this area.
I'll try to fix both.
First, a helper function called laundry_pods. It takes raw memory and "launders" it into an array of a type of your choice, so long as you pick a pod type:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
now simply do
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
and pdouble is a pointer to memory of ch interpreted as an array of 8 doubles. (It is not a copy of it, it interprets those bytes in-place).
While laundry_pods appears to copy the bytes around, both g++ and clang optimize it down into a binary noop. The seeming copying of bytes around is a way to get around aliasing restrictions and object lifetime rules in the C++ standard.
It relies on arrays of pod not having extra bookkeeping overhead (which C++ implementations are free to do; none do that I know of. That is what the non-static assert double-checks), but it returns a pointer to a real honest to goodness array of double. If you want to avoid that assumption, you could instead create each doulbe as a separate object. However, then they aren't an array, and pointer arithmetic over non-arrays is fraught as far as the standard is concerned.
The use of the term "launder" has to do with getting around aliasing and object lifetime requirements. The function does nothing at runtime, but in the C++ abstract machine it takes the memory and converts it into binary identical memory that is now a bunch of doubles.
The trick of doing this kind of "conversion" is to always cast the double* to a char* (or unsigned char or std::byte). Never the other way round.
You should be able to do something like this:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
Assuming that type byte is an alias of char or unsigned char or std::byte.
I am not completly sure what you are trying to achieve here because of the code (sizeof(ch) / sizeof(*ch)) which does not make sense for an array of undefined size.
If you have a byte-Array (POD data type; something like a typedef char byte;) then this most simple solution would be a reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
This allows you to use result[0]..result[7] as long as ch[] is valid and contains at least 64 bytes. Be aware that this construct does not generate code. It tells the compiler that result[0] corresponds to ch[0..7] and so on. An access to result[] will result in an access to ch[].
But you have to know the number of elements in ch[] to calculate the number of valid double elements in result.
If you need a copy (because - for example - the ch[] is a temporary array) you could use
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
So if ch[] is an array with 64 items and a byte is really an 8-bit value, then
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
will provide a std::vector containing 8 double values.
There is another possible method using a union:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
the 8 double values will occupie the same memory as the 64 byte values. So you can write the byte values to byteToDouble.b[] and read the resultingdouble values from byteToDouble.d[].

Request explanation on the behaviour of pointers in array

I m running this using rextester (online compiler). I followed a tutorial but there is something I don't understand.
I thought it would be better to write my question directly inside the code.
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint8_t var1 = 17;
uint8_t var2 = 23;
uint8_t arr[] ={7,9,11};
uint64_t *ptr1;//pointer
uint64_t *ptr2;
uint64_t *ptr3;
int main(void)
{
printf("var1: %d\n", var1) ;
//connecting pointer to address
ptr1 = &var1;
printf("address of ptr1: %d\n", ptr1) ;
printf("value of ptr1: %d\n\n", *ptr1) ;
//connecting pointer to address + 1
ptr2 = &var1 +1;
printf("address of ptr2: %d\n", ptr2) ;
//assign value to pointer
*ptr2 = var2;
printf("value of ptr2: %d\n\n", *ptr2) ;
//try on array
ptr3= &arr;//no need to point element 0, or yes?
printf("address of ptr3: %d\n", ptr3) ;
printf("value of ptr3: %d\n\n", *ptr3) ;//i expect 7
return 0;
}
Any help would be very appreciate to help me understand the right behaviour of pointers in c and cpp
I made a lot of tries but i m not able to link a pointer to an array
Edit after response of mato:
Do you think this is a clean way to work with pointer and array? Or there are better solution which take care of not overwriting memory?
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint16_t var = 17;
uint16_t arr[] ={3,5,7,11,13};
uint16_t *ptr;
int main(void)
{
printf("var: %d\n", var) ;
//connecting pointer to address
ptr = &var;
printf("address of ptr: %d\n", ptr) ;
printf("value of ptr: %d\n\n", *ptr) ;
//try on array
for (uint16_t n =0;n<5;n++){
ptr= &arr[n] ;
printf("item: %d value: %d ads: %d pointer: %d\n", n, arr[n], ptr, *ptr) ;
}
return 0;
}
It seems that you do understand what pointers are and you can use them with basic types.
There are two problems in your code. First is this part:
//connecting pointer to address + 1
ptr2 = &var1 + 1;
Here you assigned some address to variable ptr2. Up to this point there is nothing dangerous about that.
But then you assign a value to memory at that address
//assign value to pointer
*ptr2 = var2;
This is dangerous because you, as a developer, don't know what is stored at that address. Even if you are lucky right now, and that part of memory isn't being used for anything else, it will most likely change once your program gets longer and then you will have hard time searching for the bug.
Now arrays usually are a bit confusing, because when you create an array like this:
uint8_t arr[] = {7,9,11};
three things happen.
Your program allocates continual block of memory, that fits 3 variables of type uint8_t. The 3 variables in this context are called elements.
The elements will get the provided initial values 7, 9 and 11.
An address of first element (the one that contains value 7) will be stored in arr.
So arr is actually of type uint8_t *.
In order to get the last part do what you expect, you just need to change this one line (remove the &):
ptr3 = arr;
EDIT: BTW watch and understand this course and you will be expert on C memory manipulation. Video is a bit dated, but trust me, the guy is great.
EDIT2: I just realised the other answer is absolutely correct, you really need to match the types.
You are doing many mistakes. Up to the point, that g++ does not compile the code and explains why pretty good.
Pointer is an address. There is no "connecting pointer to address". ptr1 = &var1; means literally "store address of var1 in variable named ptr1"
You use incompatible pointer types. So as long as you dereference it (e.g. using *) you are going into undefined behaviour.
I am pretty sure you can reinterpret any type of data as char* or unsigned char*, I image this is true for equivalent types like uint8_t, i.e. single byte types.
You, however, are going the other way, you declare 1-byte data, and are pretending it's a 4 byte int. Basically you force the program to read memory out the variable bounds.
Fact, that *ptr1 and *ptr2 give result you expect is a rather lucky coincidence. Probably memory behind them was zeroed. For ptr3 it isn't because you have filled it with other element of the array (7 and 9).
I believe you also use wrong type specifier for printing. %d is for int, uint8_t should be described as hhu and uint64_t as lu. I am not 100% convinced how fatal this is, because of platform specific widths and integer promotions.
You should use matching types for your pointers and variables.

What does this code do ? (About pointers)

I have this code and im stuck at second line
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}
int* ip = (int*)p; What does this line mean ?
int* ip = (int*)p; What does this line mean ?
It means, "create a pointer to integers which starts at the same address as p."
The function is expecting p to be pointing to a sequence of bytes that represents 5 integers.
The behaviour of this function is only defined if p really was pointing to a sequence of integers before being cast to a const char*
In practice, the author of this code is assuming:
That the sequence of bytes has been encoded in such a way that they truly represent 5 integers on this machine (taking into account word size and endian-ness of the architecture).
that the alignment of the address represented by p is correct for addressing memory as integers (some processors have restrictions in this regard).
It's probably not code you want to copy or learn from, other than as a cautionary tale.
unsigned long check_password(const char* p){
int* ip = (int*)p; // line 2, non-const not required
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i]; // line 6
}
return res;
}
Line 2 declares ip as a pointer to integer and initializes it to (int*)p. (int*)p is a C-style cast, which is in this case resolved to reinterpret_cast<int*>(const_cast<char*>(p)). See
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
ip now points to the memory location of p. When using ip, the memory at that location is interpreted as holding an integer, even though it holds a char; and it can be modified, even though it was initially declared const.
Line 6 treats ip as if it was pointing to the first element of an array of int and adds the ith element of that array to res. It's likely that ip actually points to the first element of an array of char. That means, that each iteration sizeof(int) consecutive elements of that array are interpreted as the representation of a single int.
The intention of this code is probably, that a sequence of 5 ints is passed as an array of char of length sizeof(int)*5.
Note that this code is UB if p doesn't actually point to memory of a size of at least sizeof(int)*5, since the memory in that region is read. I.e. the char-array must be at least of length sizeof(int)*5.
Casting away the const in your code is not required
unsigned long check_password(const char* p){
const int* ip = reinterpret_cast<const int*>(p);
int res = 0;
for (int i = 0; i < 5; ++i){
res += ip[i];
}
return res;
}

Extracting an int out of void*

I have a method that returns void* and it is basically some block of data from allocated shared memory on linux.
The first 4 bytes in that data are an int and I haven't managed to extract that int.
These are the methods what I have tried:
int getNum(void* data)
{
return *(int*)data; // 1
return *(int*)(data & 0xFFFFFFFF); // 2
}
Thanks in advance!
int getNum(void* data)
{
return *(int32_t*)data; // 1
// ^^^^^^^
}
Should work.
Also if you need to worry about unaligned addresses achieved from the void*, you may use #Martin Bonner's suggestion:
int getNum(void* data)
{
int32_t result;
memcpy(&result, data, sizeof(int32_t));
return result;
}
int getNum(void* data)
{
return *(int*)data; // 1
return *(int*)(data & 0xFFFFFFFF); // 2
}
The second method won't even compile; data is a pointer, and you cannot apply the & bitwise and operator to a pointer value. (I don't know why you'd even want to mask a pointer value like that. If it were legal, the mask would do nothing on a 32-bit system, and would probably destroy the pointer value on a 64-bit system.)
As for the first, it should work -- if data is a valid pointer pointing to a properly aligned int object.
If that's failing at run time with a segmentation fault, it probably means either that data is null or otherwise not a valid pointer (in that case you can't do what you're trying to do), or it points to a misaligned address (which won't cause a seg fault if you're on an x86 or x86_64 system; are you?).
To find out what the pointer looks like, try adding this:
printf("data = %p\n", data);
to your getNum function -- or examine the value of data in a debugger.
If alignment is the problem, then you can do this:
int result;
memcpy(&result, data, sizeof result);
return result;
But in that case storing an int value as a misaligned address is an odd thing to do in the first place. It's not necessarily wrong, just a very odd thing to do.
How is the memory that data points to allocated?
Assuming the int is 4 bytes long, and you're operating on Linux, your method will work. If you want a portable method to move ints in pointers, try the open source ptrint module from CCAN. It converts a pointer to int by adding NULL to the int. It converts in the other direction by subtracting NULL, returning a ptrdiff_t.
#include <assert.h>
#include <stdio.h>
int getNum(void* data)
{
return *(int *) data;
}
char buf[16];
int main(void)
{
assert(sizeof(int) == 4);
*(int *)buf = 9;
printf("%c%c%c%c\n", buf[0], buf[1], buf[2], buf[3]);
printf("%d\n", getNum((void *) buf));
return 0;
}
// $ ./foo | cat -tv
// ^I^#^#^#
// 9

Cleaner pointer arithmetic syntax for manipulation with byte offsets

In the following lines of code, I need to adjust the pointer pm by an offset in bytes in one of its fields. Is there an better/easier way to do this, than incessantly casting back and forth from char * and PartitionMap * such that the pointer arithmetic still works out?
PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
pm = (PartitionMap *)(((char *)pm) + pm->partitionMapLength);
}
return pm;
For those that can't grok from the code, it's looping through variable length descriptors in a buffer that inherit from PartitionMap.
Also for those concerned, partitionMapLength always returns lengths that are supported by the system this runs on. The data I'm traversing conforms to the UDF specification.
I often use these templates for this:
template<typename T>
T *add_pointer(T *p, unsigned int n) {
return reinterpret_cast<T *>(reinterpret_cast<char *>(p) + n);
}
template<typename T>
const T *add_pointer(const T *p, unsigned int n) {
return reinterpret_cast<const T *>(reinterpret_cast<const char *>(p) + n);
}
They maintain the type, but add single bytes to them, for example:
T *x = add_pointer(x, 1); // increments x by one byte, regardless of the type of x
Casting is the only way, whether it's to a char* or intptr_t or other some such type, and then to your final type.
You can of course just keep two variables around: a char * to step through the buffer and a PartitionMap * to access it. Makes it a little clearer what's going on.
for (char *ptr = ??, pm = (PartitionMap *)ptr ; index > 0 ; --index)
{
ptr += pm->partitionMapLength;
pm = (PartitionMap *)ptr;
}
return pm;
As others have mentioned you need the casts, but you can hide the ugliness in a macro or function. However, one other thing to keep in mind is alignment requirements. On most processors you can't simply increment a pointer to a type by an arbitrary number of bytes and cast the result back into a pointer to the original type without problems accessing the struct through the new pointer due to misalignment.
One of the few architectures (even if it is about the most popular) that will let you get away with it is the x86 architecture. However, even if you're writing for Windows, you'll want to take this problem into account - Win64 does enforce alignment requirements.
So even accessing the partitionMapLength member through the pointer might crash your program.
You might be able to easily work around this problem using a compiler extension like __unaligned on Windows:
PartitionMap __unaliged *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
for ( ; index > 0 ; --index)
{
pm = (PartitionMap __unaligned *)(((char *)pm) + pm->partitionMapLength);
}
return pm;
Or you can copy the potentially unaligned data into a properly aligned struct:
PartitionMap *pm(reinterpret_cast<PartitionMap *>(partitionMaps));
char* p = reinterpret_cast<char*>( pm);
ParititionMap tmpMap;
for ( ; index > 0 ; --index)
{
p += pm->partitionMapLength;
memcpy( &tmpMap, p, sizeof( newMap));
pm = &tmpMap;
}
// you may need a more spohisticated copy to return something useful
size_t siz = pm->partitionMapLength;
pm = reinterpret_cast<PartitionMap*>( malloc( siz));
if (pm) {
memcpy( pm, p, siz);
}
return pm;
The casting has to be done, but it makes the code nearly unreadable. For readability's sake, isolate it in a static inline function.
What is puzzling me is why you have 'partitionMapLength' in bytes?
Wouldn't it be better if it was in 'partitionMap' units since you anyway cast it?
PartitionMap *pmBase(reinterpret_cast<PartitionMap *>(partitionMaps));
PartitionMap *pm;
...
pm = pmBase + index; // just guessing about your 'index' variable here
Both C and C++ allow you to iterate through an array via pointers and ++:
#include <iostream>
int[] arry = { 0, 1, 2, 3 };
int* ptr = arry;
while (*ptr != 3) {
std::cout << *ptr << '\n';
++ptr;
}
For this to work, adding to pointers is defined to take the memory address stored in the pointer and then add the sizeof whatever the type is times the value being added. For instance, in our example ++ptr adds 1 * sizeof(int) to the memory address stored in ptr.
If you have a pointer to a type, and want to advance a particular number of bytes from that spot, the only way to do so is to cast to char* (because sizeof(char) is defined to be one).