[PTR_DEMANGLE]: Also demangle stack pointer. Add CFI.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / strtok.S
index 6fa6cc2..88b343b 100644 (file)
@@ -1,26 +1,27 @@
 /* strtok (str, delim) -- Return next DELIM separated token from STR.
    For Intel 80x86, x>=3.
-   Copyright (C) 1996, 1997, 1998, 2000 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
 
-#define FUNCTION strtok
+# ifdef PIC
+#  define SAVE_PTR save_ptr@GOTOFF(%ebx)
+# else
+#  define SAVE_PTR save_ptr
+# endif
+
+# define FUNCTION strtok
 #endif
 
 #define PARMS  LINKAGE         /* no space for saved regs */
@@ -56,25 +69,44 @@ save_ptr:
 #define SAVE   DELIM+PTR_SIZE
 
        .text
-
-ENTRY (FUNCTION)
+ENTRY (BP_SYM (FUNCTION))
        ENTER
 
        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.  */
@@ -83,14 +115,12 @@ L(here):
 #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.
@@ -99,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
@@ -169,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 */
@@ -188,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
@@ -249,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.  */
@@ -262,23 +366,26 @@ L(8):     /* Remove the stopset table.  */
        incl %edx
 L(11):
 
-L(return):
        /* Store the pointer to the next character.  */
 #ifdef USE_AS_STRTOK_R
        movl SAVE(%esp), %ecx
-       movl %edx, (%ecx)
-#else
-# ifndef PIC
-       movl %edx, save_ptr
-# else
-       movl %edx, save_ptr@GOTOFF(%ebx)
+#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
        LEAVE
        RET_PTR
 
 L(returnNULL):
        xorl %eax, %eax
-       jmp L(return)
-END (FUNCTION)
+       RETURN_NULL_BOUNDED_POINTER
+       jmp L(epilogue)
+
+END (BP_SYM (FUNCTION))