Intro

This page shows by example the stack layout for an ELF program on the i386 architecture.

Program startup

When a program is started, the first part of the job is done by the kernel, in the code for the execve system call (do_exec(), load_elf_binary()). If there is a .interp section, the interpreter is started. (As in our example case here. The interpreter is /lib/ld-linux.so.2.) Otherwise the object is started directly. In the usual case, the interpreter will fill in the GOT and PLT tables with the appropriate addresses and jump to the objects's _start. There the glibc init code is run, which calls main().

Stack layout

As a first approximation, the stack of a C program on an i386 machine looks like the following (going up from low addresses):
...
local variables of main
saved registers of main
return address of main
argc
argv
envp
stack from startup code
argc
argv pointers
NULL that ends argv[]
environment pointers
NULL that ends envp[]
ELF Auxiliary Table
argv strings
environment strings
program name
NULL
and ends at 0xc0000000. Let us dump a stack, and look. The argv strings and environment strings are character strings, most of the rest are 4-byte integers or pointers, so let us dump things that way.

dumpstack.c

Program dumpstack.c
#include <stdio.h>
extern char **environ;

int main(int argc, char **argv) {
        unsigned int a, *x;
	unsigned char *y;

	printf("argv = %08x\n", (unsigned int) argv);
	printf("argv[0] = %08x\n", (unsigned int) argv[0]);
	printf("environ = %08x\n", (unsigned int) environ);
	printf("environ[0] = %08x\n", (unsigned int) environ[0]);
	printf("\n\n");

        x = (unsigned int *) ((unsigned int) &a & ~0xf);
        while ((unsigned int) x < (unsigned int) argv[0]) {
                printf("%08x:", (unsigned int) x);
                for (a=0; a<4; a++)
                        printf(" %08x", x[a]);
                printf("\n");
                x += 4;
        }

	printf("\n\n");
	y = (unsigned char *) ((unsigned int) argv[0] & ~0xf) - 16;
        while ((unsigned int) y < 0xc0000000) {
                printf("%08x:", (unsigned int) y);
                for (a=0; a<16; a++)
                        printf(" %02x", y[a]);
		printf("   ");
		for (a=0; a<16; a++)
			putchar((y[a] > 32 && y[a] < 127) ? y[a] : '.');
                printf("\n");
                y += 16;
        }
        return 0;
}

The dumped stack

Call:
% ./dumpstack aap noot mies
Output (all is in hex), with comments interspersed:
argv = bffff534
argv[0] = bffff6d0
environ = bffff548
environ[0] = bffff6ea

main()

The local variables x and a of main
bffff4a0: bffff4a0 00000001
The saved frame pointer %ebp and the return address of main
bffff4a0:                   bffff508 4004b500
The parameters of main: argc, argv, envp
bffff4b0: 00000004 bffff534 bffff548         

glibc startup

The following was produced by glibc:sysdeps/generic/libc-start.c:__libc_start_main
bffff4b0:                            40017970
bffff4c0: 40147bd0 400168c0 08048600 bffff508
bffff4d0: bffff4b0 4004b4c5 00000000 00000000
bffff4e0: 00000000 40016cbc 00000004 08048360
bffff4f0: 00000000 4000ca40 4000d330 40016cbc
bffff500: 00000004 08048360 00000000         
The following was produced by glibc:sysdeps/i386/elf/start.S:_start (push the parameters for __libc_start_main and call it)

Return address for the call of __libc_start_main at 0x804837c, points to the final hlt

bffff500:                            08048381
Eight values pushed by _start: main, argc, argv, __libc_csu_init, __libc_csu_fini, %edx (rtld_fini), %esp, %eax (padding)
bffff510: 0804841c 00000004 bffff534 08048670
bffff520: 08048600 4000d330 bffff52c 00000000
The first seven are the parameters of __libc_start_main().

stack set by kernel

The following was produced by kernel:fs/binfmt_elf.c:create_elf_tables()

argc, followed by the array of argv pointers, followed by NULL:

