Improve NetBSD support: Allow VMA determination with fewer system calls.
[libsigsegv/ericb.git] / src / heur-bc.h
blobcf090fdc0b324b42b4aa1a18d8866372b5d8c28a
1 /* Detecting stack overflow. Version for platforms which supply the
2 stack pointer and have sigsegv_get_vma.
3 Copyright (C) 2003 Bruno Haible <bruno@clisp.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 #if HAVE_GETRLIMIT
20 # include <sys/types.h>
21 # include <sys/time.h>
22 # include <sys/resource.h> /* declares struct rlimit */
23 #endif
25 /* Address of the last byte belonging to the stack vma. */
26 static unsigned long stack_top = 0;
28 static int
29 remember_stack_top (void *some_variable_on_stack)
31 struct vma_struct vma;
33 if (stack_top)
34 return 0;
36 /* Needs to be retrieved once only. */
37 if (sigsegv_get_vma ((unsigned long) some_variable_on_stack, &vma) >= 0)
39 stack_top = vma.end - 1;
40 return 0;
42 else
43 return -1;
46 #define IS_STACK_OVERFLOW \
47 is_stk_overflow ((unsigned long) (SIGSEGV_FAULT_STACKPOINTER))
49 static int
50 is_stk_overflow (int sp)
52 struct vma_struct vma;
54 if (sigsegv_get_vma (stack_top, &vma) < 0)
55 return 0;
57 #if HAVE_GETRLIMIT && defined RLIMIT_STACK
59 /* Heuristic BC: If the stack size has reached its maximal size,
60 and sp is near the low end, we consider it a stack
61 overflow. */
62 struct rlimit rl;
64 if (getrlimit (RLIMIT_STACK, &rl) >= 0)
66 unsigned long current_stack_size = vma.end - vma.start;
67 unsigned long max_stack_size = rl.rlim_cur;
68 if (current_stack_size <= max_stack_size - 4096)
69 return 0;
72 #endif
74 /* Heuristic BC: If we know sp, and it is neither
75 near the low end, nor in the alternate stack, then
76 it's probably not a stack overflow. */
77 return (sp >= stk_extra_stack
78 && sp <= stk_extra_stack + stk_extra_stack_size)
79 #if STACK_DIRECTION < 0
80 || (sp <= vma.start + 4096 && vma.start <= sp + 4096)
81 #else
82 || (sp <= vma.end + 4096 && vma.end <= sp + 4096)
83 #endif