In GDB, can you set memory as if it were a char array? - c

Say for instance I have a 32 element unsigned char array at address 0xdeadbeef. I would like to overwrite the contents of the array in memory. I am not compiled with -g, and so cannot just do a "set [variable name] = [my value]".
Is it possible to set the contents of the memory all at once?
I've seen someone try set *((unsigned char*) 0xdeadbeef) = "abcdefghijklmnop", but this doesn't appear to work.
Alternatively, if it isn't possible (for instance, because how would gdb know to convert that to the hex ascii representation?), is it possible to give multiple bytes, words, etc all at once? For example, I could just calculate the value in hex that I want the array to represent, but can I feed it all at once? Something like: set 0xdeadbeef = 0x4142434445464748495051

There's alternative of writing char array in one command, without standard functions like strcpy().
set *(char [CHAR_ARRAY_SIZE] *) <WRITE_ADDRESS> = "YOUR_CHAR_ARRAY"
where CHAR_ARRAY_SIZE is the size of YOUR_CHAR_ARRAY, plus extra NULL byte (null-terminated string).
e.g.
set *(char [15] *) 0x20018000 = "Write a string"

(Posting this just so the question has an "official" answer)
Carl's statements in the comments are entirely correct. You can do the following in gdb:
call strcpy(0xdeadbeef, "mystring")
This works for any of the functions included in the statically linked C library (memset, strncpy, etc).

Related

How do I initialize a char array with a memory address in C?