bffff530: 00000004 bffff6d0 bffff6dc bffff6e0
bffff540: bffff6e5 00000000                  
The global variable environ has the value 0xbffff548. It points at an array of string pointers, closed by NULL.
bffff540:                   bffff6ea bffff703
bffff550: bffff74d bffff75d bffff78f bffff79e
bffff560: bffff7c5 bffff7ec bffff7f7 bffff802
bffff570: bffff812 bffff823 bffff831 bffff84d
bffff580: bffff85f bffff872 bffff88d bffff896
bffff590: bffffb57 bffffb77 bffffb85 bffffb90
bffff5a0: bffffb9e bffffbb2 bffffbc5 bffffc5e
bffff5b0: bffffc67 bffffc85 bffffc9a bffffcaf
bffff5c0: bffffcc7 bffffcd8 bffffcef bffffd5d
bffff5d0: bffffd74 bffffd7c bffffd8b bffffda9
bffff5e0: bffffdb6 bffffdd5 bffffde8 bffffe03
bffff5f0: bffffe24 bffffe6c bffffe77 bffffe90
bffff600: bffffe9c bffffea8 bffffefd bfffff15
bffff610: bfffff3b bfffff6e bfffff7b bfffff98
bffff620: bfffffad bfffffc5 bfffffd1 bfffffdf
bffff630: 00000000                           

ELF Auxiliary Table

The ELF Auxiliary Table is a list of (id,value) pairs.
AT_SYSINFO=32 VSYSCALL_ENTRY: 0xffffe400
AT_SYSINFO_EHDR=33 VSYSCALL_BASE: 0xffffe000
AT_HWCAP=16 hardware capabilities: 0x0183f9ff
AT_PAGESZ=6 page size: 4096
AT_CLKTCK=17 clock frequency for times(): 100 Hz
AT_PHDR=3 address program headers: 0x08048034
AT_PHENT=4 size of program header: 32
AT_PHNUM=5 number of program headers: 8
AT_BASE=7 base address of interpreter: 0x40000000
AT_FLAGS=8 flags: 0
AT_ENTRY=9 program entry point: 0x08048360
AT_UID=11 uid: 500
AT_EUID=12 effective uid: 500
AT_GID=13 gid: 100
AT_EGID=14 effective gid: 100
AT_SECURE=23 secure mode boolean: 0
AT_PLATFORM=15 address of platform string: 0xbffff6cb
AT_NULL=0 end of table
bffff630:          00000020 ffffe400 00000021
bffff640: ffffe000 00000010 0183f9ff 00000006
bffff650: 00001000 00000011 00000064 00000003
bffff660: 08048034 00000004 00000020 00000005
bffff670: 00000008 00000007 40000000 00000008
bffff680: 00000000 00000009 08048360 0000000b
bffff690: 000001f4 0000000c 000001f4 0000000d
bffff6a0: 00000064 0000000e 00000064 00000017
bffff6b0: 00000000 0000000f bffff6cb 00000000
bffff6c0: 00000000                           
Padding and platform string
bffff6c0:          00000000 69000000 00363836
The kernel part of the stack, starting with argc, is aligned on a 16-byte boundary, while the strings are packed towards the end, so one needs 0-15 bytes of padding in between. Here there is 7 bytes of padding.

The strings

Here we start giving the data in bytes instead of integers.

platform

The ELF_PLATFORM string, defined in <asm/elf.h>. For the i386 architecture it is the output of `uname -m`.

platform: i686

bffff6c0:                                  69 36 38 36 00              i686.

argv strings

The following was produced by kernel:fs/exec.c:do_execve() and is the same for all types of binary: argv strings, environment strings, program name, NULL.

argv strings: ./dumpstack aap noot mies

bffff6d0: 2e 2f 64 75 6d 70 73 74 61 63 6b 00 61 61 70 00   ./dumpstack.aap.
bffff6e0: 6e 6f 6f 74 00 6d 69 65 73 00                     noot.mies.      

environment strings

environment strings: LESSKEY=/etc/lesskey.bin MANPATH=...
bffff6e0:                               4c 45 53 53 4b 45             LESSKE
bffff6f0: 59 3d 2f 65 74 63 2f 6c 65 73 73 6b 65 79 2e 62   Y=/etc/lesskey.b
bffff700: 69 6e 00 4d 41 4e 50 41 54 48 3d 2f 75 73 72 2f   in.MANPATH=/usr/
... ... _=./dumpstack OLDPWD=/home/aeb
bfffffd0: 00 5f 3d 2e 2f 64 75 6d 70 73 74 61 63 6b 00 4f   ._=./dumpstack.O
bfffffe0: 4c 44 50 57 44 3d 2f 68 6f 6d 65 2f 61 65 62 00   LDPWD=/home/aeb.

program name

