@@ -58,96 +58,103 @@ static void *find_prefered_mmap_base(size_t requested_size)
58
58
#if defined(__linux__ )
59
59
FILE * f ;
60
60
char buffer [MAXPATHLEN ];
61
-
61
+
62
62
f = fopen ("/proc/self/maps" , "r" );
63
63
if (!f ) {
64
64
return MAP_FAILED ;
65
65
}
66
66
67
- while (fgets (buffer , MAXPATHLEN , f ) && sscanf (buffer , "%lx-%lx" , & start , & end ) == 2 ) {
68
- if ((uintptr_t )execute_ex >= start ) {
69
- /* the current segment lays before PHP .text segment or PHP .text segment itself */
70
- if (last_free_addr + requested_size <= start ) {
71
- last_candidate = last_free_addr ;
72
- }
73
- if ((uintptr_t )execute_ex < end ) {
74
- /* the current segment is PHP .text segment itself */
75
- if (last_candidate != (uintptr_t )MAP_FAILED ) {
76
- if (end - last_candidate < UINT32_MAX ) {
77
- /* we have found a big enough hole before the text segment */
78
- break ;
79
- }
80
- last_candidate = (uintptr_t )MAP_FAILED ;
67
+ while (fgets (buffer , MAXPATHLEN , f ) && sscanf (buffer , "%lx-%lx" , & start , & end ) == 2 ) {
68
+ if ((uintptr_t )execute_ex >= start ) {
69
+ /* the current segment lays before PHP .text segment or PHP .text segment itself */
70
+ /*Search for candidates at the end of the free segment near the .text segment
71
+ to prevent candidates from being missed due to large hole*/
72
+ if (last_free_addr + requested_size <= start ) {
73
+ last_candidate = ZEND_MM_ALIGNED_SIZE_EX (start - requested_size , huge_page_size );
74
+ if (last_candidate + requested_size > start ) {
75
+ last_candidate -= huge_page_size ;
81
76
}
82
- text_start = start ;
83
- }
84
- } else {
85
- /* the current segment lays after PHP .text segment */
86
- if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
87
- /* the current segment and the following segments lay too far from PHP .text segment */
88
- break ;
89
- }
90
- if (last_free_addr + requested_size <= start ) {
91
- last_candidate = last_free_addr ;
92
- break ;
93
- }
94
- }
95
- last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (end , huge_page_size );
96
-
77
+ }
78
+ if ((uintptr_t )execute_ex < end ) {
79
+ /* the current segment is PHP .text segment itself */
80
+ if (last_candidate != (uintptr_t )MAP_FAILED ) {
81
+ if (end - last_candidate < UINT32_MAX ) {
82
+ /* we have found a big enough hole before the .text segment */
83
+ break ;
84
+ }
85
+ last_candidate = (uintptr_t )MAP_FAILED ;
86
+ }
87
+ text_start = start ;
88
+ }
89
+ } else {
90
+ /* the current segment lays after PHP .text segment */
91
+ if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
92
+ /* the current segment and the following segments lay too far from PHP .text segment */
93
+ break ;
94
+ }
95
+ if (last_free_addr + requested_size <= start ) {
96
+ last_candidate = last_free_addr ;
97
+ break ;
98
+ }
99
+ }
100
+ last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (end , huge_page_size );
97
101
}
98
102
fclose (f );
99
103
#elif defined(__FreeBSD__ )
100
- size_t s = 0 ;
101
- int mib [4 ] = {CTL_KERN , KERN_PROC , KERN_PROC_VMMAP , getpid ()};
102
- if (sysctl (mib , 4 , NULL , & s , NULL , 0 ) == 0 ) {
103
- s = s * 4 / 3 ;
104
- void * addr = mmap (NULL , s , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANON , -1 , 0 );
105
- if (addr != MAP_FAILED ) {
106
- if (sysctl (mib , 4 , addr , & s , NULL , 0 ) == 0 ) {
107
- start = (uintptr_t )addr ;
108
- end = start + s ;
109
- while (start < end ) {
110
- struct kinfo_vmentry * entry = (struct kinfo_vmentry * )start ;
111
- size_t sz = entry -> kve_structsize ;
112
- if (sz == 0 ) {
113
- break ;
114
- }
115
- uintptr_t e_start = entry -> kve_start ;
116
- uintptr_t e_end = entry -> kve_end ;
117
- if ((uintptr_t )execute_ex >= e_start ) {
118
- /* the current segment lays before PHP .text segment or PHP .text segment itself */
119
- if (last_free_addr + requested_size <= e_start ) {
120
- last_candidate = last_free_addr ;
121
- }
122
- if ((uintptr_t )execute_ex < e_end ) {
123
- /* the current segment is PHP .text segment itself */
124
- if (last_candidate != (uintptr_t )MAP_FAILED ) {
125
- if (e_end - last_candidate < UINT32_MAX ) {
126
- /* we have found a big enough hole before the text segment */
127
- break ;
128
- }
129
- last_candidate = (uintptr_t )MAP_FAILED ;
104
+ size_t s = 0 ;
105
+ int mib [4 ] = {CTL_KERN , KERN_PROC , KERN_PROC_VMMAP , getpid ()};
106
+ if (sysctl (mib , 4 , NULL , & s , NULL , 0 ) == 0 ) {
107
+ s = s * 4 / 3 ;
108
+ void * addr = mmap (NULL , s , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANON , -1 , 0 );
109
+ if (addr != MAP_FAILED ) {
110
+ if (sysctl (mib , 4 , addr , & s , NULL , 0 ) == 0 ) {
111
+ start = (uintptr_t )addr ;
112
+ end = start + s ;
113
+ while (start < end ) {
114
+ struct kinfo_vmentry * entry = (struct kinfo_vmentry * )start ;
115
+ size_t sz = entry -> kve_structsize ;
116
+ if (sz == 0 ) {
117
+ break ;
118
+ }
119
+ uintptr_t e_start = entry -> kve_start ;
120
+ uintptr_t e_end = entry -> kve_end ;
121
+ if ((uintptr_t )execute_ex >= e_start ) {
122
+ /* the current segment lays before PHP .text segment or PHP .text segment itself */
123
+ if (last_free_addr + requested_size <= e_start ) {
124
+ last_candidate = ZEND_MM_ALIGNED_SIZE_EX (e_start - requested_size , huge_page_size );
125
+ if (last_candidate + requested_size > e_start ) {
126
+ last_candidate -= huge_page_size ;
130
127
}
131
- text_start = e_start ;
132
- }
133
- } else {
134
- /* the current segment lays after PHP .text segment */
135
- if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
136
- /* the current segment and the following segments lay too far from PHP .text segment */
137
- break ;
138
- }
139
- if (last_free_addr + requested_size <= e_start ) {
140
- last_candidate = last_free_addr ;
141
- break ;
142
- }
143
- }
144
- last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (e_end , huge_page_size );
145
- start += sz ;
146
- }
147
- }
148
- munmap (addr , s );
149
- }
150
- }
128
+ }
129
+ if ((uintptr_t )execute_ex < e_end ) {
130
+ /* the current segment is PHP .text segment itself */
131
+ if (last_candidate != (uintptr_t )MAP_FAILED ) {
132
+ if (e_end - last_candidate < UINT32_MAX ) {
133
+ /* we have found a big enough hole before the text segment */
134
+ break ;
135
+ }
136
+ last_candidate = (uintptr_t )MAP_FAILED ;
137
+ }
138
+ text_start = e_start ;
139
+ }
140
+ } else {
141
+ /* the current segment lays after PHP .text segment */
142
+ if (last_free_addr + requested_size - text_start > UINT32_MAX ) {
143
+ /* the current segment and the following segments lay too far from PHP .text segment */
144
+ break ;
145
+ }
146
+ if (last_free_addr + requested_size <= e_start ) {
147
+ last_candidate = last_free_addr ;
148
+ break ;
149
+ }
150
+ }
151
+ last_free_addr = ZEND_MM_ALIGNED_SIZE_EX (e_end , huge_page_size );
152
+ start += sz ;
153
+ }
154
+ }
155
+ munmap (addr , s );
156
+ }
157
+ }
151
158
#endif
152
159
153
160
return (void * )last_candidate ;
0 commit comments