Wandering about the internet at random, I happened upon this little tidbit about generating neutrinos to communicate through the Earth in UK. I didn't look any further, but it seems they have been at this for a while.
I thought I would comment on compiling and linking the code for the simple OpenGL window that I posted. Basically gcc uses the header files that are provided to find a match for external functions and at link time it looks in the libraries provided for those elements. You need the dev files for a specific library like OpenGL so that gcc knows the format of the call and the variable types to use. The following is the "nm GLwindow" output. It isn't difficult to see in a simple example that after compilation the code links to the specific libraries and then to the device. I think I will do a simple C program and see what the nm looks like when there are no external libraries and just a simple "int main(){return 0;}"
00000000004012d0 T DrawGLScene U XCloseDisplay U XCreateColormap U XCreateWindow U XDestroyWindow U XFree U XLookupKeysym U XLookupString U XMapWindow U XNextEvent U XOpenDisplay U XPending U XSetNormalHints U XSetStandardProperties 0000000000602028 d _DYNAMIC 0000000000602210 d _GLOBAL_OFFSET_TABLE_ 00000000004019c8 R _IO_stdin_used w _Jv_RegisterClasses 0000000000602008 d __CTOR_END__ 0000000000602000 d __CTOR_LIST__ 0000000000602018 d __DTOR_END__ 0000000000602010 d __DTOR_LIST__ 0000000000401c90 r __FRAME_END__ 0000000000602020 d __JCR_END__ 0000000000602020 d __JCR_LIST__ 0000000000602368 A __bss_start 0000000000602348 D __data_start 0000000000401980 t __do_global_ctors_aux 00000000004010f0 t __do_global_dtors_aux 0000000000602350 D __dso_handle w __gmon_start__ 0000000000602000 d __init_array_end 0000000000602000 d __init_array_start 00000000004018e0 T __libc_csu_fini 00000000004018f0 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 U __stack_chk_fail@@GLIBC_2.4 0000000000602368 A _edata 0000000000602370 A _end 00000000004019b4 T _fini 0000000000400e38 T _init 00000000004010a0 T _start 00000000004010cc t call_gmon_start 0000000000602368 b completed.6183 0000000000602348 W data_start 000000000040140c T draw 000000000040178e t event_loop U exit@@GLIBC_2.2.5 0000000000401130 t frame_dummy U gettimeofday@@GLIBC_2.2.5 U glBegin U glClear U glEnd U glFlush U glLoadIdentity U glMatrixMode U glTranslatef U glVertex2f U glViewport U glXChooseVisual U glXCreateContext U glXDestroyContext U glXMakeCurrent U glXSwapBuffers U gluPerspective 0000000000401421 t init 0000000000401158 T main 0000000000401503 t make_window 0000000000602358 d p.6181 U printf@@GLIBC_2.2.5 U puts@@GLIBC_2.2.5 U rand@@GLIBC_2.2.5 0000000000401431 t reshape 00000000004012a5 T seedRandom U srand@@GLIBC_2.2.5 0000000000602360 d windowHeight.13688 0000000000602364 d windowWidth.13687
Also there is the "ldd GLwindow" output which shows what libraries are used at run time. This shows what libraries are used by the code and with such a simple example it is possible to identify how the entire process works. I call a library with a list of options and it uses the code there to perform the function I am interested in. It isn't much different than calling an internal function, but it is merely there to allow for some standard to be maintained. If the underlying system changes, the code is still valid if it conforms to a standard interface.
linux-vdso.so.1 => (0x00007fff2fdfe000) libGL.so.1 => /usr/lib/libGL.so.1 (0x00007f6227b2e000) libglut.so.3 => /usr/lib/libglut.so.3 (0x00007f6227891000) libc.so.6 => /lib/libc.so.6 (0x00007f622752f000) libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00007f62272ab000) libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f6226fa8000) libpthread.so.0 => /lib/libpthread.so.0 (0x00007f6226d8c000) libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f6226b7b000) libm.so.6 => /lib/libm.so.6 (0x00007f62268fa000) /lib64/ld-linux-x86-64.so.2 (0x00007f6227ad5000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f62265ef000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f62263e1000) libxcb-xlib.so.0 => /usr/lib/libxcb-xlib.so.0 (0x00007f62261e0000) libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007f6225fc5000) libdl.so.2 => /lib/libdl.so.2 (0x00007f6225dc1000) libXau.so.6 => /usr/lib/libXau.so.6 (0x00007f6225bbf000) libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f62259ba000)
So here is the ldd and nm from the simplest program I can think of. That is a lot of stuff to do, just to accomplish nothing.
int main(){return 0;}
0000000000600640 d _DYNAMIC 00000000006007e8 d _GLOBAL_OFFSET_TABLE_ 0000000000400544 R _IO_stdin_used w _Jv_RegisterClasses 0000000000600620 d __CTOR_END__ 0000000000600618 d __CTOR_LIST__ 0000000000600630 d __DTOR_END__ 0000000000600628 d __DTOR_LIST__ 0000000000400610 r __FRAME_END__ 0000000000600638 d __JCR_END__ 0000000000600638 d __JCR_LIST__ 0000000000600820 A __bss_start 0000000000600808 D __data_start 0000000000400500 t __do_global_ctors_aux 00000000004003e0 t __do_global_dtors_aux 0000000000600810 D __dso_handle w __gmon_start__ 0000000000600614 d __init_array_end 0000000000600614 d __init_array_start 0000000000400460 T __libc_csu_fini 0000000000400470 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 0000000000600820 A _edata 0000000000600828 A _end 0000000000400534 T _fini 0000000000400350 T _init 0000000000400390 T _start 00000000004003bc t call_gmon_start 0000000000600820 b completed.6183 0000000000600808 W data_start 0000000000400420 t frame_dummy 0000000000400448 T main 0000000000600818 d p.6181 linux-vdso.so.1 => (0x00007fff207fe000) libc.so.6 => /lib/libc.so.6 (0x00007f8c1821b000) /lib64/ld-linux-x86-64.so.2 (0x00007f8c1857d000)
And just for the sake of being complete, here is the ".S" output for the simplest program in the world. As you can see it does an "enter" and saves eSP to eBP , sets Eax to 0 (return 0) and then does a "leave" which restores eSP from eBP and restores eBP from the stack and goes back to the OS. I have seen this a lot when debugging and looking at the stack frame. It is fairly easy to just look and see the progression of the process on the stack, because the return address is just after the eBP and so it is usually very obvious what the call tree looks like.
.file "main.c" .text .globl main .type main, @function main: .LFB2: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: movl $0, %eax leave ret .LFE2: .size main, .-main .section .eh_frame,"a",@progbits .Lframe1: .long .LECIE1-.LSCIE1 .LSCIE1: .long 0x0 .byte 0x1 .string "zR" .uleb128 0x1 .sleb128 -8 .byte 0x10 .uleb128 0x1 .byte 0x3 .byte 0xc .uleb128 0x7 .uleb128 0x8 .byte 0x90 .uleb128 0x1 .align 8 .LECIE1: .LSFDE1: .long .LEFDE1-.LASFDE1 .LASFDE1: .long .LASFDE1-.Lframe1 .long .LFB2 .long .LFE2-.LFB2 .uleb128 0x0 .byte 0x4 .long .LCFI0-.LFB2 .byte 0xe .uleb128 0x10 .byte 0x86 .uleb128 0x2 .byte 0x4 .long .LCFI1-.LCFI0 .byte 0xd .uleb128 0x6 .align 8 .LEFDE1: .ident "GCC: (GNU) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)" .section .note.GNU-stack,"",@progbits
0 comments:
Post a Comment