program name: ./dumpstack
bffffff0: 2e 2f 64 75 6d 70 73 74 61 63 6b 00               ./dumpstack.    

Final NULL

bffffff0:                                     00 00 00 00               ....

objdump

Below the output of
% objdump -d dumpstack
We see that the entry point 0x08048360 is the label _start.
dumpstack:     file format elf32-i386

Disassembly of section .init:

08048300 <_init>:
 8048300:	55                   	push   %ebp
 8048301:	89 e5                	mov    %esp,%ebp
 8048303:	83 ec 08             	sub    $0x8,%esp
 8048306:	e8 79 00 00 00       	call   8048384 <call_gmon_start>
 804830b:	e8 e0 00 00 00       	call   80483f0 <frame_dummy>
 8048310:	e8 bb 03 00 00       	call   80486d0 <__do_global_ctors_aux>
 8048315:	c9                   	leave  
 8048316:	c3                   	ret    

Disassembly of section .plt:

 8048318:       ff 35 6c 98 04 08       pushl  0x804986c
 804831e:       ff 25 70 98 04 08       jmp    *0x8049870
 8048324:       00 00                   add    %al,(%eax)
 8048326:       00 00                   add    %al,(%eax)

08048328 <putchar@plt>:
 8048328:       ff 25 74 98 04 08       jmp    *0x8049874
 804832e:       68 00 00 00 00          push   $0x0
 8048333:       e9 e0 ff ff ff          jmp    8048318 <_init+0x18>

08048338 <__libc_start_main@plt>:
 8048338:       ff 25 78 98 04 08       jmp    *0x8049878
 804833e:       68 08 00 00 00          push   $0x8
 8048343:       e9 d0 ff ff ff          jmp    8048318 <_init+0x18>

08048348 <printf@plt>:
 8048348:       ff 25 7c 98 04 08       jmp    *0x804987c
 804834e:       68 10 00 00 00          push   $0x10
 8048353:       e9 c0 ff ff ff          jmp    8048318 <_init+0x18>

Disassembly of section .text:

08048360 <_start>:
 8048360:	31 ed                	xor    %ebp,%ebp
 8048362:	5e                   	pop    %esi
 8048363:	89 e1                	mov    %esp,%ecx
 8048365:	83 e4 f0             	and    $0xfffffff0,%esp
 8048368:	50                   	push   %eax
 8048369:	54                   	push   %esp
 804836a:	52                   	push   %edx
 804836b:	68 00 86 04 08       	push   $0x8048600
 8048370:	68 70 86 04 08       	push   $0x8048670
 8048375:	51                   	push   %ecx
 8048376:	56                   	push   %esi
 8048377:	68 1c 84 04 08       	push   $0x804841c
 804837c:	e8 b7 ff ff ff       	call   8048338 <__libc_start_main>
 8048381:	f4                   	hlt    
 8048382:	90                   	nop    
 8048383:	90                   	nop    

08048384 <call_gmon_start>:
 8048384:	55                   	push   %ebp
 8048385:	89 e5                	mov    %esp,%ebp
 8048387:	53                   	push   %ebx
 8048388:	e8 00 00 00 00       	call   804838d <call_gmon_start+0x9>
 804838d:	5b                   	pop    %ebx
 804838e:	81 c3 db 14 00 00    	add    $0x14db,%ebx
 8048394:	52                   	push   %edx
 8048395:	8b 83 18 00 00 00    	mov    0x18(%ebx),%eax
 804839b:	85 c0                	test   %eax,%eax
 804839d:	74 02                	je     80483a1 <call_gmon_start+0x1d>
 804839f:	ff d0                	call   *%eax
 80483a1:	58                   	pop    %eax
 80483a2:	5b                   	pop    %ebx
 80483a3:	c9                   	leave  
 80483a4:	c3                   	ret    
 80483a5:	90                   	nop    
 80483a6:	90                   	nop    
 80483a7:	90                   	nop    
 80483a8:	90                   	nop    
 80483a9:	90                   	nop    
 80483aa:	90                   	nop    
 80483ab:	90                   	nop    
 80483ac:	90                   	nop    
 80483ad:	90                   	nop    
 80483ae:	90                   	nop    
 80483af:	90                   	nop    

