Reputation: 998
I am studying about the memory layout of a program. I am using gdb to examine the stack in a little endian (intel x86_64) Linux (32 bit) machine. However, I am not able to understand the concept of big-endian and little-endian w.r.t this processor and gdb.
My sample program is:
1 #include<stdio.h>
2
3 int main(int argc, char **argv) {
4 int a = 5;
5 char b[] = "ABCDEFGH";
6
7 return 0;
8 }
[Code - 1]
The following sequence of instructions were executed in gdb.
(gdb) b 7
Breakpoint 1 at 0x8048434: file args.c, line 7.
(gdb) r
Breakpoint 1, main (argc=1, argv=0xbffff4f4) at args.c:7
7 return 0;
(gdb) x/20xw $esp
0xbffff410: 0x0011e0c0 0x08049ff4 0xbffff448 0xbffff4f4
0xbffff420: 0x00284324 0x00283ff4 0x08048470 0x00000005
0xbffff430: 0x4115d4a5 0x45444342 0x00484746 0x6a078d00
0xbffff440: 0x08048470 0x00000000 0xbffff4c8 0x00144bd6
0xbffff450: 0x00000002 0xbffff4f4 0xbffff500 0xb7fff858
[Code - 2]
Initially, I was confused whether the memory address 0xbffff430
in the stack above contains the value 0x41
or 0xa5
. So I examined the stack starting from the address 0xbffff433
.
(gdb) x/8xw 0xbffff433
0xbffff433: 0x44434241 0x48474645 0x078d0000 0x0484706a
0xbffff443: 0x00000008 0xfff4c800 0x144bd6bf 0x00000200
[code - 3]
As evident from the output above, the address 0xbffff433
contains the value 0x41
. Thus, the address 0xbffff430
contains the value 0xa5
. Thus we can conclude that memory addresses in gcc are displayed in the following order:-
0xbffff433: [0xbffff436][0xbffff435][0xbffff434][0xbffff433] [0xbffff43a] [0xbffff439][0xbffff438][0xbffff437]
D C B A H G F E
However, since intel x86_64 is little-endian, from what I understand the order in which the character array is stored (MSB at smallest address) should be as follows:-
0xbffff433: [0xbffff436][0xbffff435][0xbffff434][0xbffff433] [0xbffff43a][0xbffff439][0xbffff438][0xbffff437]
A B C D E F G H
Q (a): Could some please explain where am I getting wrong?
Q (b): Furthermore, from [code 2]
above we can see that the value for variable a
is stored at the address 0xbffff42c
. The value for variable a
is: 0x00000005
. Here also LSB is stored at the smallest memory address.
Q (c): However, the problem from Q (a) and (b) doesn't manifest when addresses are stored. For example, from code - 4
below we can check that at the address 0xbffff448
EBP (0xbffff4c8
) is stored
(gdb) x/4xw $ebp
0xbffff448: 0xbffff4c8 0x00144bd6 0x00000002 0xbffff4f4
It is clearly visible that the address is stored in the following order:-
0xbffff448: [0xbffff44b][0xbffff44a][0xbffff449][0xbffff448]
0xbf 0xff 0xf4 0xc8
Note: 1) I tried the above code on a VM of ubuntu-10.04-desktop-i386. I confirmed the endianness of my machine using the following code:
#include <stdio.h>
int main()
{
unsigned int i = 1;
char *c = (char*)&i;
if (*c)
printf("Little endian");
else
printf("Big endian");
getchar();
return 0;
}
2) I checked the following thread too Is GDB interpreting the memory address correctly? but I am still not able to understand the concept.
Thanks.
Upvotes: 4
Views: 2677
Reputation: 10251
The char type in C on the x86 is 1 8-bit byte long, with an alignment of 1 byte; there is no endianness to take into account. Arrays in C on the x86 go from lower addresses to higher addresses. The w
in x/xw
means "print 4-byte words", which is fine for showing 32-bit integers and (on 32-bit systems) pointers, but not so great for chars or char arrays. Use x/9xb b
or x/9cb b
to see the first 9 elements of the char array b
, displayed as bytes.
Upvotes: 4