I did not run the binary at all for this analysis, not even inside a virtual machine or debugger. I used
  objdump -drs the-binary > dump
to get a disassembly and then wrote an annotation perl script (annotate.pl) to insert comments in it using a symbol table I kept in syscalls.txt. syscalls.txt started as the output of findsyscall.pl, which basically looks for "int 0x80", which is the syscall assembler instruction on x86-linux, which file(1) told me was the architecture of the file. findsyscall.pl also looks for loads of eax and edx before the int 0x80. eax holds the syscall number, but the socket calls (listen, accept, ...) all have the same syscall and edx determines which socket call it actually is.

annotate.pl was extended a few times. It now converts the multi-byte NOPs from GNU binutils to "nop; nop; nop;" style commands to make the assembler code easier to read. It also changes "call $0x80569fc" to "call wait4" using the entries in syscalls.txt. And it puts comments on lines with accesses to global and local variables, which makes understanding code much easier.

If there are two entries for one address, the last one wins. That way, one can change the name of a function or, more importantly, variable by adding a new symbol table entry to syscalls.txt. That makes it convenient to edit syscalls.txt like a journal, i.e. just keep appending the findings.

I wrote a small Makefile to generate annotated.txt from dump using annotate.pl and I browsed that file with vim. In the beginning, I kept a disassembly of the libc5 libc.a with symbols around to help identify libc functions.

For a step-by-step account on the analysis, please read syscalls.txt.