080483b0 <__do_global_dtors_aux>:
 80483b0:	55                   	push   %ebp
 80483b1:	89 e5                	mov    %esp,%ebp
 80483b3:	50                   	push   %eax
 80483b4:	50                   	push   %eax
 80483b5:	80 3d 88 98 04 08 00 	cmpb   $0x0,0x8049888
 80483bc:	75 2e                	jne    80483ec <__do_global_dtors_aux+0x3c>
 80483be:	a1 84 97 04 08       	mov    0x8049784,%eax
 80483c3:	8b 10                	mov    (%eax),%edx
 80483c5:	85 d2                	test   %edx,%edx
 80483c7:	74 1c                	je     80483e5 <__do_global_dtors_aux+0x35>
 80483c9:	8d b4 26 00 00 00 00 	lea    0x0(%esi),%esi
 80483d0:	83 c0 04             	add    $0x4,%eax
 80483d3:	a3 84 97 04 08       	mov    %eax,0x8049784
 80483d8:	ff d2                	call   *%edx
 80483da:	a1 84 97 04 08       	mov    0x8049784,%eax
 80483df:	8b 10                	mov    (%eax),%edx
 80483e1:	85 d2                	test   %edx,%edx
 80483e3:	75 eb                	jne    80483d0 <__do_global_dtors_aux+0x20>
 80483e5:	c6 05 88 98 04 08 01 	movb   $0x1,0x8049888
 80483ec:	c9                   	leave  
 80483ed:	c3                   	ret    
 80483ee:	89 f6                	mov    %esi,%esi

080483f0 <frame_dummy>:
 80483f0:	55                   	push   %ebp
 80483f1:	89 e5                	mov    %esp,%ebp
 80483f3:	51                   	push   %ecx
 80483f4:	51                   	push   %ecx
 80483f5:	8b 15 64 98 04 08    	mov    0x8049864,%edx
 80483fb:	85 d2                	test   %edx,%edx
 80483fd:	74 19                	je     8048418 <frame_dummy+0x28>
 80483ff:	b8 00 00 00 00       	mov    $0x0,%eax
 8048404:	85 c0                	test   %eax,%eax
 8048406:	74 10                	je     8048418 <frame_dummy+0x28>
 8048408:	83 ec 0c             	sub    $0xc,%esp
 804840b:	68 64 98 04 08       	push   $0x8049864
 8048410:	e8 eb 7b fb f7       	call   0 <_init-0x8048300>
 8048415:	83 c4 10             	add    $0x10,%esp
 8048418:	c9                   	leave  
 8048419:	c3                   	ret    
 804841a:	90                   	nop    
 804841b:	90                   	nop    