I'm in a sophomore C class and this project is about dealing with pointers and designing a memory dump function. So I've been able to struggle through the pointers and got a beginning and ending address to dump, even bitmasked it, and I wanted to initialize a char array with the beginning memory address. I initialize it with the same variable storing my masked beginning address but when I print the array, it contains a different memory address. Here's the function:
void memDump(void *base, int bytes)
{
unsigned char *begin;
begin = base;//beginning of range of memory
unsigned char *end;// ending range of memory
end = base + bytes;
int a, b;
long long int d=base;
d=d&0xFFFFF0; //trying to bitmask
long long int e=end;
e = e&0xFFFF0; //masked off the beginning and ending range
char c[16]={d}; //loop variables
printf("%x", c);
for (a=begin; a<=end; a+=16)
{
printf("\n%016X\n", d);
printf("%016X\n", a);
printf("%016X", e);
}
}
Sorry guys, i can't find something similar and this is my last resort. Thanks!
Update: Thanks for the insight everyone, reading some more about C and some articles on how to debug helped me out.
You cannot "initialize a char array" with some "memory address." A char array can only be initialized with characters.
Stackoverflow is not about doing your homework for you, so I will give you some advice, and then you can try implementing it. If you cannot put the advice into code, then you do not deserve to turn in a completed assignment.
First of all, once you have bitmasked your "d", you need to store it back into "begin", so that you have a pointer from which you can start reading bytes to dump.
This instruction:
printf( "%08p ", begin );
Will render the hexadecimal representation of your "begin" address in 8 characters, followed by a space. This is how you need to begin each row of your memory dump.
The instruction:
printf( "%02x ", *(begin++) );
gets the byte pointed by "begin", and renders the hexadecimal representation of that byte in two characters, followed by a space. It then increments "begin", to point to the next byte. You need to do this 8 or 16 times, depending on how wide you want your memory dump to be, then do a printf( "\n" ) to move to the next line.
Then you need to keep repeating the above until your "begin" has exceeded your "end". (So, you are looking at an outer loop, for each row, and an inner loop, for each byte within the row.)
I hope this helps.
As #Jean-FrançoisFabre observed,
char c[16]={d};
probably does not do what you think it does. That is, unless what you think it does is convert the long long int value stored in d to type char (producing an implementation-defined result drawn from a much smaller range than that of d itself), initializing the first element of array c with that value, and initializing the other fifteen with 0. I can't imagine what you would want to do with the result, but since you actually don't do anything with it, that's probably moot.
As I observed myself,
printf("%x", c);
also probably does not do what you think it does. Indeed, you cannot rely on it to do any particular thing, because its behavior is undefined. You are passing a pointer to the first element of c as the second argument, but a value of type unsigned int will be expected instead (based on the format). In any case, this neither "print[s] the array" nor tells you anything about what it contains.
I suspect that what you actually had in mind was to declare c as an array whose address -- not contents -- is that designated by base, truncated to a 16-byte-aligned address. You cannot do that, because you cannot specify the address of any variable you declare, but you can declare c as a pointer, like this:
unsigned char *c = d;
(Oh no, more pointers!) There's some implementation-dependency there, but it probably has the result I think you want. Or if you want to be really clever, you might do this:
unsigned char (*c16)[16] = d;
That declares c16 as a pointer to an array of 16 unsigned char. It's as close as you can get to declaring an array at an address specified by you. I suspect you'll find it easier to work with the other declaration, however.
If you want to print the contents of the memory to which such a pointer points (as a "memory dump" function seems wont to do) then you'll need to do a little more work. The standard library's formatted I/O functions do not provide directly for printing arrays (for good reasons that I'll not go into here), except C strings, and you do not appear to want to print the data as a C string. Do, however, consider this call, and how you might modify it for or adapt it to your purpose (assuming my above declaration for c):
printf("%02x", *c);

Working with Pointers and Strcpy in C

I'm fairly new to the concept of pointers in C. Let's say I have two variables:
char *arch_file_name;
char *tmp_arch_file_name;
Now, I want to copy the value of arch_file_name to tmp_arch_file_name and add the word "tmp" to the end of it. I'm looking at them as strings, so I have:
strcpy(&tmp_arch_file_name, &arch_file_name);
strcat(tmp_arch_file_name, "tmp");
However, when strcat() is called, both of the variables change and are the same. I want one of them to change and the other to stay intact. I have to use pointers because I use the names later for the fopen(), rename() and delete() functions. How can I achieve this?
What you want is:
strcpy(tmp_arch_file_name, arch_file_name);
strcat(tmp_arch_file_name, "tmp");
You are just copying the pointers (and other random bits until you hit a 0 byte) in the original code, that's why they end up the same.
As shinkou correctly notes, make sure tmp_arch_file_name points to a buffer of sufficient size (it's not clear if you're doing this in your code). Simplest way is to do something like:
char buffer[256];
char* tmp_arch_file_name = buffer;
Before you use pointers, you need to allocate memory. Assuming that arch_file_name is assigned a value already, you should calculate the length of the result string, allocate memory, do strcpy, and then strcat, like this:
char *arch_file_name = "/temp/my.arch";
// Add lengths of the two strings together; add one for the \0 terminator:
char * tmp_arch_file_name = malloc((strlen(arch_file_name)+strlen("tmp")+1)*sizeof(char));
strcpy(tmp_arch_file_name, arch_file_name);
// ^ this and this ^ are pointers already; no ampersands!
strcat(tmp_arch_file_name, "tmp");
// use tmp_arch_file_name, and then...
free(tmp_arch_file_name);
First, you need to make sure those pointers actually point to valid memory. As they are, they're either NULL pointers or arbitrary values, neither of which will work very well:
char *arch_file_name = "somestring";
char tmp_arch_file_name[100]; // or malloc
Then you cpy and cat, but with the pointers, not pointers-to-the-pointers that you currently have:
strcpy (tmp_arch_file_name, arch_file_name); // i.e., no "&" chars
strcat (tmp_arch_file_name, "tmp");
Note that there is no bounds checking going on in this code - the sample doesn't need it since it's clear that all the strings will fit in the allocated buffers.
However, unless you totally control the data, a more robust solution would check sizes before blindly copying or appending. Since it's not directly related to the question, I won't add it in here, but it's something to be aware of.
The & operator is the address-of operator, that is it returns the address of a variable. However using it on a pointer returns the address of where the pointer is stored, not what it points to.

C String Comparison - equates to true

Perhaps an odd question..
I'm currently struggling to understand why the following equates to true i.e. "Hello World" is printed to the console? I've always thought that string comparison in C had to be done using strcmp or similar.
char *a = "Hello";
char *b = "Hello";
if(a == b)
{
printf("Hello World\n");
}
I also thought that this would only equate to true if the addresses were equivalent? Is it the fact that they're literals?
PS. Yes, this is scarcely related to an assignment, but I've just come up with the above off the top of my head. - this doesn't answer the assignment in any way.
The language makes no requirements where and how string literals are stored. All you know is that they have static storage duration and that you mustn't attempt to change the data. Nothing in the standard requires that two different string literals have different addresses, and it's entirely plausible that an implementation would deduplicate string literal data.
On the other hand, nothing requires that two identical string literals be stored at the same address, so there's little point in comparing addresses. Use strcmp for comparing the content of strings, always.
Identical literals that you put directly into the code will actually be pointed at the same memory location for optimization purposes.
The compiler in this case puts down "Hello" once in fixed memory, then points a and b at that memory.
For a more detailed understanding of what's going on, I suggest you compile this program (add a bunch of string literals first), then use gdb or valgrind or any other memory inspector and manually take a look at the memory pointing to string literals -- you'll find in standard cases gcc puts all the string literals together in memory and re-uses identical string literals.
a and b are pointers to characters.
A pointer basically stores a memory address. your a and b variables don't save the word "hello", but they save the memory address at which the word "hello" is saved.
print a and b in your program to see their value.
it will look like: 632176 or something like that, and they will be equal.
so the code a == b basically says: "Do a and b point to the same memory address?". And they do, because "hello" is a constant string and it's only going to be written to memory once.
I believe if you have two pointers who point to a value that is the same the compiler will just point both pointers at the same piece of memory. Its more efficient. But in C always use strcmp even in these kind of instances.
Whats happening here is that you have two pointers, called *a and *b. Next, as you know a pointer points a specific memory location. Now, when both *a and *b are set equal to the exact same sentence, it follows that a and b are pointing to a memory address. However, the compiler notices the pointers are the same sentence, so it sets them pointing to the exact same memory address for optimization purposes.
Because of this, what happens is something like this:
a = 0xFFFFFFFF;
b = 0xFFFFFFFF;
if(0xFFFFFFFF == 0xFFFFFFFF){
// Code
}
Now when you compare them, the compiler sees it as (0xFFFFFFFF == 0xFFFFFFFF) The compiler sees that they are equal, resulting in the if statement becoming true and showing Hello, World
However, this may not happen with different compilers, so you may get different results across compilers. This behavior does work with gcc though. So in that case, you should always use strcmp for comparisons to avoid random behavior like this.

In C program can we make the name of a variable to be a variable?

For example: like I have a variable char str[3]="abc"; then can I use this "abc" as the name of another variable (say an integer) so that I can store any value in abc.
If yes, then while storing a value in 'abc' like this:
int abc=123;
can I refer abc as variable by referring it through str?
No. What you're talking about is reflection, a way to access the inner details of the environment. C currently does not have this built into the language.
There are ways to achieve the same effect, such as having a mapping data structure from strings to integer pointers, but it's a bit messy. As one example:
int abc, def;
char *strName[] = {"abc", "def"};
int *address[] = { &abc, &def};
:
char *key = "def";
int newVal = 42;
for (i = 0; i < sizeof (strName) / sizeof (*strName); i++)
if (strcmp (key, strName[i]) == 0)
*(address[i]) = newVal;
This would go through the list of keys until it found a matching one, then use the equivalent pointer in the list of addresses to modify the variable.
But, in all honesty, once you're having to do something dark and devious like that, you may as well do it with a more appropriate data structure.
For example, a map where the values are stored in the actual map rather than it holding the addresses of "external" integers.
Not only you cannot, but it is a part of ideology of what C language is. Variable names do not exist at run-time, and variable contents should not matter at compile time.
There is a difference of what you see of your program by looking at the source code, and what your "program itself sees" when running the raw binary executable. In the executable, there is no such thing as variable names.
Lets say we have this program:
char str[4]="abc"; // note that you need to allocate 4 bytes
int abc=123;
The above is the source code, that's what the programmer sees. The program itself only "sees" something similar to this:
At some address 0x12345678, there are 4 bytes. They are 0x61, 0x62, 0x63, 0x00 (the ASCII codes). The program will access theses as individual bytes, because of the char type in the source code. But the program actually doesn't see the type either.
Then at address 0x1234567C, 4 bytes further down in memory, we have another 4 bytes (assuming 32 bit CPU). They contain the value 0x0000007B (123). The program only refers to this int variable as 0x1234567C, it has no idea that the programmer calls it abc in the source code.
You can consider code generation.
With an XML:
<var type="int" name="abc" />
Generate the code:
int abc;
(The input XML itself can itself be created with your char str[] as input)

use of pointers in passing as an argument

I have few conceptual problem in understanding the code
Below are the description
char dest[100];
char *info;
Byte *ie;
Function declaration says
getValue(Byte tag, Byte *msg, int len)
we pass something like
getValue(0X01, &info[4], 30);
here I understand that I am passing address of values to the pointer.
Now there is 2nd function
retriveValue( Byte *ie, Byte *digits, Byte totalLen)
in this function we pass something like
retriveValue(&ie[3], (Byte*)&dest, 2);
Here , I guess, we are converting char to pointer of type byte and passing Address to it.
Now my question is:
What is wrong if I convert dest to byte and pass address like (Byte)&dest?
How would I pass if dest is of type char* like for eg char *dest;?
retriveValue(&ie[3], (Byte*)&dest, 2);
here in 2nd argument you have taken address of dest & then pointer cast it by (Byte*)
1>What is wrong if I convert dest to byte and pass address like (Byte)&dest?
by doing this you are casting the address of dest into Byte.(not Byte pointer)
2>How would I pass if dest is of type char* like for eg char *dest;?
then no need to add "&" just write
retriveValue(&ie[3], (Byte*)dest, 2);
"we pass something like"
getValue(0X01, &info[4], 30);
Oh do you now? Because that is scary amounts of bad karma being built up there.
First off, passing in hex values is a little weird. You could pass in a constant or a #defined value like TAG_01. In your application it may be perfectly fine, but I'd be wary.
The second argument is where it gets scary. info is a pointer (presumably set to &dest), the value that info holds is the address of the thing you're pointing to. If you wanted to pass in an address, you'd point into to the thing, and then pass in info, without the ampersand or treating it like an array. What you're doing using the square brackets [ ] to get an element of dest, and then getting address of that.
Now, it could be that you're using pointers in some ingenious way, and you really do want to reference the 4th byte after it. But I doubt it. You're probably just dinking around with pointers to see how they work, which is fine. But when you start to make stuff, if you want to pass in a message, declare a message and send that. Don't imbed a character string into part of a larger array. It's bad form. Use a struct instead.
here I understand that I am passing address of values to the pointer.
Well, you're passing an address to a function, not a pointer.
"in this function we pass something like"
retriveValue(&ie[3], (Byte*)&dest, 2);
Again, I'm in a cold sweat over how scary wrong this is. Never do this. Who is this nefarious "we" you speak of? Are you part of some sort of horrible cult chanting an unspeakable dialect of C in an attempt to usher in a dark reign of Cthulu? Does h̡e͜͟ ͟c̀om͠e̴͝?̢̛͟
Anyway, cult aside,
What is wrong if I convert dest to byte and pass address like (Byte)&dest?
As Monsieur 32 pointed out, you're not passing an address if you do that, you're passing a Byte. Remember, that a Byte is 8 bits long. It's one char. An address is usually 32 or 64 bits, depending on the environment. So when you cast it like that, you're dropping 3/4ish of the data you need, and it doesn't fit the definition of the function. And it's a sin against nature.
How would I pass if dest is of type char* like for eg char *dest;?
Yep, just dest, all plain and vanilla by itself. This is because dest isn't a char. It's declared as dest[100], which means dest[0] is a char, but dest is the address of dest[0], like a pointer.
The array convention is really just a bit of molding over pointers to help keep things straight. There's no functional difference between *(dest+3) and dest[3]. On a technical level, arrays and pointer are different in that array declarations like dest would be treated as a const at compile time, so it wouldn't take up any RAM. A char* pointer would have it's own little hunk of RAM that you could increment while looping through your data, but only the eversleeping dark one uses pointers like that. Why is he sleeping? Endless loop because he didn't cast his pointers correctly.
Finally, if you already accepted Mr.32's answer, which was WAY ahead of mine, you really should put it back. And just say no to dead alien gods.

Resources