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)
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. */
26 #include <mach/mach.h>
28 #include <mach/machine/vm_param.h>
31 #include "stackvma-simple.c"
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;
41 #ifdef VM_REGION_BASIC_INFO
43 task_t task
= mach_task_self ();
45 task_t task
= task_self ();
46 vm_prot_t protection
, max_protection
;
47 vm_inherit_t inheritance
;
52 for (address
= VM_MIN_ADDRESS
; more
; address
+= size
)
54 mach_port_t object_name
;
55 #ifdef VM_REGION_BASIC_INFO
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
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
)
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
)
93 more
= (vm_region (task
, &address
, &size
, &protection
, &max_protection
,
94 &inheritance
, &shared
, &object_name
, &offset
)
99 address
= join_address
+ join_size
;
103 if ((unsigned long) address
== join_address
+ join_size
)
107 prev_address
= join_address
;
108 prev_size
= join_size
;
109 join_address
= (unsigned long) address
;
113 #ifdef VM_REGION_BASIC_INFO
114 if (object_name
!= MACH_PORT_NULL
)
115 mach_port_deallocate (mach_task_self (), object_name
);
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
;
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
;
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
;