0804841c <main>:
 804841c:	55                   	push   %ebp
 804841d:	89 e5                	mov    %esp,%ebp
 804841f:	83 ec 18             	sub    $0x18,%esp
 8048422:	83 e4 f0             	and    $0xfffffff0,%esp
 8048425:	b8 00 00 00 00       	mov    $0x0,%eax
 804842a:	29 c4                	sub    %eax,%esp
 804842c:	83 ec 08             	sub    $0x8,%esp
 804842f:	ff 75 0c             	pushl  0xc(%ebp)
 8048432:	68 18 87 04 08       	push   $0x8048718
 8048437:	e8 0c ff ff ff       	call   8048348 <_init+0x48>
 804843c:	83 c4 10             	add    $0x10,%esp
 804843f:	83 ec 08             	sub    $0x8,%esp
 8048442:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048445:	ff 30                	pushl  (%eax)
 8048447:	68 25 87 04 08       	push   $0x8048725
 804844c:	e8 f7 fe ff ff       	call   8048348 <_init+0x48>
 8048451:	83 c4 10             	add    $0x10,%esp
 8048454:	83 ec 08             	sub    $0x8,%esp
 8048457:	ff 35 84 98 04 08    	pushl  0x8049884
 804845d:	68 35 87 04 08       	push   $0x8048735
 8048462:	e8 e1 fe ff ff       	call   8048348 <_init+0x48>
 8048467:	83 c4 10             	add    $0x10,%esp
 804846a:	83 ec 08             	sub    $0x8,%esp
 804846d:	a1 84 98 04 08       	mov    0x8049884,%eax
 8048472:	ff 30                	pushl  (%eax)
 8048474:	68 47 87 04 08       	push   $0x8048747
 8048479:	e8 ca fe ff ff       	call   8048348 <_init+0x48>
 804847e:	83 c4 10             	add    $0x10,%esp
 8048481:	83 ec 0c             	sub    $0xc,%esp
 8048484:	68 5c 87 04 08       	push   $0x804875c
 8048489:	e8 ba fe ff ff       	call   8048348 <_init+0x48>
 804848e:	83 c4 10             	add    $0x10,%esp
 8048491:	8d 45 fc             	lea    0xfffffffc(%ebp),%eax
 8048494:	83 e0 f0             	and    $0xfffffff0,%eax
 8048497:	89 45 f8             	mov    %eax,0xfffffff8(%ebp)
 804849a:	8b 55 0c             	mov    0xc(%ebp),%edx
 804849d:	8b 45 f8             	mov    0xfffffff8(%ebp),%eax
 80484a0:	3b 02                	cmp    (%edx),%eax
 80484a2:	72 02                	jb     80484a6 <main+0x8a>
 80484a4:	eb 61                	jmp    8048507 <main+0xeb>
 80484a6:	83 ec 08             	sub    $0x8,%esp
 80484a9:	ff 75 f8             	pushl  0xfffffff8(%ebp)
 80484ac:	68 5f 87 04 08       	push   $0x804875f
 80484b1:	e8 92 fe ff ff       	call   8048348 <_init+0x48>
 80484b6:	83 c4 10             	add    $0x10,%esp
 80484b9:	c7 45 fc 00 00 00 00 	movl   $0x0,0xfffffffc(%ebp)
 80484c0:	83 7d fc 03          	cmpl   $0x3,0xfffffffc(%ebp)
 80484c4:	76 02                	jbe    80484c8 <main+0xac>
 80484c6:	eb 27                	jmp    80484ef <main+0xd3>
 80484c8:	83 ec 08             	sub    $0x8,%esp
 80484cb:	8b 45 fc             	mov    0xfffffffc(%ebp),%eax
 80484ce:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 80484d5:	8b 45 f8             	mov    0xfffffff8(%ebp),%eax
 80484d8:	ff 34 10             	pushl  (%eax,%edx,1)
 80484db:	68 67 87 04 08       	push   $0x8048767
 80484e0:	e8 63 fe ff ff       	call   8048348 <_init+0x48>
 80484e5:	83 c4 10             	add    $0x10,%esp
 80484e8:	8d 45 fc             	lea    0xfffffffc(%ebp),%eax
 80484eb:	ff 00                	incl   (%eax)
 80484ed:	eb d1                	jmp    80484c0 <main+0xa4>
 80484ef:	83 ec 0c             	sub    $0xc,%esp
 80484f2:	68 6d 87 04 08       	push   $0x804876d
 80484f7:	e8 4c fe ff ff       	call   8048348 <_init+0x48>
 80484fc:	83 c4 10             	add    $0x10,%esp
 80484ff:	8d 45 f8             	lea    0xfffffff8(%ebp),%eax
 8048502:	83 00 10             	addl   $0x10,(%eax)
 8048505:	eb 93                	jmp    804849a <main+0x7e>
 8048507:	83 ec 0c             	sub    $0xc,%esp
 804850a:	68 5c 87 04 08       	push   $0x804875c
 804850f:	e8 34 fe ff ff       	call   8048348 <_init+0x48>
 8048514:	83 c4 10             	add    $0x10,%esp
 8048517:	8b 45 0c             	mov    0xc(%ebp),%eax
 804851a:	8b 00                	mov    (%eax),%eax
 804851c:	83 e0 f0             	and    $0xfffffff0,%eax
 804851f:	83 e8 10             	sub    $0x10,%eax
 8048522:	89 45 f4             	mov    %eax,0xfffffff4(%ebp)
 8048525:	81 7d f4 ff ff ff bf 	cmpl   $0xbfffffff,0xfffffff4(%ebp)
 804852c:	76 05                	jbe    8048533 <main+0x117>
 804852e:	e9 c5 00 00 00       	jmp    80485f8 <main+0x1dc>
 8048533:	83 ec 08             	sub    $0x8,%esp
 8048536:	ff 75 f4             	pushl  0xfffffff4(%ebp)
 8048539:	68 5f 87 04 08       	push   $0x804875f
 804853e:	e8 05 fe ff ff       	call   8048348 <_init+0x48>
 8048543:	83 c4 10             	add    $0x10,%esp
 8048546:	c7 45 fc 00 00 00 00 	movl   $0x0,0xfffffffc(%ebp)
 804854d:	83 7d fc 0f          	cmpl   $0xf,0xfffffffc(%ebp)
 8048551:	76 02                	jbe    8048555 <main+0x139>
 8048553:	eb 25                	jmp    804857a <main+0x15e>
 8048555:	83 ec 08             	sub    $0x8,%esp
 8048558:	8b 45 fc             	mov    0xfffffffc(%ebp),%eax
 804855b:	03 45 f4             	add    0xfffffff4(%ebp),%eax
 804855e:	8a 00                	mov    (%eax),%al
 8048560:	25 ff 00 00 00       	and    $0xff,%eax
 8048565:	50                   	push   %eax
 8048566:	68 6f 87 04 08       	push   $0x804876f
 804856b:	e8 d8 fd ff ff       	call   8048348 <_init+0x48>
 8048570:	83 c4 10             	add    $0x10,%esp
 8048573:	8d 45 fc             	lea    0xfffffffc(%ebp),%eax
 8048576:	ff 00                	incl   (%eax)
 8048578:	eb d3                	jmp    804854d <main+0x131>
 804857a:	83 ec 0c             	sub    $0xc,%esp
 804857d:	68 75 87 04 08       	push   $0x8048775
 8048582:	e8 c1 fd ff ff       	call   8048348 <_init+0x48>
 8048587:	83 c4 10             	add    $0x10,%esp
 804858a:	c7 45 fc 00 00 00 00 	movl   $0x0,0xfffffffc(%ebp)
 8048591:	83 7d fc 0f          	cmpl   $0xf,0xfffffffc(%ebp)
 8048595:	76 02                	jbe    8048599 <main+0x17d>
 8048597:	eb 44                	jmp    80485dd <main+0x1c1>
 8048599:	83 ec 0c             	sub    $0xc,%esp
 804859c:	8b 45 fc             	mov    0xfffffffc(%ebp),%eax
 804859f:	03 45 f4             	add    0xfffffff4(%ebp),%eax
 80485a2:	80 38 20             	cmpb   $0x20,(%eax)
 80485a5:	76 1d                	jbe    80485c4 <main+0x1a8>
 80485a7:	8b 45 fc             	mov    0xfffffffc(%ebp),%eax
 80485aa:	03 45 f4             	add    0xfffffff4(%ebp),%eax
 80485ad:	80 38 7e             	cmpb   $0x7e,(%eax)
 80485b0:	77 12                	ja     80485c4 <main+0x1a8>
 80485b2:	8b 45 fc             	mov    0xfffffffc(%ebp),%eax
 80485b5:	03 45 f4             	add    0xfffffff4(%ebp),%eax
 80485b8:	ba 00 00 00 00       	mov    $0x0,%edx
 80485bd:	8a 10                	mov    (%eax),%dl
 80485bf:	89 55 f0             	mov    %edx,0xfffffff0(%ebp)
 80485c2:	eb 07                	jmp    80485cb <main+0x1af>
 80485c4:	c7 45 f0 2e 00 00 00 	movl   $0x2e,0xfffffff0(%ebp)
 80485cb:	ff 75 f0             	pushl  0xfffffff0(%ebp)
 80485ce:	e8 55 fd ff ff       	call   8048328 <_init+0x28>
 80485d3:	83 c4 10             	add    $0x10,%esp
 80485d6:	8d 45 fc             	lea    0xfffffffc(%ebp),%eax
 80485d9:	ff 00                	incl   (%eax)
 80485db:	eb b4                	jmp    8048591 <main+0x175>
 80485dd:	83 ec 0c             	sub    $0xc,%esp
 80485e0:	68 6d 87 04 08       	push   $0x804876d
 80485e5:	e8 5e fd ff ff       	call   8048348 <_init+0x48>
 80485ea:	83 c4 10             	add    $0x10,%esp
 80485ed:	8d 45 f4             	lea    0xfffffff4(%ebp),%eax
 80485f0:	83 00 10             	addl   $0x10,(%eax)
 80485f3:	e9 2d ff ff ff       	jmp    8048525 <main+0x109>
 80485f8:	b8 00 00 00 00       	mov    $0x0,%eax
 80485fd:	c9                   	leave  
 80485fe:	c3                   	ret    
 80485ff:	90                   	nop    

