The following code, readTwice.c, reads twice from standard input:
int main()
{
char s[8]={0};
read(0, (void *)s, (size_t) 3);
read(0, (void *)(s + 4), (size_t) 3);
for (int i = 0; i < 8; i++)
printf("%d: 0x%x\n", i, s[i]);
return 0;
}
My objective is to, while debugging the corresponding binary, feed the first read() with a first file a (say, created by echo a > a), and the second read() with a second file b (say, created by echo b > b).
Outside GDB, the following bash 5.0 command has the desired effect:
$ ./readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x0
3: 0x0
4: 0x62
5: 0xa
6: 0x0
7: 0x0
However, when running the binary in GDB 8.2.1 with the same process redirection, the first read() call also reads the beginning of the second file:
$ gdb -q readTwice
Reading symbols from readTwice...(no debugging symbols found)...done.
(gdb) run < <(cat a;cat b)
Starting program: /home/av/root-me/ch77/readTwice < <(cat a;cat b)
0: 0x61
1: 0xa
2: 0x62
3: 0x0
4: 0xa
5: 0x0
6: 0x0
7: 0x0
[Inferior 1 (process 4710) exited normally]
(gdb)
Could you help me understand this behaviour and/or tell me about a command having the desired effect ?
The input to your program consists of 4 characters:
'a' '\n' 'b' '\n'
Inside your program you use two reads:
read(0, (void *)s, (size_t) 3);
read(0, (void *)(s + 4), (size_t) 3);
read doesn't read exactly 3 characters. It reads up to 3 characters and returns the number of characters read, see man read(2). I assume by default STDIN_FILENO is blocking on your platform, so it should read at least 1 character.
Possible outcomes:
Both reads read 1 byte. s will have {'a',0,0,0,'\n',0,0,0}. There are 2 unread bytes in the input.
First read read 1 byte, second reads 3 bytes. s will have {'a',0,0,0,'\n','b','\n',0}
First read reads 3 bytes, second reads 1 byte. s will have {'a','\n','b',0,'\n',0,0,0}. This is the output you observe in gdb.
First read reads 2 bytes, second reads 2 bytes. s will have {'a','\n',0,0,'b','\n',0,0}. This is the output you observe when running in shell.
Hopefully you get the idea by now.
Most probably your operating system implements read on STDIN_FILENO in a line buffered fashion on your platform, so the two most possible outcomes are the ones you are observing.
Related
I am trying basic Hello_World program in MPI but it is printing random numbers which shouldn't be printing at all(I am not printing any numbers in the program).
I am following this tutorial:
http://mpitutorial.com/tutorials/running-an-mpi-cluster-within-a-lan/
My mpirun command is as followed:
mpirun -np 2 -host my.ip.add,username#other.ip.add ./a.out
The two computers are connected over same wifi and have same version of MPI installed. The code is as followed:
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d"
" out of %d processors\n",
processor_name, world_rank, world_size);
// Finalize the MPI environment.
MPI_Finalize();
}
EDIT
I ran following mpirun command and the output is as followed:
Command : mpirun -np 1 -host my.ip.add, uname#other.ip.add ./a.out
Output: Hello world from processor pranav, rank 0 out of 1 processors
Changing the number of processes to 2, the following random output as mentioned above is seen:
Command: mpirun -np 2 -host my.ip.add, uname#other.ip.add ./a.out
Output: 199931 199931
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1
6 7 1
7 8 1
8 9 1
9 10 1 ...
The numbers go in an infinite loop with pattern as seen above. Also i would like to note that in first output, there is no output from process of the other computer.
I wrote a simple C program and compiled it for 32 bit architecture.
But when I ran it, I found unexpected results.
#include <stdio.h>
int foo(int n) {
int sum=0;
int i;
if (n <= 1 || n >= 0x1000)
return n;
for (i=0; i<= n; i++) {
sum = sum + i;
}
return foo(sum);
}
int main(int argc, char** argv) {
int n;
n = foo(200);
printf("\n\n main about to return %d \n\n", n);
return n;
}
➜ wbench gcc -o test.elf test.c -m32 -fno-stack-protector -mpreferred-stack-boundary=2 -Wall
➜ wbench ./test.elf
main about to return 20100
➜ wbench echo $?
132
I'm expecting 20100 to be the return value, as printed by the main function.
But, I'm getting 132 as the exit code.
I verified using GDB that 20100 is the value in the eax register when main is about to return.
➜ wbench gdb -q test.elf
gdb-peda$ b *main+44
Breakpoint 1 at 0x8048492
gdb-peda$ r
main about to return 20100
Breakpoint 1, 0x08048492 in main ()
0x8048489 <main+35>: call 0x80482f0 <printf#plt>
0x804848e <main+40>: mov eax,DWORD PTR [ebp-0x4]
0x8048491 <main+43>: leave
=> 0x8048492 <main+44>: ret
0x8048493: xchg ax,ax
gdb-peda$ p/d $eax
$1 = 20100
gdb-peda$ c
[Inferior 1 (process 32172) exited with code 0204]
Warning: not running or target is remote
gdb-peda$ p/d 0204
$2 = 132
I even verified that when control is transferred back to __libc_start_main and exit function is being called, 20100 is being pushed as argument to exit().
gdb-peda$ r
main returning 20100
Breakpoint 1, 0x08048492 in main ()
gdb-peda$ finish
=> 0xf7e1ca83 <__libc_start_main+243>: mov DWORD PTR [esp],eax
0xf7e1ca86 <__libc_start_main+246>: call 0xf7e361e0 <exit>
0xf7e1ca8b <__libc_start_main+251>: xor ecx,ecx
gdb-peda$ si
=> 0xf7e1ca86 <__libc_start_main+246>: call 0xf7e361e0 <exit>
0xf7e1ca8b <__libc_start_main+251>: xor ecx,ecx
gdb-peda$ x/wd $esp
0xffffd5c0: 20100
What could possibly be the reason for this ?
I don't think the exit code 132 here has got anything to do with SIGILL because when I changed the hardcoded argument to foo() from 200 to 2 , the exit code changed to 172 where the expected exit code is 26796.
It looks like what you're doing is invalid, as you only have 8 bits to return to the OS.
Assuming you're linking against libc:
When a program exits, it can return to the parent process a small amount of information about the cause of termination, using the exit status. This is a value between 0 and 255 that the exiting process passes as an argument to exit.
As indicated in its documentation here. Also relevant is this line:
Warning: Don’t try to use the number of errors as the exit status. This is actually not very useful; a parent process would generally not care how many errors occurred. Worse than that, it does not work, because the status value is truncated to eight bits. Thus, if the program tried to report 256 errors, the parent would receive a report of 0 errors—that is, success.
20100 decimal is 4E84 hex.
132 decimal is 84 hex.
Your shell is receiving the return value as only 8 bits.
While your program may be returning 20100, the system only fetches the lowest byte, e.g return % 256
So 20100 % 256 = 132
This kind of usage is common while writing loops.
I was wondering if i >=0 will need more CPU cycles as it has two conditions greater than OR equal to when compared to i > -1. Is one known to be better than the other, and if so, why?
This is not correct. The JIT will implement both tests as a single machine language instruction.
And the number of CPU clock cycles is not determined by the number of comparisons to zero or -1, because the CPU should do one comparison and set flags to indicate whether the result of the comparison is <, > or =.
It's possible that one of those instructions will be more efficient on certain processors, but this kind of micro-optimization is almost always not worth doing. (It's also possible that the JIT - or javac - will actually generate the same instructions for both tests.)
On the contrary, comparsions (including non-strict) with zero takes one CPU instruction less. x86 architecture supports conditional jumps after any arithmetic or loading operation. It is reflected in Java bytecode instruction set, there is a group of instructions to compare the value on the top of the stack and jump: ifeq/ifgt/ifge/iflt/ifle/ifne. (See the full list). Comparsion with -1 requires additional iconst_m1 operation (loading -1 constant onto the stack).
The are two loops with different comparsions:
#GenerateMicroBenchmark
public int loopZeroCond() {
int s = 0;
for (int i = 1000; i >= 0; i--) {
s += i;
}
return s;
}
#GenerateMicroBenchmark
public int loopM1Cond() {
int s = 0;
for (int i = 1000; i > -1; i--) {
s += i;
}
return s;
}
The second version is one byte longer:
public int loopZeroCond();
Code:
0: iconst_0
1: istore_1
2: sipush 1000
5: istore_2
6: iload_2
7: iflt 20 //
10: iload_1
11: iload_2
12: iadd
13: istore_1
14: iinc 2, -1
17: goto 6
20: iload_1
21: ireturn
public int loopM1Cond();
Code:
0: iconst_0
1: istore_1
2: sipush 1000
5: istore_2
6: iload_2
7: iconst_m1 //
8: if_icmple 21 //
11: iload_1
12: iload_2
13: iadd
14: istore_1
15: iinc 2, -1
18: goto 6
21: iload_1
22: ireturn
It is slightly more performant on my machine (to my surprise. I expected JIT to compile these loops into identical assembly.)
Benchmark Mode Thr Mean Mean error Units
t.LoopCond.loopM1Cond avgt 1 0,319 0,004 usec/op
t.LoopCond.loopZeroCond avgt 1 0,302 0,004 usec/op
Сonclusion
Compare with zero whenever sensible.
I like to make GDB set a break point when a variable equal some value I set, I tried this example:
#include <stdio.h>
main()
{
int i = 0;
for(i=0;i<7;++i)
printf("%d\n", i);
return 0;
}
Output from GDB:
(gdb) break if ((int)i == 5)
No default breakpoint address now.
(gdb) run
Starting program: /home/SIFE/run
0
1
2
3
4
5
6
Program exited normally.
(gdb)
Like you see, GDB didn't make any break point, is this possible with GDB?
in addition to a watchpoint nested inside a breakpoint
you can also set a single breakpoint on the 'filename:line_number' and use a condition.
I find it sometimes easier.
(gdb) break iter.c:6 if i == 5
Breakpoint 2 at 0x4004dc: file iter.c, line 6.
(gdb) c
Continuing.
0
1
2
3
4
Breakpoint 2, main () at iter.c:6
6 printf("%d\n", i);
If like me you get tired of line numbers changing, you can add a label
then set the breakpoint on the label like so:
#include <stdio.h>
main()
{
int i = 0;
for(i=0;i<7;++i) {
looping:
printf("%d\n", i);
}
return 0;
}
(gdb) break main:looping if i == 5
You can use a watchpoint for this (A breakpoint on data instead of code).
You can start by using watch i.
Then set a condition for it using condition <breakpoint num> i == 5
You can get the breakpoint number by using info watch
First, you need to compile your code with appropriate flags, enabling debug into code.
$ gcc -Wall -g -ggdb -o ex1 ex1.c
then just run you code with your favourite debugger
$ gdb ./ex1
show me the code.
(gdb) list
1 #include <stdio.h>
2 int main(void)
3 {
4 int i = 0;
5 for(i=0;i<7;++i)
6 printf("%d\n", i);
7
8 return 0;
9 }
break on lines 5 and looks if i == 5.
(gdb) b 5
Breakpoint 1 at 0x4004fb: file ex1.c, line 5.
(gdb) rwatch i if i==5
Hardware read watchpoint 5: i
checking breakpoints
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004004fb in main at ex1.c:5
breakpoint already hit 1 time
5 read watchpoint keep y i
stop only if i==5
running the program
(gdb) c
Continuing.
0
1
2
3
4
Hardware read watchpoint 5: i
Value = 5
0x0000000000400523 in main () at ex1.c:5
5 for(i=0;i<7;++i)
There are hardware and software watchpoints. They are for reading and for writing a variable. You need to consult a tutorial:
http://www.unknownroad.com/rtfm/gdbtut/gdbwatch.html
To set a watchpoint, first you need to break the code into a place where the varianle i is present in the environment, and set the watchpoint.
watch command is used to set a watchpoit for writing, while rwatch for reading, and awatch for reading/writing.
Currently I press right mouse button to select "Copy file path to clipboard" menu. Next left click to source line until where execute code, outside loop (this line number indicated in bottom right corner of WinDbg).
Next in command prompt I set breakpoint (by inserting from clipboard path to file and typing line number, which read from status bar):
bp `d:\home\devel\plugin\plugin-svn\common\win-gui-admin.c:788`
This seems too complicate. In GDB for leaving loops resurved command until. Any way to do this in WinDbg?
F7 gives you the "Run to Cursor" command, which I think does what you're looking for. Just put the cursor on whatever source line you want and then hit F7.
-scott
again a very late answer but one can use source level syntax in windbg
.lines to enable src line support
l+* to enable all src options
lsf to load src file
ls from,to to inspect src lines from current src file
lsc to show current src file
`module!srcfile:linenum` to denaote any line from any src file (src syntax needs to be wrapped in grave accents not single quotes)
here is a sample walkthrough
jmpouttaloo:\>dir /b
jmpouttaloo.cpp
jmpouttaloo:\>type jmpouttaloo.cpp
#include <stdio.h>
int main (void)
{
int i=0,j=0,k=0,l=0;
while (i++ < 100)
{
while (j++ < 100)
{
while(k++ < 100)
{
l++;
}
l++;
}
l++;
}
printf("%d\n",l);
return 0;
}
jmpouttaloo:\>cl /Zi /nologo jmpouttaloo.cpp
jmpouttaloo.cpp
jmpouttaloo:\>dir /b *.exe
jmpouttaloo.exe
jmpouttaloo:\>jmpouttaloo.exe
300
.lines turns on src line support in cdb (it is on by defaukt in windbg )
l+* enables all src line options
lsf load src file jmpouttaloo.cpp
set a bp on main and run the exe
jmpouttaloo:\>cdb -c ".lines;l+*; lsf jmpouttaloo.cpp; bp jmpouttaloo!main;g" jmpouttaloo.exe
stepping with p steps one src line per step
in 6 steps we land inside the innermost while loop
now we want to get out of each loop systematically
ls start , count shows the src lines from start number to startnumber+count
to run until we get to certain src line
do g graveaccent colon linenumber graveaccent
the complete src line syntax as follows
graveaccent modulename! filename : linenumber graveaccent
first run
0:000> cdb: Reading initial command '.lines;l+*; lsf jmpouttaloo.cpp; bp jmpouttaloo!main;g'
Breakpoint 0 hit
> 3: {
0:000> p
> 4: int i=0,j=0,k=0,l=0;
0:000>
> 5: while (i++ < 100)
0:000>
> 7: while (j++ < 100)
0:000>
> 9: while(k++ < 100)
0:000>
> 11: l++;
0:000>
> 12: }
0:000>
> 9: while(k++ < 100)
we are in loop line 12 back to line 9 we need to exit out of this loop at line 13
0:000> ls 13,6 view src lines from line number 13 to 18 (6 lines )
13: l++;
14: }
15: l++;
16: }
17: printf("%d\n",l);
18: return 0;
0:000> dv view locals we have stepped only once so all locals must be 1
j = 0n1
l = 0n1
k = 0n1
i = 0n1
0:000> g `:13` lets get out of innermost loop and look at the locals
> 13: l++;
0:000> dv
j = 0n1
l = 0n100 <-------
k = 0n101 <-------------
i = 0n1
0:000> g `:15` getting out of second innermost loop and inspect locals
> 15: l++;
0:000> dv
j = 0n101
l = 0n200
k = 0n200
i = 0n1
0:000> g `:17` getting out of all loops and inspect locals
> 17: printf("%d\n",l);
0:000> dv
j = 0n200
l = 0n300
k = 0n200
i = 0n101
0:000> p
300 <--------------- output of printf
> 18: return 0;
0:000>
second run
another jig this time we break on line 15 straight without even loading the src
jmpouttaloo:\>cdb -c ".lines;g `jmpouttaloo!jmpouttaloo.cpp:15`;dv;q" jmpouttaloo.exe | grep -A 4 "j ="
j = 0n101
l = 0n200
k = 0n200
i = 0n1
quit:
jmpouttaloo:\>