[PTR_DEMANGLE]: Also demangle stack pointer. Add CFI.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / strtok.S
index a510e18..88b343b 100644 (file)
@@ -1,25 +1,28 @@
 /* strtok (str, delim) -- Return next DELIM separated token from STR.
-For Intel 80x86, x>=3.
-Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+   For Intel 80x86, x>=3.
+   Copyright (C) 1996-1998, 2000, 2001, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
 
 #include <sysdep.h>
+#include "asm-syntax.h"
+#include "bp-sym.h"
+#include "bp-asm.h"
 
 /* This file can be used for three variants of the strtok function:
 
@@ -36,51 +39,88 @@ Boston, MA 02111-1307, USA.  */
 
    We do a common implementation here.  */
 
-#ifndef USE_AS_STRTOK_R
+#ifdef USE_AS_STRTOK_R
+# define SAVE_PTR 0(%ecx)
+#else
        .bss
        .local save_ptr
        ASM_TYPE_DIRECTIVE (save_ptr, @object)
        .size save_ptr, 4
 save_ptr:
+# if __BOUNDED_POINTERS__
+       .space 12
+# else
        .space 4
+# endif
+
+# ifdef PIC
+#  define SAVE_PTR save_ptr@GOTOFF(%ebx)
+# else
+#  define SAVE_PTR save_ptr
+# endif
 
-#define FUNCTION strtok
+# define FUNCTION strtok
 #endif
 
-       .text
+#define PARMS  LINKAGE         /* no space for saved regs */
+#define RTN    PARMS
+#define STR    RTN+RTN_SIZE
+#define DELIM  STR+PTR_SIZE
+#define SAVE   DELIM+PTR_SIZE
 
-ENTRY (FUNCTION)
+       .text
+ENTRY (BP_SYM (FUNCTION))
+       ENTER
 
-       movl 4(%esp), %edx              /* Get start of string.  */
-       movl 8(%esp), %eax              /* Get start of delimiter set.  */
+       movl STR(%esp), %edx
+       movl DELIM(%esp), %eax
+       CHECK_BOUNDS_LOW (%eax, DELIM(%esp))
 
-#if !defined (USE_AS_STRTOK_R) && defined (PIC)
+#if !defined USE_AS_STRTOK_R && defined PIC
        pushl %ebx                      /* Save PIC register.  */
-       call Lhere
-Lhere: popl %ebx
-       addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ebx
+       cfi_adjust_cfa_offset (4)
+       call L(here)
+       cfi_adjust_cfa_offset (4)
+       cfi_rel_offset (ebx, 0)
+L(here):
+       popl %ebx
+       cfi_adjust_cfa_offset (-4)
+       addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
 #endif
 
        /* If the pointer is NULL we have to use the stored value of
           the last run.  */
        cmpl $0, %edx
-       jne L0
+#if __BOUNDED_POINTERS__
+       movl SAVE(%esp), %ecx
+       je L(0)
+       /* Save bounds of incoming non-NULL STR into save area.  */
+       movl 4+STR(%esp), %eax
+       movl %eax, 4+SAVE_PTR
+       movl 8+STR(%esp), %eax
+       movl %eax, 8+SAVE_PTR
+       CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
+       jmp L(1)
+L(0):  movl SAVE_PTR, %edx
+       CHECK_BOUNDS_LOW (%edx, SAVE_PTR)
+       jmp L(1)
+#else
+       jne L(1)
+#endif
 
 #ifdef USE_AS_STRTOK_R
        /* The value is stored in the third argument.  */
-       movl 12(%esp), %edx
+       movl SAVE(%esp), %edx
        movl (%edx), %edx
 #else
        /* The value is in the local variable defined above.  But
           we have to take care for PIC code.  */
-# ifndef PIC
-       movl save_ptr, %edx
-# else
-       movl save_ptr@GOTOFF(%ebx), %edx
-# endif
+       movl SAVE_PTR, %edx
 #endif
+       testl %edx, %edx
+       jz L(returnNULL)
 
-L0:
+L(1):
        /* First we create a table with flags for all possible characters.
           For the ASCII (7bit/8bit) or ISO-8859-X character sets which are
           supported by the C string functions we have 256 characters.
@@ -89,96 +129,169 @@ L0:
        xorl %ecx, %ecx         /* %ecx = 0 !!! */
 
        pushl %ecx              /* make a 256 bytes long block filled with 0 */
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl %ecx
+       cfi_adjust_cfa_offset (4)
        pushl $0                /* These immediate values make the label 2 */
+       cfi_adjust_cfa_offset (4)
        pushl $0                /* to be aligned on a 16 byte boundary to */
+       cfi_adjust_cfa_offset (4)
        pushl $0                /* get a better performance of the loop.  */
+       cfi_adjust_cfa_offset (4)
        pushl $0
+       cfi_adjust_cfa_offset (4)
        pushl $0
+       cfi_adjust_cfa_offset (4)
        pushl $0
+       cfi_adjust_cfa_offset (4)
 
 /* For understanding the following code remember that %ecx == 0 now.
    Although all the following instruction only modify %cl we always
    have a correct zero-extended 32-bit value in %ecx.  */
 
-L2:    movb (%eax), %cl        /* get byte from stopset */
+L(2):  movb (%eax), %cl        /* get byte from stopset */
        testb %cl, %cl          /* is NUL char? */
-       jz L1                   /* yes => start compare loop */
+       jz L(1_1)               /* yes => start compare loop */
        movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
 
        movb 1(%eax), %cl       /* get byte from stopset */
        testb $0xff, %cl        /* is NUL char? */
-       jz L1                   /* yes => start compare loop */
+       jz L(1_2)               /* yes => start compare loop */
        movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
 
        movb 2(%eax), %cl       /* get byte from stopset */
        testb $0xff, %cl        /* is NUL char? */