08048600 <__libc_csu_fini>:
 8048600:	55                   	push   %ebp
 8048601:	89 e5                	mov    %esp,%ebp
 8048603:	83 ec 18             	sub    $0x18,%esp
 8048606:	89 5d f4             	mov    %ebx,0xfffffff4(%ebp)
 8048609:	e8 ba 00 00 00       	call   80486c8 <__i686.get_pc_thunk.bx>
 804860e:	81 c3 5a 12 00 00    	add    $0x125a,%ebx
 8048614:	89 7d fc             	mov    %edi,0xfffffffc(%ebp)
 8048617:	8d 83 14 ff ff ff    	lea    0xffffff14(%ebx),%eax
 804861d:	8d bb 14 ff ff ff    	lea    0xffffff14(%ebx),%edi
 8048623:	89 75 f8             	mov    %esi,0xfffffff8(%ebp)
 8048626:	29 f8                	sub    %edi,%eax
 8048628:	c1 f8 02             	sar    $0x2,%eax
 804862b:	85 c0                	test   %eax,%eax
 804862d:	8d 70 ff             	lea    0xffffffff(%eax),%esi
 8048630:	75 12                	jne    8048644 <__libc_csu_fini+0x44>
 8048632:	e8 bd 00 00 00       	call   80486f4 <_fini>
 8048637:	8b 5d f4             	mov    0xfffffff4(%ebp),%ebx
 804863a:	8b 75 f8             	mov    0xfffffff8(%ebp),%esi
 804863d:	8b 7d fc             	mov    0xfffffffc(%ebp),%edi
 8048640:	89 ec                	mov    %ebp,%esp
 8048642:	5d                   	pop    %ebp
 8048643:	c3                   	ret    
 8048644:	ff 14 b7             	call   *(%edi,%esi,4)
 8048647:	89 f0                	mov    %esi,%eax
 8048649:	4e                   	dec    %esi
 804864a:	85 c0                	test   %eax,%eax
 804864c:	75 f6                	jne    8048644 <__libc_csu_fini+0x44>
 804864e:	89 f6                	mov    %esi,%esi
 8048650:	e8 9f 00 00 00       	call   80486f4 <_fini>
 8048655:	8b 5d f4             	mov    0xfffffff4(%ebp),%ebx
 8048658:	8b 75 f8             	mov    0xfffffff8(%ebp),%esi
 804865b:	8b 7d fc             	mov    0xfffffffc(%ebp),%edi
 804865e:	89 ec                	mov    %ebp,%esp
 8048660:	5d                   	pop    %ebp
 8048661:	c3                   	ret    
 8048662:	8d b4 26 00 00 00 00 	lea    0x0(%esi),%esi
 8048669:	8d bc 27 00 00 00 00 	lea    0x0(%edi),%edi

