Dear All, First, a clarification: we will use our X-hour for lectures only if previously announced in class or on this list. Please emails me for the office hours; I am also usually available after class to talk about your questions, projects, or interests. Here are some links and resources from today's class. Intel Developer Manuals: http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html Compiling, disassembling, and debugging our toy program: (recorded with script(1), cleaned with a perl script from http://unix.stackexchange.com/questions/14684/removing-control-chars-including-console-codes-colours-from-script-output) Repeat this on your Linux machine. Compare 32-bit and 64-bit versions---they will be significantly different. For amd64/x86_64, the calling convention will be different; read its quick summary in https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI, full details in http://x86-64.org/documentation/abi.pdf See the man page for execv(3), and look carefully at the required arguments and their creation in assembly code. Also see man pages for readelf(1), nm(1), and ld.so(8). (So far, I only used readelf with the -a option.) Look at /boot/System-map- in your Linux machine. This is the map of your kernel with the public kernel symbols. Think of it as the output of nm(1) on the kernel binary image once loaded (on your disk, your images, vmlinuz-*, are stored compressed; hence simply running nm on them won't work) Run nm on your object files and executables that you compile. Compare with the output of objdump and the disas command of gdb. Details on dynamic linking and the PLT and GOT tables: http://www.iecc.com/linker/, chapter 10 (http://www.iecc.com/linker/linker10.html) This is a very good book---and its draft version is posted for free. ================================[ begin script ]================================ sergey@toy32:~$ cat exec.c #include #include int main() { char * args[] = {"/bin/ls", NULL}; printf("pid: %d\n", getpid()); //sleep(60); execv("/bin/ls", args); } sergey@toy32:~$ gcc -E exec.c > exec-preprocessed.txt sergey@toy32:~$ gcc -S exec.c sergey@toy32:~$ grep -v cfi exec.s > exec-cfi-stripped.s sergey@toy32:~$ cat exec-cfi-stripped.s .file "exec.c" .section .rodata .LC0: .string "/bin/ls" .LC1: .string "pid: %d\n" .text .globl main .type main, @function main: .LFB0: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $.LC0, 24(%esp) movl $0, 28(%esp) call getpid movl $.LC1, %edx movl %eax, 4(%esp) movl %edx, (%esp) call printf leal 24(%esp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call execv leave ret .LFE0: .size main, .-main .ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1" .section .note.GNU-stack,"",@progbits sergey@toy32:~$ gcc -g -o exec exec.c sergey@toy32:~$ objdump -d exec > exec.disasm sergey@toy32:~$ gdb ./exec GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /home/sergey/exec...done. (gdb) disas getpid Dump of assembler code for function getpid@plt: 0x08048350 <+0>: jmp *0x804a004 0x08048356 <+6>: push $0x8 0x0804835b <+11>: jmp 0x8048330 End of assembler dump. (gdb) disas printf Dump of assembler code for function printf@plt: 0x08048340 <+0>: jmp *0x804a000 0x08048346 <+6>: push $0x0 0x0804834b <+11>: jmp 0x8048330 End of assembler dump. (gdb) disas execv Dump of assembler code for function execv@plt: 0x08048380 <+0>: jmp *0x804a010 0x08048386 <+6>: push $0x20 0x0804838b <+11>: jmp 0x8048330 End of assembler dump. (gdb) b getpid Breakpoint 1 at 0x8048350 (gdb) b printf Breakpoint 2 at 0x8048340 (gdb) b execv Breakpoint 3 at 0x8048380 (gdb) disas main Dump of assembler code for function main: 0x08048444 <+0>: push %ebp 0x08048445 <+1>: mov %esp,%ebp 0x08048447 <+3>: and $0xfffffff0,%esp 0x0804844a <+6>: sub $0x20,%esp 0x0804844d <+9>: movl $0x8048560,0x18(%esp) 0x08048455 <+17>: movl $0x0,0x1c(%esp) 0x0804845d <+25>: call 0x8048350 0x08048462 <+30>: mov $0x8048568,%edx 0x08048467 <+35>: mov %eax,0x4(%esp) 0x0804846b <+39>: mov %edx,(%esp) 0x0804846e <+42>: call 0x8048340 0x08048473 <+47>: lea 0x18(%esp),%eax 0x08048477 <+51>: mov %eax,0x4(%esp) 0x0804847b <+55>: movl $0x8048560,(%esp) 0x08048482 <+62>: call 0x8048380 0x08048487 <+67>: leave 0x08048488 <+68>: ret End of assembler dump. (gdb) x/2x 0x804a000 0x804a000 : 0x08048346 0x08048356 (gdb) r Starting program: /home/sergey/exec Breakpoint 1, 0x001cd380 in getpid () from /lib/i386-linux-gnu/libc.so.6 (gdb) x/2x 0x804a000 0x804a000 : 0x08048346 0x001cd380 (gdb) c Continuing. Breakpoint 2, 0x0017b1b0 in printf () from /lib/i386-linux-gnu/libc.so.6 (gdb) x/2x 0x804a000 0x804a000 : 0x0017b1b0 0x001cd380 (gdb) c Continuing. pid: 11597 Breakpoint 3, 0x001cca80 in execv () from /lib/i386-linux-gnu/libc.so.6 (gdb) x/x 0x804a010 0x804a010 : 0x001cca80 (gdb) c Continuing. process 11597 is executing new program: /bin/ls [Thread debugging using libthread_db enabled] [Inferior 1 (process 11597) exited normally] (gdb) q ================================[ end script ]================================ See also http://www.cs.dartmouth.edu/~sergey/cs258/dyn-linking-with-gdb.txt for some comments on a similar older transcript. Thanks, --Sergey