Bump version number.
[libsigsegv/ericb.git] / src / stackvma-mach.c
blobccd78a69cc31ef78b19fc5dcb81c4bf1b4368fe3
1 /* Determine the virtual memory area of a given address. Mach version.
2 Copyright (C) 2003, 2006 Paolo Bonzini <bonzini@gnu.org>
3 Copyright (C) 2010 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 #include "stackvma.h"
20 #include <stdio.h>
21 #ifdef HAVE_UNISTD_H
22 # include <unistd.h>
23 #endif
24 #include <libc.h>
25 #include <nlist.h>
26 #include <mach/mach.h>
27 #ifndef NeXT
28 #include <mach/machine/vm_param.h>
29 #endif
31 #include "stackvma-simple.c"
33 int
34 sigsegv_get_vma (unsigned long req_address, struct vma_struct *vma)
36 unsigned long prev_address = 0, prev_size = 0;
37 unsigned long join_address = 0, join_size = 0;
38 int more = 1;
39 vm_address_t address;
40 vm_size_t size;
41 #ifdef VM_REGION_BASIC_INFO
42 /* MacOS X API */
43 task_t task = mach_task_self ();
44 #else
45 task_t task = task_self ();
46 vm_prot_t protection, max_protection;
47 vm_inherit_t inheritance;
48 boolean_t shared;
49 vm_offset_t offset;
50 #endif
52 for (address = VM_MIN_ADDRESS; more; address += size)
54 mach_port_t object_name;
55 #ifdef VM_REGION_BASIC_INFO
56 /* MacOS X API */
57 /* In MacOS X 10.5, the types vm_address_t, vm_offset_t, vm_size_t have
58 32 bits in 32-bit processes and 64 bits in 64-bit processes. Whereas
59 mach_vm_address_t and mach_vm_size_t are always 64 bits large.
60 MacOS X 10.5 has three vm_region like methods:
61 - vm_region. It has arguments that depend on whether the current
62 process is 32-bit or 64-bit. When linking dynamically, this
63 function exists only in 32-bit processes. Therefore we use it only
64 in 32-bit processes.
65 - vm_region_64. It has arguments that depend on whether the current
66 process is 32-bit or 64-bit. It interprets a flavor
67 VM_REGION_BASIC_INFO as VM_REGION_BASIC_INFO_64, which is
68 dangerous since 'struct vm_region_basic_info_64' is larger than
69 'struct vm_region_basic_info'; therefore let's write
70 VM_REGION_BASIC_INFO_64 explicitly.
71 - mach_vm_region. It has arguments that are 64-bit always. This
72 function is useful when you want to access the VM of a process
73 other than the current process.
74 In 64-bit processes, we could use vm_region_64 or mach_vm_region.
75 I choose vm_region_64 because it uses the same types as vm_region,
76 resulting in less conditional code. */
77 # if defined __ppc64__ || defined __x86_64__
78 struct vm_region_basic_info_64 info;
79 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
81 more = (vm_region_64 (task, &address, &size, VM_REGION_BASIC_INFO_64,
82 (vm_region_info_t)&info, &info_count, &object_name)
83 == KERN_SUCCESS);
84 # else
85 struct vm_region_basic_info info;
86 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
88 more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
89 (vm_region_info_t)&info, &info_count, &object_name)
90 == KERN_SUCCESS);
91 # endif
92 #else
93 more = (vm_region (task, &address, &size, &protection, &max_protection,
94 &inheritance, &shared, &object_name, &offset)
95 == KERN_SUCCESS);
96 #endif
97 if (!more)
99 address = join_address + join_size;
100 size = 0;
103 if ((unsigned long) address == join_address + join_size)
104 join_size += size;
105 else
107 prev_address = join_address;
108 prev_size = join_size;
109 join_address = (unsigned long) address;
110 join_size = size;
113 #ifdef VM_REGION_BASIC_INFO
114 if (object_name != MACH_PORT_NULL)
115 mach_port_deallocate (mach_task_self (), object_name);
116 #endif
118 #if STACK_DIRECTION < 0
119 if (join_address <= req_address && join_address + join_size > req_address)
121 vma->start = join_address;
122 vma->end = join_address + join_size;
123 vma->prev_end = prev_address + prev_size;
124 vma->is_near_this = simple_is_near_this;
125 return 0;
127 #else
128 if (prev_address <= req_address && prev_address + prev_size > req_address)
130 vma->start = prev_address;
131 vma->end = prev_address + prev_size;
132 vma->next_start = join_address;
133 vma->is_near_this = simple_is_near_this;
134 return 0;
136 #endif
139 #if STACK_DIRECTION > 0
140 if (join_address <= req_address && join_address + size > req_address)
142 vma->start = prev_address;
143 vma->end = prev_address + prev_size;
144 vma->next_start = ~0UL;
145 vma->is_near_this = simple_is_near_this;
146 return 0;
148 #endif
150 return -1;