08048670 <__libc_csu_init>:
 8048670:	55                   	push   %ebp
 8048671:	89 e5                	mov    %esp,%ebp
 8048673:	83 ec 18             	sub    $0x18,%esp
 8048676:	89 5d f4             	mov    %ebx,0xfffffff4(%ebp)
 8048679:	89 75 f8             	mov    %esi,0xfffffff8(%ebp)
 804867c:	31 f6                	xor    %esi,%esi
 804867e:	e8 45 00 00 00       	call   80486c8 <__i686.get_pc_thunk.bx>
 8048683:	81 c3 e5 11 00 00    	add    $0x11e5,%ebx
 8048689:	89 7d fc             	mov    %edi,0xfffffffc(%ebp)
 804868c:	e8 6f fc ff ff       	call   8048300 <_init>
 8048691:	8d 93 14 ff ff ff    	lea    0xffffff14(%ebx),%edx
 8048697:	8d 83 14 ff ff ff    	lea    0xffffff14(%ebx),%eax
 804869d:	29 c2                	sub    %eax,%edx
 804869f:	c1 fa 02             	sar    $0x2,%edx
 80486a2:	39 d6                	cmp    %edx,%esi
 80486a4:	73 15                	jae    80486bb <__libc_csu_init+0x4b>
 80486a6:	89 45 f0             	mov    %eax,0xfffffff0(%ebp)
 80486a9:	89 d7                	mov    %edx,%edi
 80486ab:	90                   	nop    
 80486ac:	8d 74 26 00          	lea    0x0(%esi),%esi
 80486b0:	ff 14 b0             	call   *(%eax,%esi,4)
 80486b3:	46                   	inc    %esi
 80486b4:	8b 45 f0             	mov    0xfffffff0(%ebp),%eax
 80486b7:	39 fe                	cmp    %edi,%esi
 80486b9:	72 f5                	jb     80486b0 <__libc_csu_init+0x40>
 80486bb:	8b 5d f4             	mov    0xfffffff4(%ebp),%ebx
 80486be:	8b 75 f8             	mov    0xfffffff8(%ebp),%esi
 80486c1:	8b 7d fc             	mov    0xfffffffc(%ebp),%edi
 80486c4:	89 ec                	mov    %ebp,%esp
 80486c6:	5d                   	pop    %ebp
 80486c7:	c3                   	ret    