-       jz L1                   /* yes => start compare loop */
+       jz L(1_3)               /* yes => start compare loop */
        movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
 
        movb 3(%eax), %cl       /* get byte from stopset */
        addl $4, %eax           /* increment stopset pointer */
        movb %cl, (%esp,%ecx)   /* set corresponding byte in stopset table */
        testb $0xff, %cl        /* is NUL char? */
-       jnz L2                  /* no => process next dword from stopset */
-
-L1:    leal -4(%edx), %eax     /* prepare loop */
+       jnz L(2)                /* no => process next dword from stopset */
+
+#if __BOUNDED_POINTERS__
+       jmp L(1_0)              /* pointer is correct for bounds check */
+L(1_3):        incl %eax               /* adjust pointer for bounds check */
+L(1_2):        incl %eax               /* ditto */
+L(1_1):        incl %eax               /* ditto */
+L(1_0):        CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe)
+#else
+L(1_3):; L(1_2):; L(1_1):      /* fall through */
+#endif
+       leal -4(%edx), %eax     /* prepare loop */
 
        /* We use a neat trick for the following loop.  Normally we would
           have to test for two termination conditions
@@ -189,97 +302,90 @@ L1:       leal -4(%edx), %eax     /* prepare loop */
           value in the table.  The value of NUL is NUL so the loop
           terminates for NUL in every case.  */
 
-L3:    addl $4, %eax           /* adjust pointer for full loop round */
+L(3):  addl $4, %eax           /* adjust pointer for full loop round */
 
        movb (%eax), %cl        /* get byte from string */
        testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
-       jz L4                   /* no => start of token */
+       jz L(4)                 /* no => start of token */
 
        movb 1(%eax), %cl       /* get byte from string */
        testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
-       jz L5                   /* no => start of token */
+       jz L(5)                 /* no => start of token */
 
        movb 2(%eax), %cl       /* get byte from string */
        testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
-       jz L6                   /* no => start of token */
+       jz L(6)                 /* no => start of token */
 
        movb 3(%eax), %cl       /* get byte from string */
        testb %cl, (%esp,%ecx)  /* is it contained in stopset? */
-       jnz L3                  /* yes => start of loop */
+       jnz L(3)                /* yes => start of loop */
 
        incl %eax               /* adjust pointer */
-L6:    incl %eax
-L5:    incl %eax
+L(6):  incl %eax
+L(5):  incl %eax
 
        /* Now we have to terminate the string.  */
 
-L4:    leal -4(%eax), %edx     /* We use %EDX for the next run.  */
+L(4):  leal -4(%eax), %edx     /* We use %EDX for the next run.  */
 
-L7:    addl $4, %edx           /* adjust pointer for full loop round */
+L(7):  addl $4, %edx           /* adjust pointer for full loop round */
 
        movb (%edx), %cl        /* get byte from string */
        cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
-       je L8                   /* yes => return */
+       je L(8)                 /* yes => return */
 
        movb 1(%edx), %cl       /* get byte from string */
        cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
-       je L9                   /* yes => return */
+       je L(9)                 /* yes => return */
 
        movb 2(%edx), %cl       /* get byte from string */
        cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
-       je L10                  /* yes => return */
+       je L(10)                /* yes => return */
 
        movb 3(%edx), %cl       /* get byte from string */
        cmpb %cl, (%esp,%ecx)   /* is it contained in skipset? */
-       jne L7                  /* no => start loop again */
+       jne L(7)                /* no => start loop again */
 
        incl %edx               /* adjust pointer */
-L10:   incl %edx
-L9:    incl %edx
+L(10): incl %edx
+L(9):  incl %edx
 
-L8:    /* Remove the stopset table.  */
+L(8):  /* Remove the stopset table.  */
        addl $256, %esp
+       cfi_adjust_cfa_offset (-256)
 
        cmpl %eax, %edx
-       je LreturnNULL          /* There was no token anymore.  */
+       je L(returnNULL)        /* There was no token anymore.  */
 
        movb $0, (%edx)         /* Terminate string.  */
 
        /* Are we at end of string?  */
        cmpb $0, %cl
-       je L11
+       je L(11)
 
        incl %edx
-L11:
+L(11):
 
        /* Store the pointer to the next character.  */
 #ifdef USE_AS_STRTOK_R
-       movl 12(%esp), %ecx
-       movl %edx, (%ecx)
-#else
-# ifndef PIC
-       movl %edx, save_ptr
-# else
-       movl %edx, save_ptr@GOTOFF(%ebx)
+       movl SAVE(%esp), %ecx
+#endif
+       movl %edx, SAVE_PTR
+       CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb)
+       RETURN_BOUNDED_POINTER (SAVE_PTR)
+
+L(epilogue):
+#if !defined USE_AS_STRTOK_R && defined PIC
        popl %ebx
-# endif
+       cfi_adjust_cfa_offset (-4)
+       cfi_restore (ebx)
 #endif
-       ret
+       LEAVE
+       RET_PTR
 
-LreturnNULL:
+L(returnNULL):
        xorl %eax, %eax
+       RETURN_NULL_BOUNDED_POINTER
+       jmp L(epilogue)
 
-       /* Store current pointer for next round.  */
-#ifdef USE_AS_STRTOK_R
-       movl 12(%esp), %ecx
-       movl %edx, (%ecx)
-#else
-# ifndef PIC
-       movl %edx, save_ptr
-# else
-       movl %edx, save_ptr@GOTOFF(%ebx)
-       popl %ebx
-# endif
-#endif
-       ret
-PSEUDO_END (FUNCTION)
+END (BP_SYM (FUNCTION))