The trouble with more than six arguments


If there were never routines written with more than six arguments, we could forget about stacks for a while and move onto another topic. Unfortunately, there are such routines within the UNIX kernel, so we really need to talk about this.

Let's refer to /usr/include/sys/frame.h again for a moment.

 /*   * Definition of the sparc stack frame (when it is pushed on the stack).   */  struct frame {         int     fr_local[8];         /* saved locals */          int     fr_arg[6];           /* saved arguments [0 - 5] */          struct frame    *fr_savfp;   /* saved frame pointer */          int     fr_savpc;            /* saved program counter */          char    *fr_stret;           /* struct return addr */          int     fr_argd[6];          /* arg dump area */          int     fr_argx[1];          /* array of args past the sixth */  }; 

Quickly, let's review what happens when we execute the save instruction upon entering a new routine. A new stack frame is created, the window is shifted, and possibly a window overflow trap occurs. The kernel will process the trap, copying the former output registers (aka the new input registers) onto the new stack frame. We are okay so far, right?

Now, if the calling routine needs to send more than six arguments to the callee, it cannot pass them through the window registers, as we have already used all of the overlapping registers. Looking at the frame structure, we see that the arguments past the sixth are to be loaded into the fr_argx array. We are still okay, right?

Here's the problem. Timing! We can't load up the callee's frame fr_argx array prior to calling the callee. The callee's frame doesn't exist yet! So, exactly where and when do we load up the additional parameters?

The answer is: in the caller's frame, in his own fr_argx array, before we invoke the callee.

We've seen that the compiler can be quite clever. When it comes to this scenario, the compiler creates assembly code that has the callee routine referencing not only his own frame, pointed to by %sp , but also the caller's frame via %fp.

Compile the following program on your own system. We recommend you compile first with optimization. After you get through the optimized version, try a straight compile for fun.

Here's the program, nine-args.c .

 /*   *  Demo file to show how the compiler produces   *  SPARC assembly code to handle more than 6   *  calling arguments.   *  */  main()  {   printf ("Main calling fred.\n");    fred (1, 2, 3, 4, 5, 6, 7, 8, 9);  }  int fred (i1, i2, i3, i4, i5, i6, i7, i8, i9)  int       i1, i2, i3, i4, i5, i6, i7, i8, i9;  {   printf ("args are %x, %x, %x, %x, %x, %x, %x, %x, %x\n",             i1, i2, i3, i4, i5, i6, i7, i8, i9);    george (0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777, 0x888, 0x999);  }  int george (k1, k2, k3, k4, k5, k6, k7, k8, k9)  int         k1, k2, k3, k4, k5, k6, k7, k8, k9;  {   int value;    printf ("args are %x, %x, %x, %x, %x, %x, %x, %x, %x\n",             k1, k2, k3, k4, k5, k6, k7, k8, k9);  } 

For demonstration purposes, we will compile this program with optimization and show you what the whole stack looks like just after we create george() 's frame. Since we are expecting to see additional information in the frames , we will be displaying more than 24 words per frame (the minimum frame size ).

After we walk through the stack, we also will show you the SPARC assembly program the compiler generated. This will allow you to try running the program on paper in case you don't have a computer handy. Yes, we highly recommend you try this method of program execution, especially on those nights when you are convinced you absolutely cannot fall sleep.

graphics/18fig05.gif

graphics/18fig06.gif

And here are the actual assembly instructions that were generated by the compile we used in this example. We'll see you in the next chapter where we will introduce you to the UNIX kernel. Until then, sweet dreams!