080486c8 <__i686.get_pc_thunk.bx>:
 80486c8:	8b 1c 24             	mov    (%esp),%ebx
 80486cb:	c3                   	ret    
 80486cc:	90                   	nop    
 80486cd:	90                   	nop    
 80486ce:	90                   	nop    
 80486cf:	90                   	nop    

080486d0 <__do_global_ctors_aux>:
 80486d0:	55                   	push   %ebp
 80486d1:	89 e5                	mov    %esp,%ebp
 80486d3:	53                   	push   %ebx
 80486d4:	52                   	push   %edx
 80486d5:	bb 54 98 04 08       	mov    $0x8049854,%ebx
 80486da:	a1 54 98 04 08       	mov    0x8049854,%eax
 80486df:	83 f8 ff             	cmp    $0xffffffff,%eax
 80486e2:	74 0c                	je     80486f0 <__do_global_ctors_aux+0x20>
 80486e4:	83 eb 04             	sub    $0x4,%ebx
 80486e7:	ff d0                	call   *%eax
 80486e9:	8b 03                	mov    (%ebx),%eax
 80486eb:	83 f8 ff             	cmp    $0xffffffff,%eax
 80486ee:	75 f4                	jne    80486e4 <__do_global_ctors_aux+0x14>
 80486f0:	58                   	pop    %eax
 80486f1:	5b                   	pop    %ebx
 80486f2:	5d                   	pop    %ebp
 80486f3:	c3                   	ret    

Disassembly of section .fini:

080486f4 <_fini>:
 80486f4:	55                   	push   %ebp
 80486f5:	89 e5                	mov    %esp,%ebp
 80486f7:	53                   	push   %ebx
 80486f8:	e8 00 00 00 00       	call   80486fd <_fini+0x9>
 80486fd:	5b                   	pop    %ebx
 80486fe:	81 c3 6b 11 00 00    	add    $0x116b,%ebx
 8048704:	50                   	push   %eax
 8048705:	e8 a6 fc ff ff       	call   80483b0 <__do_global_dtors_aux>
 804870a:	59                   	pop    %ecx
 804870b:	5b                   	pop    %ebx
 804870c:	c9                   	leave  
 804870d:	c3                   	ret    

gcc4

The above listing came from a compilation that used GCC 3.3.3. Some interesting details differ with GCC 4.1.0.

In the above, main() did

 804841c:       55                      push   %ebp
 804841d:       89 e5                   mov    %esp,%ebp
 804841f:       83 ec 18                sub    $0x18,%esp
 8048422:       83 e4 f0                and    $0xfffffff0,%esp
...
 80485fd:       c9                      leave
 80485fe:       c3                      ret
With gcc4 we see
 8048474:       8d 4c 24 04             lea    0x4(%esp),%ecx
 8048478:       83 e4 f0                and    $0xfffffff0,%esp
 804847b:       ff 71 fc                pushl  0xfffffffc(%ecx)
 804847e:       55                      push   %ebp
 804847f:       89 e5                   mov    %esp,%ebp
 8048481:       51                      push   %ecx
 8048482:       83 ec 24                sub    $0x24,%esp
...
 80486c3:       83 c4 24                add    $0x24,%esp
 80486c6:       59                      pop    %ecx
 80486c7:       5d                      pop    %ebp
 80486c8:       8d 61 fc                lea    0xfffffffc(%ecx),%esp
 80486cb:       c3                      ret    
That is, the address of the first parameter (traditionally argc) to main is taken, the stack pointer is aligned to 0 (mod 16), another copy of the return address is pushed, the frame pointer is saved, a new frame pointer is set up, and and the address of argc is pushed. Upon return, the "outer" return address is used, the one below argc. For people contemplating buffer overflow attacks, this means that the first thing overwritten is not the return address, but the address of the location following that of the return address. (However, this is for main() only, not for other functions.)