why GDB is not printing arrays? - gdb

When running some of my binaries I found it strange that GDB does not dump the arrays and I don't know why this only happens in some of the executables.
The declaration is very simple:
tbl_account_t accounts[MAX_ACCOUNTS];
When I print arrays (just any array), I get this:
(gdb) print accounts
$16 = 0x618d20 <accounts>
Confirming the variable type, everything is ok:
(gdb) ptype accounts
type = struct tbl_account {
unsigned short email_len;
unsigned short password_len;
char auto_log_in;
char reserved_char[3];
int reserved_int;
char email[64];
char password[25];
} []
(gdb)
I do have the data in it:
(gdb) print accounts[1]
$18 = {email_len = 16, password_len = 3, auto_log_in = 0 '\000', reserved_char = "\000\000", reserved_int = 0, email = "abra#cadabra.com", '\000' <repeats 47 times>,
password = "123", '\000' <repeats 21 times>}
(gdb)
With "print accounts" command I was expecting GDB to dump the entire contents of the array, like it does in other executables. Why does this happen ?

I don't quite have the full answer but I suspect that if you share more of your code we can figure it out. It appears that gdb does not know the length of your array.
Consider this program
struct tbl_account {
unsigned short email_len;
unsigned short password_len;
char auto_log_in;
char reserved_char[3];
int reserved_int;
char email[64];
char password[25];
};
int main(int argc, char* agv[])
{
tbl_account table[10];
tbl_account* table_ptr = table;
return 0;
}
Now the gdb session
(gdb) b main
Breakpoint 1 at 0x4006e5: file junk.cpp, line 22.
(gdb) r
Starting program: /tmp/a.out
Breakpoint 1, main (argc=1, agv=0x7fffffffdfe8) at junk.cpp:22
22 tbl_account* table_ptr = table;
(gdb) n
23 return 0;
(gdb) ptype table_ptr
type = struct tbl_account {
unsigned short email_len;
unsigned short password_len;
char auto_log_in;
char reserved_char[3];
int reserved_int;
char email[64];
char password[25];
} *
(gdb) ptype table
type = struct tbl_account {
unsigned short email_len;
unsigned short password_len;
char auto_log_in;
char reserved_char[3];
int reserved_int;
char email[64];
char password[25];
} [10]
Note how the ptype of the pointer is indicated by the '*'. We can also see that the array type is indicated by the [10]. In my example, the array size is included and gdb will print each element. For some reason, in your example the size of the array is not included. Perhaps it is an extern variable?
Since gdb isn't certain of the size of the array, it just prints it as a pointer value. As a worked around try casting
(gdb) p (tbl_account[10])accounts

You can also manually tell GDB how many entries to print using '#'.
This works better if your array is not statically allocated or you just want to examine specific set of entries in the array.
struct tbl_account {
int id;
char email[64];
char password[25];
};
int main(void)
{
struct tbl_account table[] = {
{1, "abc", "1234"},
{2, "def", "5678"},
{3, "ghi", "1011"},
{4, "jkl", "1213"}};
return 0;
}
And then tell GDB to print first 3 entries in the array
(gdb) p table[0]#3
$3 = {{
id = 1,
email = "abc", '\000' <repeats 60 times>,
password = "1234", '\000' <repeats 20 times>
}, {
id = 2,
email = "def", '\000' <repeats 60 times>,
password = "5678", '\000' <repeats 20 times>
}, {
id = 3,
email = "ghi", '\000' <repeats 60 times>,
password = "1011", '\000' <repeats 20 times>
}}
If you are interested in only index 2-3 for e.g, You could do -
(gdb) p table[2]#2
$5 = {{
id = 3,
email = "ghi", '\000' <repeats 60 times>,
password = "1011", '\000' <repeats 20 times>
}, {
id = 4,
email = "jkl", '\000' <repeats 60 times>,
password = "1213", '\000' <repeats 20 times>
}}

Related

Debug Core dump in QNX - How to get more info?