Figure 18-5 Viewing nineargs's assembly instructions via adb
  main,50?ai  main:           main:           save    %sp, -0x68, %sp  main+4:         sethi   %hi(0x20800), %l0  main+8:         call    _PROCEDURE_LINKAGE_TABLE_ + 0x54  main+0xc:       add     %l0, 0x1c0, %o0  main+0x10:      mov     0x7, %l0  main+0x14:      mov     0x8, %l1  main+0x18:      st      %l0, [%sp + 0x5c]  main+0x1c:      mov     0x1, %o0  main+0x20:      mov     0x2, %o1  main+0x24:      mov     0x3, %o2  main+0x28:      mov     0x4, %o3  main+0x2c:      mov     0x5, %o4  main+0x30:      mov     0x6, %o5  main+0x34:      st      %l1, [%sp + 0x60]  main+0x38:      mov     0x9, %l0  main+0x3c:      call    fred  main+0x40:      st      %l0, [%sp + 0x64]  main+0x44:      ret  main+0x48:      restore  main+0x4c:      unimp   0x0  main+0x50:      unimp   0x0  main+0x54:      unimp   0x0  main+0x58:      unimp   0x0  main+0x5c:      unimp   0x0  fred:           save    %sp, -0x78, %sp  fred+4:         ld      [%fp + 0x5c], %l0  fred+8:         mov     %i0, %o1  fred+0xc:       st      %l0, [%sp + 0x60]  fred+0x10:      mov     %i1, %o2  fred+0x14:      ld      [%fp + 0x60], %l1  fred+0x18:      mov     %i2, %o3  fred+0x1c:      st      %l1, [%sp + 0x64]  fred+0x20:      sethi   %hi(0x20800), %l1  fred+0x24:      ld      [%fp + 0x64], %l0  fred+0x28:      add     %l1, 0x1d4, %o0  fred+0x2c:      mov     %i3, %o4  fred+0x30:      mov     %i4, %o5  fred+0x34:      st      %i5, [%sp + 0x5c]  fred+0x38:      call    _PROCEDURE_LINKAGE_TABLE_ + 0x54  fred+0x3c:      st      %l0, [%sp + 0x68]  fred+0x40:      mov     0x777, %l0  fred+0x44:      mov     0x888, %l1  fred+0x48:      st      %l0, [%sp + 0x5c]  fred+0x4c:      mov     0x111, %o0  fred+0x50:      mov     0x222, %o1  fred+0x54:      mov     0x333, %o2  fred+0x58:      mov     0x444, %o3  fred+0x5c:      mov     0x555, %o4  fred+0x60:      mov     0x666, %o5  fred+0x64:      st      %l1, [%sp + 0x60]  fred+0x68:      mov     0x999, %l0  fred+0x6c:      call    george  fred+0x70:      st      %l0, [%sp + 0x64]  fred+0x74:      ret  fred+0x78:      restore  fred+0x7c:      unimp   0x0  fred+0x80:      unimp   0x0  fred+0x84:      unimp   0x0  fred+0x88:      unimp   0x0  fred+0x8c:      unimp   0x0  george:         save    %sp, -0x70, %sp  george+4:       ld      [%fp + 0x5c], %l0  george+8:       mov     %i0, %o1  george+0xc:     st      %l0, [%sp + 0x60]  george+0x10:    mov     %i1, %o2  george+0x14:    ld      [%fp + 0x60], %l1  george+0x18:    mov     %i2, %o3  george+0x1c:    st      %l1, [%sp + 0x64]  george+0x20:    sethi   %hi(0x20800), %l1  george+0x24:    ld      [%fp + 0x64], %l0  george+0x28:    add     %l1, 0x204, %o0  george+0x2c:    mov     %i3, %o4  george+0x30:    mov     %i4, %o5  george+0x34:    st      %i5, [%sp + 0x5c]  george+0x38:    call    _PROCEDURE_LINKAGE_TABLE_ + 0x54  george+0x3c:    st      %l0, [%sp + 0x68]  george+0x40:    ret  george+0x44:    restore  _ex_text1:      save    %sp, -0x60, %sp  _ex_text1+4:    call    _ex_text1 + 0x10 


PANIC. UNIX System Crash Dump Analysis Handbook
PANIC! UNIX System Crash Dump Analysis Handbook (Bk/CD-ROM)
ISBN: 0131493868
EAN: 2147483647
Year: 1994
Pages: 289
Authors: Chris Drake

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net