* * * * *

                            Multiple system calls

I finally found the answer to little conundrum [1]. But first, a bit of a
recap—the code for __getpid (the function that acually does the system call)
that I presented:

> 0804e380 <__getpid>:
>  804e380:       b8 14 00 00 00          mov    $0x14,%eax
>  804e385:       cd 80                   int    $0x80
>  804e387:       c3                      ret
>

That was generated from the output from objdump, and in order to get that, I
had to compile the program using gcc -g -static -o t1 t1.o t1a.o, but note
the -static bit there. Normally, such routines are part of a shared library
that aren't included in the final executable, but by adding -static when
compiling, the routines in the standard libraries are included in the final
result. And had I run the statically compiled version, I would have seen that
the code that calls the system supplied __getpid() would have taken 11
minutes to run.

What bit of code was I actually testing?

> (gdb) disassemble __getpid
> Dump of assembler code for function getpid:
> 0x00820730 <getpid+0>:  mov    %gs:0x4c,%edx
> 0x00820737 <getpid+7>:  test   %edx,%edx
> 0x00820739 <getpid+9>:  mov    %edx,%eax
> 0x0082073b <getpid+11>: jle    0x82073e <getpid+14>
> 0x0082073d <getpid+13>: ret
> 0x0082073e <getpid+14>: jne    0x820752 <getpid+34>
> 0x00820740 <getpid+16>: mov    %gs:0x48,%eax
> 0x00820746 <getpid+22>: test   %eax,%eax
> 0x00820748 <getpid+24>: nop
> 0x00820749 <getpid+25>: lea    0x0(%esi),%esi
> 0x00820750 <getpid+32>: jne    0x82073d <getpid+13>
> 0x00820752 <getpid+34>: mov    $0x14,%eax
> 0x00820757 <getpid+39>: call   *%gs:0x10
> 0x0082075e <getpid+46>: test   %edx,%edx
> 0x00820760 <getpid+48>: jne    0x82073d <getpid+13>
> 0x00820762 <getpid+50>: mov    %eax,%gs:0x48
> 0x00820768 <getpid+56>: ret
> 0x00820769 <getpid+57>: nop
> 0x0082076a <getpid+58>: nop
> 0x0082076b <getpid+59>: nop
> 0x0082076c <getpid+60>: nop
> 0x0082076d <getpid+61>: nop
> 0x0082076e <getpid+62>: nop
> 0x0082076f <getpid+63>: nop
> End of assembler dump.
>

Ah! That makes more sense then!

It's basically checking to see if the getpid() system call has been made, and
if not, call it once, then cache the value for later calls to this routine.
You also won't notice an int $80 here, but that's because the shared library
version of __getpid() uses a different method of making a system call [2]
than the traditional int $80, although the older method is still supported,
which is why I suspect the static version of the system libraries use int $80
to make system calls—to support older systems that might not support the
newer system call mechanism.

[1] gopher://gopher.conman.org/0Phlog:2007/11/30.1
[2] http://manugarg.googlepages.com/systemcallinlinux2_6.html

Email author at [email protected]