[PTR_DEMANGLE]: Also demangle stack pointer. Add CFI.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / strtok.S
index 3d09dd7..88b343b 100644 (file)
@@ -1,26 +1,28 @@
 /* strtok (str, delim) -- Return next DELIM separated token from STR.
    For Intel 80x86, x>=3.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   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 Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   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
-   Library General Public License for more details.
+   Lesser 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.  */
+   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:
 
 
    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.  */
+       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 L(0)
+#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)
 
-L(0):
+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.
@@ -91,69 +129,133 @@ L(0):
        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
@@ -161,17 +263,17 @@ L(0):
 
 L(2):  movb (%eax), %cl        /* get byte from stopset */
        testb %cl, %cl          /* is NUL char? */
-       jz L(1)                 /* 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 L(1)                 /* 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 L(1)                 /* 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 */
@@ -180,7 +282,16 @@ L(2):      movb (%eax), %cl        /* get byte from stopset */
        testb $0xff, %cl        /* is NUL char? */
        jnz L(2)                /* no => process next dword from stopset */
 
-L(1):  leal -4(%edx), %eax     /* prepare loop */
+#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
@@ -241,6 +352,7 @@ L(9):       incl %edx
 
 L(8):  /* Remove the stopset table.  */
        addl $256, %esp
+       cfi_adjust_cfa_offset (-256)
 
        cmpl %eax, %edx
        je L(returnNULL)        /* There was no token anymore.  */
@@ -256,32 +368,24 @@ 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
 
 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
-END (FUNCTION)
+END (BP_SYM (FUNCTION))