My previously working code crashes now. The core dump points to the constructor being called.
I have tried to get bt, bt full and disassembly. I need some help to conclude what could cause segmentation fault while calling constructor?
Code is run on QNX and there is console gdb only. The local variables are all 0, what could that mean ?
Here's the o/p:
(gdb) bt
#0 0x481a95b0 in notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID (path_Type=PATH_NULL, pathId=1215822164,
alarm_Id=DS3_PATH_IDLE_ID) at /vob/qnx/cema-common/msg/PathObjMsg.h:47
(gdb) bt full
#0 0x481a95b0 in notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID (path_Type=PATH_NULL, pathId=1215822164,
alarm_Id=DS3_PATH_IDLE_ID) at /vob/qnx/cema-common/msg/PathObjMsg.h:47
msg = {<Message> = {msgSource = MSG_SOURCE_INVALID, msgPriority = MSG_PRIO_LOW, msgLength = 0},
msgType = MSG_PATH_ALARM, pathType = PATH_NULL, pathId = {bay = 0 '\0', line = 0 '\0', path = {stsn = {
sts1Num = 0 '\0'}, vt = {sts1Num = 0 '\0', isTu3 = 0 '\0', tug3Num = 0 '\0', vtgTug2Num = 0 '\0',
vtTuNum = 0 '\0'}, ds3 = {sts1Num = 0 '\0', ds3Num = 0 '\0'}, ds1InDS3Line = {pad = 0 '\0', ds1Num = 0 '\0'},
ds1InVT = {sts1Num = 0 '\0', pad = 0 '\0', tug3Num = 0 '\0', vtgTug2Num = 0 '\0', vtTuNum = 0 '\0'},
ds1InDS3Path = {sts1Num = 0 '\0', tug3Num = 0 '\0', ds1Num = 0 '\0'}, e1InVT = {sts1Num = 0 '\0', pad = 0 '\0',
tug3Num = 0 '\0', vtgTug2Num = 0 '\0', vtTuNum = 0 '\0'}, e3 = {sts1Num = 0 '\0', ds3Num = 0 '\0'}}},
alarmId = 0, lineId = 0 '\0'}
emPathType = PATH_NULL
emAlarmId = 10
(gdb) l * 0x481a95b0
0x481a95b0 is in notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID (/vob/qnx/cema-common/msg/PathObjMsg.h:47).
42 PathObjMsg(
43 PATH_TYPE pathTypeIn,
44 EM_PATH_ID pathIdIn,
45 PATH_OBJ_MSG_TYPE msgTypeIn,
46 EM_PATH_ALARM_ID alarmIdIn
**47 ): Message(MSG_SOURCE_PATH_OBJ)**
48 {
49 pathType = pathTypeIn;
50 pathId = pathIdIn;
51 msgType = msgTypeIn;
O/p of Disassembly:
bne- 0x481a962c <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+264>
0x481a959c <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+120>: li r0,15
0x481a95a0 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+124>: mr r27,r28
0x481a95a4 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+128>: stw r27,88(r1)
0x481a95a8 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+132>: stw r0,8(r1)
0x481a95ac <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+136>: addi r31,r1,8
0x481a95b0 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+140>: li r9,1
0x481a95b4 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+144>: stw r9,4(r31)
0x481a95b8 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+148>: stw r29,16(r31)
0x481a95bc <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+152>: lwz r0,88(r1)
0x481a95c0 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+156>: stw r9,12(r31)
0x481a95c4 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+160>: stw r0,20(r31)
0x481a95c8 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+164>: stw r5,24(r31)
0x481a95cc <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+168>: lbz r0,89(r1)
0x481a95d0 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+172>: mr r3,r31
0x481a95d4 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+176>: stb r0,28(r31)
0x481a95d8 <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+180>: li r4,32
0x481a95dc <notifyDs3PathAlarmClrEvent__F9PATH_TYPEUi17DS3_PATH_ALARM_ID+184>:
My previously working code crashes now. The core dump points to the
constructor being called. I have tried to get bt, bt full and
disassembly. I need some help to conclude what could cause
segmentation fault while calling constructor? Code is run on QNX and
there is console gdb only. The local variables are all 0, what could
that mean ?. I need some help to conclude what could cause
segmentation fault while calling constructor?
Please do not conclude that there could be problem(only) while calling constructor. This can
be just the side effect of something else(bad) which has already occurred. It would be difficult
to figure out the problem from the current stack trace. Sometime memory bugs would be in very
intermittent(due to different input/threading/change in sequence of execution),and program may run for years without showing any symptoms of any problem.
The locals variables 0 may indicate that it looks ok but we can not conclude anything from it.
I do feel that there could be some memory corruption scenario (somewhere else in your other module)is leading this crash. You would have to debug your code using GDB/Valgrind(some dynamic tool) to find out the root problem. It looks like you are experiencing this problem on QNX, so you may want to run the Valgrind to identify the problem in your code. You can refer to my previous post
https://stackoverflow.com/a/22658693/2724703

buffer overflow that shouldnt happen (?)

I have the following program
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int check_authentication(char *password){
6 char password_buffer[16];
7 int auth_flag =0;
8
9
10 strcpy(password_buffer, password);
11
12 if(strcmp(password_buffer, "brillig" ) == 0 )
13 auth_flag = 1;
14 if(strcmp(password_buffer, "outgrabe") == 0)
15 auth_flag = 1;
16
17 return auth_flag;
18 }
19
20 int main(int argc, char *argv[]){
21 if (argc<2){
22 printf("Usage: %s <password>\n", argv[0]);
23 exit(0);
24 }
25
26 if(check_authentication(argv[1])){
27 printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
28 printf(" Access Granted.\n");
29 printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
30 }
31 else {
32 printf("\n Access Denied. \n");
33 }
34 }
I am running it supplying 30 bytes of As through gdb... and I am setting the following breakpoints
(gdb) break 9
Breakpoint 1 at 0x80484c1: file auth_overflow2.c, line 9.
(gdb) break 16
Breakpoint 2 at 0x804850f: file auth_overflow2.c, line 16.
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
So far so good. Everything goes as it was supposed to go even till the next breakpoint
Breakpoint 1, check_authentication (password=0xbffff6d2 'A' <repeats 30 times>)
at auth_overflow2.c:10
10 strcpy(password_buffer, password);
(gdb) x/s password_buffer
0xbffff484: "\364\237\374\267\240\205\004\b\250\364\377\277\245", <incomplete sequence \352\267>
(gdb) x/x &auth_flag
0xbffff494: 0x00
Now we see the following information:
variable auth_flag is in address 0xbffff494 and variable buffer is in the address 0xbffff484. Since address of var auth_flag is greater than the address of buffer and the stack grows towards lower addresses that means that additional (overrun of the buffer) bytes in the buffer variable WILL NOT OVERWRITE auth_flag. Right ?
But gdb has a different opinion...
(gdb) cont
Continuing.
Breakpoint 2, check_authentication (
password=0xbf004141 <Address 0xbf004141 out of bounds>)
at auth_overflow2.c:17
17 return auth_flag;
(gdb) x/s password_buffer
0xbffff484: 'A' <repeats 30 times>
(gdb) x/x &auth_flag
0xbffff494: 0x41
and ...
(gdb) x/16xw &auth_flag
0xbffff494: 0x41414141 0x41414141 0x41414141 0xbf004141
0xbffff4a4: 0x00000000 0xbffff528 0xb7e8bbd6 0x00000002
0xbffff4b4: 0xbffff554 0xbffff560 0xb7fe1858 0xbffff510
0xbffff4c4: 0xffffffff 0xb7ffeff4 0x080482bc 0x00000001
We see that auth_flag was overwritten with these 0x41 (=A) although this variable was in a lower position in stack. Why this happened?
Stack growth direction has nothing to do with where the extra bytes go when you overrun a buffer. Overruns from strcpy are always going to be into higher addresses (unless overrun so far that you wrap around to address 0, which is pretty unlikely)
Objects are stored in memory from lower udresses up to higher addresses. As you can not guarantee that the length of the string refered to by parameter password is less than 16 then your code is invalid.
In fact there is no any need in the local buffer password_buffer.
The function could be written the following way
_Bool check_authentication( const char *password )
{
return ( strcmp( password, "brillig" ) == 0 || strcmp( password, "outgrabe" ) == 0 );
}
Instead of the return type _Bool you may use type int as in your function realization. In any case either 1 or 0 will be returned.
the compiler can freely reorder the stack of variables therefore in this case it's always char array before int variable. This makes the program vulnerable for stack-based buffer overflow.
In order to change the following:
(gdb) x/s password_buffer
0xbffff484: 'A' <repeats 30 times>
(gdb) x/x &auth_flag
0xbffff494: 0x41
into expected answer as below:
(gdb) x/s password_buffer
0xbffff494: 'A' <repeats 30 times>
(gdb) x/x &auth_flag
0xbffff484: 0x00
We simply add a -fstack-protector-all argument during compilation and the result will be as expected. To be vice-versa, perhaps you can use -O0 or -fno-stack-protector.
Answer from: https://stackoverflow.com/a/21215205/3205268
If you are reading in more then 15 bytes you will get that. strcpy will look for the end of the string. You could use something like strncpy to only copy a limited number of characters.

C++ conversion between char and int with wrong result

i want to convert between char and int in c++ but i've found a problem with char to int conversion.
I did a test with two numbers, 103 and 155. 103 give me "g" in char and 155 give me "ø" and both are correct, but the problem is when i try to back chars to int: "g" give me 103 (correct) but i don't know why "ø" give me -101.
I'm using a char variable to store numbers, and "prinf("%d", char[x]);" to show back the number.
I've this test script:
#include <cstdlib>
#include <cstdio>
using namespace std;
int numero = 26523;
char *inttochar(int number) {
char *salida;
for (int j=0;j<=5;j++) {
salida[5-j] = number % 256;
printf("%d = %d = %c = %c = %d\n", 5-j, number % 256, number % 256, salida[5-j], salida[5-j]);
number = number / 256;
}
return salida;
}
int main(int argc, char** argv) {
char *texto = inttochar(numero);
for (int j=0;j<=5;j++) {
printf("%d: ", j+1);
printf("%c = %d\n", texto[j], texto[j]);
}
return 0;
}
And result is:
5 = 155 = ø = ø = -101
4 = 103 = g = g = 103
3 = 0 = = = 0
2 = 0 = = = 0
1 = 0 = = = 0
0 = 0 = = = 0
1: = 0
2: = 0
3: = 0
4: = 0
5: g = 103
6: ø = -101
With this script i want to convert a number to a base 256 char. ¿What i'm doing wrong?.
Thanks!!, and i'm sorry for my english.
Characters are signed values between -128 and 127 (on most systems). You're converting something from outside that range; the conversion to a char truncates but the bit pattern is OK. Converting the other direction puts you back into the range, and 155 isn't part of it. The bit pattern for 155 is 0x9b; to convert to a signed value you invert the bits and add one, so it becomes -0x65 which is -101 in decimal.
You can fix it with an and that strips off the extended sign bits: salida[5-j] & 0xff.
Edit: As noted in the comments your salida variable is intended to be a string but you never allocate any storage for it.
char *salida = new char[6];
char appears to be a signed type on your platform. That means 155 won't fit in it. You're getting that 155 interpreted as a 2's complement signed number, which equals -101.

GDB: Why can I not print this?

(gdb) print argv[1]
$5 = 0xbffffb1d "hello"
(gdb) step
21 sz = strlen(argv[1]) + 1;
(gdb) print sz
$6 = 0
(gdb) printf "%s", sz
Cannot access memory at address 0x0
(gdb) printf "%i", sz
0
I am expecting 4 in sz, why is it coming out as 0?
I am not sure why you are expecting 4. You get 5 from strlen(argv[1]) because hello has 5 characters. And then you are adding 1 to it which is why the answer is 6.
sz = strlen(argv[1]) + 1; // 5 + 1 = 6

Why I can't access the memory directly?

(gdb) p it
$2 = (item *) 0x6
(gdb) p *it
$3 = {next = 0x0, prev = 0x0, h_next = 0x0, time = 0, exptime = 0, nbytes = 7, refcount = 1, nsuffix = 6 '\006', it_flags = 2 '\002', slabs_clsid = 1 '\001', nkey = 6 '\006',
end = 0x7f0890b6e040}
(gdb) p *0x6
Cannot access memory at address 0x6
Isn't p *it and p *0x6 the same thing here??
Unless you are on an embedded target that has real memory mapped at address 0, the value of it == 0x6 is bogus (usually result of a null pointer dereference).
The fact that gdb prints *it probably means there is a bug in gdb, but it's hard to say. Unfortunately you didn't say which version of GDB, and what OS, you are using.
The gdb 'p' command can only be used for printing variables value.
If you want to inspect memory have a look there