Sunday, August 13, 2006

Don't be afraid of mdb - cont

I thought I would just quickly show why I did not use any "optimize" flags when I compiled my example code. At the same time I show the er_src program which part of Sun Studio.

First I compile the program with the '-g' flag. This will give er_src access to the source code.
doug@bangkok> cc -g -o ./makecore ./makecore.c
Next run the program and do a pstack. Everything looks fine
doug@bangkok> ./makecore
Memory fault(coredump)
doug@bangkok> /bin/pstack core
core 'core' of 102246: ./makecore
08050775 fruitloop (8060958, 804710c, 80507bb, 8047210, 804712c, 80506ca) + 15
08050794 giveitatry (8047210, 804712c, 80506ca, 1, 8047138, 8047140) + 14
080507bb main (1, 8047138, 8047140) + b
080506ca _start (1, 8047278, 0, 8047283, 8047290, 80472ca) + 7a
Ok, lets have a look at what er_src does
doug@bangkok> /opt/SUNWspro/bin/er_src -func ./makecore

Functions sorted in lexicographic order

Load Object:

Address Size Name

0x000005e0 16 @plt
0x000005f0 16 __fpstart
0x000006dc 123 __fsr
0x00000620 16 _exit
0x000007ec 27 _fini
0x00000640 16 _get_exit_frame_monitor
0x000007d0 27 _init
0x00000650 139 _start
0x00000610 16 atexit
0x00000600 16 exit
0x00000630 16 printf
0x00000760 30 fruitloop
0x00000780 38 giveitatry
0x000007b0 29 main

doug@bangkok> /opt/SUNWspro/bin/er_src -disasm fruitloop ./makecore
Annotated disassembly
---------------------------------------
Source file: ./makecore.c
Object file: ./makecore
Load Object: ./makecore
1. #include
2. #include
3.
4. static void
5. fruitloop(){

[ 5] 8050760: pushl %ebp
[ 5] 8050761: movl %esp,%ebp
[ 5] 8050763: subl $4,%esp
6. char *p;
7. p=(char *)NULL;
[ 7] 8050766: movl $0,-4(%ebp)
8. *p='c';
[ 8] 805076d: movl $0x63,%eax
[ 8] 8050772: movl -4(%ebp),%edx
[ 8] 8050775: movb %al,0(%edx)
[ 8] 8050778: jmp .+4 [ 0x805077c ]
[ 8] 805077a: nop
[ 8] 805077b: nop
9. }
[ 9] 805077c: leave
[ 9] 805077d: ret
10.
11. static void
12. giveitatry(){

[12] 8050780: pushl %ebp
[12] 8050781: movl %esp,%ebp
[12] 8050783: subl $4,%esp
13. char *msg="Ahh we made it!\n";
[13] 8050786: leal 0x8060958,%eax
[13] 805078c: movl %eax,-4(%ebp)
14.
15. fruitloop();
[15] 805078f: call fruitloop [ 0x8050760, .-0x2f ]
16. (void)printf(msg);
[16] 8050794: movl -4(%ebp),%eax
[16] 8050797: pushl %eax
[16] 8050798: call printf [ 0x8050630, .-0x168 ]
[16] 805079d: addl $4,%esp
[16] 80507a0: jmp .+4 [ 0x80507a4 ]
[16] 80507a2: nop
[16] 80507a3: nop
17. }
[17] 80507a4: leave
[17] 80507a5: ret
18.
19. int
20. main(int argc, char **argv){

[20] 80507b0: pushl %ebp
[20] 80507b1: movl %esp,%ebp
[20] 80507b3: subl $4,%esp
21. giveitatry();
[21] 80507b6: call giveitatry [ 0x8050780, .-0x36 ]
22. return(0);
[22] 80507bb: movl $0,-4(%ebp)
[22] 80507c2: jmp .+6 [ 0x80507c8 ]
[22] 80507c4: jmp .+4 [ 0x80507c8 ]
[22] 80507c6: nop
[22] 80507c7: nop
23. }
[23] 80507c8: movl -4(%ebp),%eax
[23] 80507cb: leave
[23] 80507cc: ret
Now, that is really nice. The C program is listed with the assembly code for the corresponding C code. It makes a very nice assembly language tutorial. Now, lets do the same, but compile using the "-fast" flag. (-fast is actually a macro for several other flags. It is known to generally give the best optimized code for your system with the least effort)
doug@bangkok> cc -fast -g -o ./makecore ./makecore.c
doug@bangkok> ./makecore
Memory fault(coredump)
doug@bangkok> /bin/pstack core
core 'core' of 102283: ./makecore
08050850 main (1, 8047278, 0, 8047283, 8047290, 80472ca)
Hmmm, this time it stopped in function main. Lets look at what -fast did to the code.
doug@bangkok> /opt/SUNWspro/bin/er_src -disasm fruitloop ./makecore
Annotated disassembly
---------------------------------------
Source file: ./makecore.c
Object file: ./makecore
Load Object: ./makecore
1. #include
2. #include
3.
4. static void
5. fruitloop(){
6. char *p;
7. p=(char *)NULL;
8. *p='c';

[ 8] 8050820: movb $0x63,0
9. }
[ 9] 8050827: ret

[ 8] 8050830: movb $0x63,0
10.
11. static void
12. giveitatry(){
13. char *msg="Ahh we made it!\n";
14.

Function fruitloop inlined from source file ./makecore.c into the code for the following line. 0 loops inlined
15. fruitloop();
16. (void)printf(msg);
[16] 8050837: subl $8,%esp
[16] 805083a: pushl $0x80609f4
[16] 805083f: call printf [ 0x8050630, .-0x20f ]
[16] 8050844: addl $0xc,%esp
17. }
[17] 8050847: ret

[ 8] 8050850: movb $0x63,0
[16] 8050857: subl $8,%esp
[16] 805085a: pushl $0x80609f4
[16] 805085f: call printf [ 0x8050630, .-0x22f ]
[16] 8050864: addl $0xc,%esp
18.
19. int
20. main(int argc, char **argv){

Function giveitatry inlined from source file ./makecore.c into the code for the following line. 0 loops inlined
Function fruitloop inlined from source file ./makecore.c into inline copy of function giveitatry. 0 loops inlined
21. giveitatry();
22. return(0);
[22] 8050867: xorl %eax,%eax
[22] 8050869: ret
23. }
As you can read from the comments, both of the functions were inlined. Therefore they are now part of the 'main' function. The 'er_src' program is really neat app. Lets see the comment change when we tell it not to inline.
doug@bangkok> cc -fast -g -xinline=no%fruitloop -o ./makecore ./makecore.c
doug@bangkok> /opt/SUNWspro/bin/er_src -disasm fruitloop ./makecore
Annotated disassembly
---------------------------------------
Source file: ./makecore.c
Object file: ./makecore
Load Object: ./makecore
.
.
5. fruitloop(){
6. char *p;
7. p=(char *)NULL;
8. *p='c';

[ 8] 8050820: movb $0x63,0
9. }
[ 9] 8050827: ret
10.
11. static void
12. giveitatry(){
13. char *msg="Ahh we made it!\n";
14.

Function fruitloop not inlined because user explicitly requested that it not be inlined
If you are playing around with optimizing code, then er_src is one tool you should use.

Have Fun!

No comments: