I am debugging an ARM microcontroller remotely and trying to modify a variable with gdb in the following block of code:
for (int i = 0; i < 100; i++) {
__asm__("nop");
}
When I execute print i I can see the value of the variable
(gdb) print i
$1 = 0
Executing whatis i returns this
whatis i
~"type = int\n"
But when I try to change the variable I get the following error
(gdb) set variable i=99
Left operand of assignment is not an lvalue.
What am I doing wrong here?
UPDATE: here is the assembler code
! for (int i = 0; i < 100; i++) {
main+38: subs\tr3, #1
main+40: bne.n\t0x80001d0 <main+36>
main+42: b.n\t0x80001c4 <main+24>
main+44: lsrs\tr0, r0, #16
main+46: ands\tr2, r0
! __asm__("nop");
main+36: nop
I had the same problem and making the variable volatile helped.
The command would be just set i = 99
Try it this way:
(gdb) print i
$1 = 3
(gdb) set var i=6
(gdb) print i
$2 = 6
There is two issue here change the variable name from i to var_i as there are some set command starting with i so set i=6 will gives the ambiguous command set error.
The "Left operand of assignment is not an lvalue." can be fixed with the code changes as shown below.
volatile int var_i = 1;
TRACE((2255, 0, NORMAL, "Ravi I am sleeping here........."));
do
{
sleep(5);
var_i = 1;
}while(var_i);
(gdb)bt
#1 0x00007f67fd7b9404 in sleep () from /lib64/libc.so.6
#2 0x00000000004cd410 in pgWSNVBUHandleGetUser (warning: Source file is more recent than executable.
ptRequest=<optimized out>, oRequest=<optimized out>,
(gdb) finish
Run till exit from #0 0x00007f67fd7b9550 in __nanosleep_nocancel () from /lib64/libc.so.6
0x00007f67fd7b9404 in sleep () from /lib64/libc.so.6
(gdb) finish
Run till exit from #0 0x00007f67fd7b9404 in sleep () from /lib64/libc.so.6
0x00000000004cd410 in pgWSNVBUHandleGetUser (ptRequest=<optimized out>, oRequest=<optimized out>,
pptResponse=0x7fff839e8760) at /root/Checkouts/trunk/source/base/webservice/provnvbuuser.c:376
(gdb)
│372 volatile int var_i = 1; │
│373 TRACE((2255, 0, NORMAL, "Ravi I am sleeping here.........")); │
│374 do │
│375 { │
>│376 sleep(5); │
│377 var_i = 1; │
│378 }while(var_i);
(gdb) set var_i=0
(gdb) n
(gdb) p var_i
$1 = 1
(gdb) set var_i=0
(gdb) p var_i
$2 = 0
(gdb) n
(gdb) n
Related
Is there any way to extract variables that are being passed to a particular function as parameters in a given c code?
For an example,
main()
{
int a = 10;
float b = 2.0f;
funcA(a,b);
}
Need is to extract the information that variable a & variable b are passed to funcA in a given C code.
Is there a way to extract these information using gdb and it's function breakpoints?
when you are in any function typing frame will give you parameters information of function.
Below are some other commands you can use to get to know more about local variables and parameters.
info locals
frame
info args
more gdb commands
sample :
(gdb) b main
Note: breakpoint 1 also set at pc 0x40053e.
Breakpoint 2 at 0x40053e: file main.c, line 6.
(gdb) r
Starting program: /home/a.out
Breakpoint 1, main () at main.c:6
6 int a = 10;
(gdb) n
7 float b = 2.0f;
(gdb) info locals
a = 10
b = 0
x = 0
(gdb) frame
#0 main () at main.c:7
7 float b = 2.0f;
(gdb) next
9 int x = funcA(a,b);
(gdb) step
funcA (a=10, b=2) at main.c:16
16 int sum = 0;
(gdb) frame
#0 funcA (a=10, b=2) at main.c:16
16 int sum = 0;
(gdb) info args
a = 10
b = 2
(gdb) info locals
sum = 0
(gdb) p a
$1 = 10
(gdb) print b
$2 = 2
(gdb)
I use gdb test core and get this:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x0000557ce64b63f8 in _create (str=str#entry=0x557ce80a8820 "SEND")
at system.c:708
708 data->res = command->data->res;
(gdb) bt
#0 0x0000557ce64b63f8 in _create (str=str#entry=0x557ce80a8820 "SEND")
at system.c:708
#1 0x0000557ce64b2ef1 in make_command (s=<optimized out>, cmd=0x557ce809cb70) at command.c:121
#2 0x0000557ce63aefdf in main (argc=<optimized out>, argv=0x7fff19053278) at main.c:394
(gdb) p *command
$1 = {status = 1, data = 0x7f21027e9a80, sum = 1543465568, time = 0, msg = { str = 0x7f20fd19f080 "GOOD", len = 4}, id = 2}
(gdb) p *command->data
$2 = {status = 1, item = 0x7f21027eb780, res = 0x7f2100990b00, sum = 1133793665}
(gdb) p *command->data->res
$3 = {msg = { str = 0x7f21010a5500 "Hi, test, test"..., len = 14}, status = 1}
(gdb) p *data
$4 = {status = 1, type = 5, res = 0x0, id = 2}
as you can see, the pointer command and command->data and data are all valid, why this SIGSEGV happened?
why this SIGSEGV happened?
We can't tell.
One possible reason: some other code is actually executing and crashing.
This could happen if system.c has been edited or updated, but the program has not been rebuilt with the new source. Or if the compiler mapping of program counter to file/line is inaccurate (this often happens with optimized code).
If you edit your question to show the output from list _create, disas $pc and info registers, we may be able to tell you more.
I see some value in some place, but unsure where it has originated in my program. How do I figure out where this value initially comes from?
I expect the following event types to be logged:
A value originated from constant, arithmetical expression or syscall - the initial event;
The value was assigned to (or retrieved from) some variable;
The value was passed as an argument or returned from some function;
The value was stored to (or retrieved from) some struct;
By annotating source code with something specific, I triggered the history dump for this value.
For example, for this sample code:
#include <stdlib.h>
struct SomeStruct {
int a;
int b;
};
struct SomeStruct *globalvar;
int f1(struct SomeStruct* par) {
return par->a;
}
int f2(struct SomeStruct* par, int q) {
par->a = q;
return par->b;
}
void trace_value(int g) {} /* dummy */
int main(void) {
int f = 31337;
globalvar = malloc(sizeof(*globalvar));
f2(globalvar, f);
struct SomeStruct q = *globalvar;
int g = f1(&q);
trace_value(g);
return 0;
}
it should return something like
value 31337 originated from constant at fate.c:18
assigned to variable at fate.c:18
retrieved from variable at fate.c:21
passed as argument to function at fate.c:21
received as arument to a function at fate.c:12
assigned to struct field at fate.c:13
copied as a part of struct at fate.c:22
retrieved from struct field at fate.c:9
returned from function at fate.c:10
assigned to variable at fate.c:23
retrieved from variable at fate.c:25
traced at fate.c:25
How do I do this or something similar? I expect Valgrind or GDB or some combination should be able to do this.
Combined idea1 of using reverse gdb and idea2 from MarkPlotnick's comment of using gdb watchpoints. Here is the demo session, more complete than in original answer:
$ gcc -ggdb -Dtrace_value=exit fate.c -o fate
$ gdb -quiet -args ./fate
Reading symbols from /home/vi/code/_/fate...done.
(gdb) break main
Breakpoint 1 at 0x8048482: file fate.c, line 18.
(gdb) r
Starting program: /home/vi/code/_/fate
warning: Could not load shared library symbols for linux-gate.so.1.
Do you need "set solib-search-path" or "set sysroot"?
Breakpoint 1, main () at fate.c:18
18 int f = 31337;
(gdb) record
(gdb) break 25
(gdb) # traced at fate.c:25
Breakpoint 2 at 0x80484d2: file fate.c, line 25.
(gdb) c
Continuing.
Breakpoint 2, main () at fate.c:25
25 trace_value(g);
(gdb) # retrieved from variable at fate.c:25
(gdb) watch g
Hardware watchpoint 3: g
(gdb) reverse-continue
Continuing.
Hardware watchpoint 3: g
Old value = 31337
New value = 134513899
0x080484ce in main () at fate.c:23
23 int g = f1(&q);
(gdb) # assigned to variable at fate.c:23
(gdb) # returned from function at fate.c:10
(gdb) reverse-step
f1 (par=0xffffd670) at fate.c:10
10 }
(gdb) list
5
6 struct SomeStruct *globalvar;
7
8 int f1(struct SomeStruct* par) {
9 return par->a;
10 }
11
12 int f2(struct SomeStruct* par, int q) {
13 par->a = q;
14 return par->b;
(gdb) # retrieved from struct field at fate.c:9
(gdb) print par
$3 = (struct SomeStruct *) 0xffffd670
(gdb) print ((struct SomeStruct *) 0xffffd670)->a
$4 = 31337
(gdb) watch ((struct SomeStruct *) 0xffffd670)->a
Hardware watchpoint 4: ((struct SomeStruct *) 0xffffd670)->a
(gdb) reverse-continue
Continuing.
Hardware watchpoint 4: ((struct SomeStruct *) 0xffffd670)->a
Old value = 31337
New value = -134716508
0x080484ba in main () at fate.c:22
22 struct SomeStruct q = *globalvar;
(gdb) # copied as a part of struct at fate.c:22
(gdb) print globalvar->a
$5 = 31337
(gdb) watch globalvar->a
Hardware watchpoint 5: globalvar->a
(gdb) reverse-continue
Continuing.
Hardware watchpoint 5: globalvar->a
Old value = 31337
New value = 0
0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
13 par->a = q;
(gdb) # assigned to struct field at fate.c:13
(gdb) # received as arument to a function at fate.c:12
(gdb) list
8 int f1(struct SomeStruct* par) {
9 return par->a;
10 }
11
12 int f2(struct SomeStruct* par, int q) {
13 par->a = q;
14 return par->b;
15 }
16
17 int main() {
(gdb) bt
#0 0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
#1 0x080484b0 in main () at fate.c:21
(gdb) reverse-finish
Run back to call of #0 0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
0x080484ab in main () at fate.c:21
21 f2(globalvar, f);
(gdb) # passed as argument to function at fate.c:21
(gdb) # retrieved from variable at fate.c:21
(gdb) watch f
Hardware watchpoint 6: f
(gdb) reverse-finish
"finish" not meaningful in the outermost frame.
(gdb) reverse-continue
Continuing.
Warning:
Could not insert hardware watchpoint 6.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) watch f
Hardware watchpoint 7: f
(gdb) reverse-continue
Continuing.
No more reverse-execution history.
main () at fate.c:18
18 int f = 31337;
(gdb) # assigned to variable at fate.c:18
(gdb) # value 31337 originated from constant at fate.c:18
All expected messages in the question statement correspond to some info you have seen in gdb output (as shown in comments).
I believe it could be accomplished manually (i.e. running on gdb session) in runtime by technique called "reverse debugging". I haven't tried it yet, but GDB version 7.0 documentation claims, that it is supported on some platforms.
The method would be something like:
localize single step where variable is used in the last place (that is, your "starting point")
analyze source code (so you need debugging symbol and code section available) of stack frame (e.g. by list), so you get how this value is obtained (or possibly modified) witihin (e.g. from parameter passed to function)
step back to previous stack frame and repeat from previous step unless you find its origin
Here is some proof-of-concept session for your sample code. I edited it a bit, as trace_value function was undefined. Note that record command may heavily slow down program's execution.
$ gdb -q a.out
Reading symbols from /home/grzegorz/workspace/a.out...done.
(gdb) b main
Breakpoint 1 at 0x400502: file fate.c, line 22.
(gdb) run
Starting program: /home/grzegorz/workspace/a.out
Breakpoint 1, main () at fate.c:22
22 int f = 31337;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.5.x86_64
(gdb) record
(gdb) b trace_value
Breakpoint 2 at 0x4004f8: file fate.c, line 19.
(gdb) c
Continuing.
Breakpoint 2, trace_value (g=31337) at fate.c:19
19 void trace_value(int g){}
(gdb) info args
g = 31337
(gdb) reverse-finish
Run back to call of #0 trace_value (g=31337) at fate.c:19
0x0000000000400550 in main () at fate.c:29
29 trace_value(g);
(gdb) bt
#0 0x0000000000400550 in main () at fate.c:29
(gdb) list 29
24 globalvar = malloc(sizeof(*globalvar));
25 f2(globalvar, f);
26 struct SomeStruct q = *globalvar;
27 int g = f1(&q);
28
29 trace_value(g);
30
31 return 0;
32 }
Few things maybe require some explanation. You need to set breakpoint for main at first, as this is when the program execution begins, then enable session recording by record command. Then set second breakpoint at trace_value function and use continue command (c in short). This allows you to record whole execution up to moment when trace_value is entered. You may think of it as this "starting point", described above.
This of course not the full story. As I described earlier you need to analyze source code of current stack frame an then decide what to do next. You may use reverse-step or reverse-finish command accordingly to current situation.
I have the following piece of code in a while loop where I calculate some probability with the exp() function. No matter what the input to the program
on the 7th iteration of the loop the exp returns nan.
if(new<=old){
coloring[random_node]=random_color;
}else{
proba=exp((-(new-old))/temperature);
/*assert(!isnan(proba));*/
printf("proba == %.50f\n",proba);
if(random_percent(proba)){
coloring[random_node]=random_color;
}
}
The following is the debugging information of the 6th and 7th iteration inside the loop.
Breakpoint 1, graph_coloring_local_search (objectiveValue=50, N=50, E=350, edge_list=0x804d170, node_list=0x804dc68, maxIterations=100,
initial_temperature=7) at coloring.c:391
391 proba=exp((-(new-old))/temperature);
(gdb) p new
$21 = 1
(gdb) p old
$22 = 0
(gdb) p temperature
$23 = 6.9992999999999999
(gdb) p -(new-old)/temperature
$24 = -0.14287143000014288
(gdb) p ((double(*)())exp)(-(new-old)/temperature)
$25 = 0.8668655146301385
(gdb) c
Continuing.
proba == 0.86686551463013850060690401733154430985450744628906
Breakpoint 1, graph_coloring_local_search (objectiveValue=50, N=50, E=350, edge_list=0x804d170, node_list=0x804dc68, maxIterations=100,
initial_temperature=7) at coloring.c:391
391 proba=exp((-(new-old))/temperature);
(gdb) p new
$26 = 1
(gdb) p old
$27 = 0
(gdb) p temperature
$28 = 6.9992999999999999
(gdb) p -(new-old)/temperature
$29 = -0.14287143000014288
(gdb) p ((double(*)())exp)(-(new-old)/temperature)
$30 = -nan(0x8000000000000)
(gdb) c
Continuing.
proba == -nan
In both cases the variables used have exactly the same value.
Zack's intuition was right. My random_percent function looks as follows and the round() macro wasn't declared.
int random_percent(double probability){
int edge=round(100*probability);
return ((rand () % 100) < edge) ? 1 : 0;
}
When trying the following in C :
g_string_printf(qbuf,"INSERT INTO inbox (number, smsdate, text) VALUES ('%s','%04d-%02d-%02d %02d:%02d:%02d', '%s')",
xmx.remote.number,
xmx.smsc_time.year,
xmx.smsc_time.month,
xmx.smsc_time.day,
xmx.smsc_time.hour,
xmx.smsc_time.minute,
xmx.smsc_time.second,
xmx.user_data[0].u.text);
I see the following crash:
Program received signal SIGSEGV, Segmentation fault.
0x00984809 in g_string_truncate () from /lib/libglib-2.0.so.0
(gdb)
Why would this happen? Is there any initiation before calling g_string_printf() ?
From frame 2:
(gdb) frame 2
#2 0x08049ba8 in fetching_phone (unit=0x807cd80) at main.c:152
152 g_string_printf(qbuf,"INSERT INTO inbox (number, smsdate, text) VALUES ('%s','%04d-%02d-%02d %02d:%02d:%02d', '%s')",
(gdb) ptype xmx.remote.number
type = char [40]
(gdb) ptype xmx.smsc_time.year
type = int
(gdb) ptype xmx.smsc_time.month
type = int
(gdb) ptype xmx.smsc_time.day
type = int
(gdb) ptype xmx.smsc_time.hour
type = int
(gdb) ptype xmx.smsc_time.minute
type = int
(gdb) ptype xmx.smsc_time.second
type = int
(gdb) ptype xmx.user_data[0].u.text
type = unsigned char [1601]
(gdb)
But, I still can't find where the problem is.
You probably have a bad pointer for the '%s' fields.
As you are running gdb, here is what you can do:
(gdb) bt
...trace...
# see the frame # of your call to g_string_printf()
(gdb) frame 5 # considering it was 5
(gdb) print xmx.remote.number
(gdb) print xmx.user_data[0].u.text
(gdb) print *xmx.remote.number
(gdb) print *xmx.user_data[0].u.text
or you can also check types (is xmx.remote.number a pointer ?)
(gdb) ptype xmx.remote.number
Did you initialize qbuf?
GString *qbuf = g_string_new("");