I have this address, 0x8002bf20, and I need to see what's inside there. I know GDB does nice things like "print x" and I'll see something like struct ex {x: 1, y: 2}
I need to see that kind of print output for this address I need to examine.
Thanks.
If you know the type of the structure at that address, you can coerce GDB to print it with:
(gdb) print *(struct mystruct *) 0x8002bf20
If you do not know the type of the structure, then the best you can do is the x command which you already mentioned -- although do be aware that there's no harm in casting to the 'wrong' type, so you can try various structures with print *(struct mystruct *) until the output looks plausible.
Related
I used to work with Java and C++ and now work in a company which primarily programs in C. I almost every other day need to run a gdb on a daemon and get the backtrace. I am never fully able to understand how to get the values out of the structure properly.
Let me give an example:
lets say we have 4 structures:
typedef struct profile_s{
int x;
int y;
gold_t *gold;
}profile_t;
typedef struct copper_s{
int price;
profile_t *prof;
}copper_t;
typedef struct gold_s{
int cost;
}gold_t;
void foo(copper_t *var){
copper_t *variable = var;
bar();
}
void bar(){
}
Now if we want to obtain values of profile and gold, we can obtain those from copper_t pointer variable. I am not sure how to obtain these.
If GDB for this code is on foo function, we can obtain copper pointer value.
When typecasting copper pointer val, why does (copper_t *) variable not work and (copper_t) * variable work in gdb ?
Also, similarly if we wanted to obtain profile and gold values out of this pointer, we will have to typecast those pointers to their respective structures.
now if we do (copper_t) *variable->prof, it gives me profile pointer. How to typecast this expression to get x and y out of it.
p (profile_t)(copper_t) *variable->prof is incorrect.
What is correct expression to get the value ?
Also similarly for gold, how to get (gold_t)(profile_t)(copper_t)variable->prof->gold
Hoping to get some clarity regarding the same.
Edit:
(gdb) p variable->prof
$21 = (profile_t *) 0x7f2bd3343e60
(gdb) p variable
$22 = (copper_t *) 0x7f2a4d202040
(gdb) p (copper_t) *variable
$23 = {
price = 100,
prof = 0x7f2bd3343e60,
}
Now I want to get the profile structure values from this pointer. How to get that.
Also, why would (copper_t) *variable work and (copper_t *)variable print only pointer value.
Ex:
(gdb) p (copper_t *) variable
$24 = (copper_t *) 0x7f2a4d202040
There seem to be a few questions here:
Why do the following 2 commands have different results in gdb?
p (copper_t *) variable
p (copper_t) *variable
In the first case, the typecast applies to the expression variable and tells gdb to treat variable as being a pointer to a copper_t. As seen in the earlier output of p variable, gdb is already aware that variable is a pointer to a copper_t, so the typecast is unnecessary can be left off, leaving the equivalent p variable which just prints the pointer.
In the second case gdb first forms the expression *variable. Given that gdb knows the type of variable to be a pointer to a copper_t, gdb knows that *variable is of type copper_t. So again the typecast is unnecessary and you could just use the command p *variable , which prints out a copper_t structure.
In summary you could have used the following commands to print the pointer and the target of the pointer, respectively.
p variable
p *variable
How does one print out the profile?
p *(variable->prof)
How does one print out the x and y values for the profile, as opposed to the entire profile?
p variable->prof->x
p variable->prof->y
How does one print out the gold structure associated with that variable?
p *(variable->prof->gold)
I'm trying to understand some sample C code that I got with my microcontroller board. I have a really hard time to understand that whole pointer thing. I read a lot of posts in this forum and I also read several tutorials and slowly I get the hang of it :) But...
In my sample code there is the following line of code, which I could not decrypt with any information that I have found yet.
#define SOMENAME ((uint32_t *)0x130010f0)
I understood, that #define simply replaces all occurrences of SOMENAME in the compiled code with the respective statement (don't know if this is correctly explained, but I really think I got what this is doing).
Now, what I could imagine, what the rest of the statement means is the following:
SOMENAME is now a pointer to the address 0x130010f0 but without being an actual variable.
Is this correct? And I could kind of use it for example as: printf("value at address 0x130010f0: %p",SOMENAME) because the compiler would replace it with printf("value at address 0x130010f0: %p",((uint32_t *)0x130010f0)) and this gives the value stored at that address? What would be the print statement if I want the address of that pointer? I can't, right? Because the pointer does not have an address as it is not a variable? Very confusing...
The example is quite complex and this definition is also part of other definitions which are pointers to structs of structs of structs, therefore this "simple" example. Below you can find the "whole" structure:
#define ROM_API_TREE ((uint32_t *)0x130010f0)
#define BOOTLOADER_POINTER ((bootloader_tree_t *)ROM_API_TREE)
flash_driver_interface_t *FLASH_API_TREE
#define FLASH_API_TREE BOOTLOADER_POINTER->flashDriver
typedef struct BootloaderTree{
...
const flash_driver_interface_t *flashDriver;
} bootloader_tree_t
typedef struct FlashDriverInterface{
...
status_t (*ffr_get_uuid)(flash_config_t *config, uint8_t *uuid);
} flash_driver_interface_t
/*
* I actually want to understand that statement, but as I fail
* already at the beginning, I posted this question
*/
status_t = FLASH_API_TREE->ffr_get_uuid(config,uuid);
You are correct that SOMENAME get replaced by the preprocessor with ((uint32_t *)0x130010f0). What this gives you is a pointer to a uint32_t, and the value of that pointer is 0x130010f0.
When you then do this:
printf("value at address 0x130010f0: %p",SOMENAME);
You'll actually print the value of the pointer, i.e. 0x130010f0, not what it points to. For that you would need to dereference it, i.e.:
printf("value at address 0x130010f0: %u", *SOMENAME);
This however assumes that 0x130010f0 is a valid address that can be dereferenced and read. This will typically only be the case in some particular embedded environment where the implementation allows it.
As i saw, you basically could understand many things behind the Pointers. The SOMENAME is a macro not a variable right. Before i get to the code, a pointer in general is nothing else but a variable that contains an adress instead of having a value.
printf("value at address 0x130010f0: %p",SOMENAME); is wrong because the %p expects a value not an Adress and you are passing the adress to it, so you all you have to do is to dereference it using the *.
When you write (uint32_t *)0x130010f0 you are casting the adress to the type writteb between parentheses.
Whenever it gets complicated while using pointers try to remember this small example:
int a = 10;
int *p = &a;// declare pointer of type integer. This is valid, adress of an integer variable contains adress of integer variable
int *j; //declare pointer of type integer
j = &a; //correct, because j expects an adress.
*j = &a; //wrong *j expects a value
printf("value of p: %p", *p);
printf("adress of p: %p", p); //or &p
This shows that your microcontroller board has a program accessible 32-bit device.
I say 'accessible' because this device could be readable, writable or both.
I use the kinda general term 'device' because it could be all kinds of things. Quite often it's a register that simply stores a value, but it could also be a FIFO chip returning the next stored value at every read.
Assuming it's a register: These registers often consist of separate bits or small groups of bits to represent some function. In that case you'd see bitfield struct declarations that look like this (two 16-bit fields as example):
struct {
uint32_t someField : 16;
uint32_t otherField : 16;
} fields;
I have a 2 dimensional array of structures, like so:
struct foo {
int bar;
float baz;
};
I'm actually learning about OS development right now, and one thing I'm trying to do is created a 2d array of these structures with the dimensions 80x25:
struct foo foobar[80][25];
Though I need to set it to the address 0xb8000, since this is where the video memory starts. Is there any way I can specify the address in which my array starts?
So far I have tried doing this:
struct foo foobar[80][25];
*foobar = (struct foo) 0xb8000;
But this doesn't work. Edit: also, is doing something like this legal and/or possible to the c99 standard?
You cannot declare array at a specific location, but you can use a pointer:
struct foo *x;
x = (struct foo*)0xb8000;
This should work, but probably the operating system will complain if you tried that from a normal program, unless it is DOS or something like that.
I've just started to learn C so please be kind.
From what I've read so far regarding pointers:
int * test1; //this is a pointer which is basically an address to the process
//memory and usually has the size of 2 bytes (not necessarily, I know)
float test2; //this is an actual value and usually has the size of 4 bytes,
//being of float type
test2 = 3.0; //this assigns 3 to `test2`
Now, what I don't completely understand:
*test1 = 3; //does this assign 3 at the address
//specified by `pointerValue`?
test1 = 3; //this says that the pointer is basically pointing
//at the 3rd byte in process memory,
//which is somehow useless, since anything could be there
&test1; //this I really don't get,
//is it the pointer to the pointer?
//Meaning, the address at which the pointer address is kept?
//Is it of any use?
Similarly:
*test2; //does this has any sense?
&test2; //is this the address at which the 'test2' value is found?
//If so, it's a pointer, which means that you can have pointers pointing
//both to the heap address space and stack address space.
//I ask because I've always been confused by people who speak about
//pointers only in the heap context.
Great question.
Your first block is correct. A pointer is a variable that holds the address of some data. The type of that pointer tells the code how to interpret the contents of the address being held by that pointer.
The construct:
*test1 = 3
Is called the deferencing of a pointer. That means, you can access the address that the pointer points to and read and write to it like a normal variable. Note:
int *test;
/*
* test is a pointer to an int - (int *)
* *test behaves like an int - (int)
*
* So you can thing of (*test) as a pesudo-variable which has the type 'int'
*/
The above is just a mnemonic device that I use.
It is rare that you ever assign a numeric value to a pointer... maybe if you're developing for a specific environment which has some 'well-known' memory addresses, but at your level, I wouldn't worry to much about that.
Using
*test2
would ultimately result in an error. You'd be trying to deference something that is not a pointer, so you're likely to get some kind of system error as who knows where it is pointing.
&test1 and &test2 are, indeed, pointers to test1 and test2.
Pointers to pointers are very useful and a search of pointer to a pointer will lead you to some resources that are way better than I am.
It looks like you've got the first part right.
An incidental thought: there are various conventions about where to put that * sign. I prefer mine nestled with the variable name, as in int *test1 while others prefer int* test1. I'm not sure how common it is to have it floating in the middle.
Another incidental thought: test2 = 3.0 assigns a floating-point 3 to test2. The same end could be achieved with test2=3, in which case the 3 is implicitly converted from an integer to a floating point number. The convention you have chosen is probably safer in terms of clarity, but is not strictly necessary.
Non-incidentals
*test1=3 does assign 3 to the address specified by test.
test1=3 is a line that has meaning, but which I consider meaningless. We do not know what is at memory location 3, if it is safe to touch it, or even if we are allowed to touch it.
That's why it's handy to use something like
int var=3;
int *pointy=&var;
*pointy=4;
//Now var==4.
The command &var returns the memory location of var and stores it in pointy so that we can later access it with *pointy.
But I could also do something like this:
int var[]={1,2,3};
int *pointy=&var;
int *offset=2;
*(pointy+offset)=4;
//Now var[2]==4.
And this is where you might legitimately see something like test1=3: pointers can be added and subtracted just like numbers, so you can store offsets like this.
&test1 is a pointer to a pointer, but that sounds kind of confusing to me. It's really the address in memory where the value of test1 is stored. And test1 just happens to store as its value the address of another variable. Once you start thinking of pointers in this way (address in memory, value stored there), they become easier to work with... or at least I think so.
I don't know if *test2 has "meaning", per se. In principle, it could have a use in that we might imagine that the * command will take the value of test2 to be some location in memory, and it will return the value it finds there. But since you define test2 as a float, it is difficult to predict where in memory we would end up, setting test2=3 will not move us to the third spot of anything (look up the IEEE754 specification to see why). But I would be surprised if a compiler would allow such thing.
Let's look at another quick example:
int var=3;
int pointy1=&var;
int pointy2=&pointy1;
*pointy1=4; //Now var==4
**pointy2=5; //Now var==5
So you see that you can chain pointers together like this, as many in a row as you'd like. This might show up if you had an array of pointers which was filled with the addresses of many structures you'd created from dynamic memory, and those structures contained pointers to dynamically allocated things themselves. When the time comes to use a pointer to a pointer, you'll probably know it. For now, don't worry too much about them.
First let's add some confusion: the word "pointer" can refer to either a variable (or object) with a pointer type, or an expression with the pointer type. In most cases, when people talk about "pointers" they mean pointer variables.
A pointer can (must) point to a thing (An "object" in standards parlance). It can only point to the right kind of thing; a pointer to int is not supposed to point to a float object. A pointer can also be NULL; in that case there is no thing to point to.
A pointertype is also a type, and a pointer object is also an object. So it is allowable to construct a pointer to pointer: the pointer-to-pointer just stores the addres of the pointer object.
What a pointer can not be:
It cannot point to a value: p = &4; is impossible. 4 is a literal value, which is not stored in an object, and thus has no address.
the same goes for expressions: p = &(1+4); is impossible, because the expression "1+4" does not have a location.
the same goes for return value p = &sin(pi); is impossible; the return value is not an object and thus has no address.
variables marked as "register" (almost distinct now) cannot have an address.
you cannot take the address of a bitfield, basically because these can be smaller than character (or have a finer granularity), hence it would be possible that different bitmasks would have the same address.
There are some "exceptions" to the above skeletton (void pointers, casting, pointing one element beyond an array object) but for clarity these should be seen as refinements/amendments, IMHO.
I have run gdb, as my code show segfault. I understand that the code that give the error is
210 if (colour_s->colorlist.colorlist_id == 1)
(gdb) print colour_s
$1 = (car_colour_list_t_slot *) 0x21
(gdb) print colorlist
$2 = (car_colour_list_t *) 0x12d1a80
(gdb) print colour_s->colorlist
Cannot access memory at address 0x21
typedef struct {
int colorlist_id;
} car_colour_list_t;
typedef struct _car_colour_list_t_slot {
car_colour_list_t colorlist;
struct _car_colour_list_t_slot *next, *prev;
} car_colour_list_t_slot;
car_colour_list_t_slot *colour_s;
colour_s = (car_colour_list_t_slot *)malloc(sizeof(car_colour_list_t_slot));
car_colour_list_t *colorlist;
colorlist = (car_colour_list_t *)malloc(sizeof(car_colour_list_t));
I have already assigned those pointers memory, but when I tried to print colour_s->colorlist it fails (can not access memory at address 0x21)
Can anyone understand why this happens, although I have already assign memory to each poitner?
Thank you
The colour_s pointer is definitely invalid. There is no doubt about it. GDB is simply informing you of this fact. (Any pointer near 0x0 is invalid, and any pointer with a residue modulo 4 is invalid for your structure.) The malloc function will never return 0x21.
There are lots of ways your program can do this. They boil down to two basic types of errors in your program:
colour_s was not initialized.
colour_s was initialized, but it was accidentally overwritten by an error in a different part of your code.
there is an error in GDB or your compiler (not worth considering)
Run your program with Valgrind or set a watchpoint on colour_s. These will help you discover where the error is in your code.
As an alternative exercise, see if you can find the error just by reading your code, without running it. Read carefully. This kind of exercise will make you a better programmer.