@@ -148,27 +148,22 @@ static int intercept_munmap(void *start, size_t length)
148148
149149#if defined (SYS_mremap )
150150
151- static void * (* original_mremap ) (void * , size_t , size_t , int , ...);
151+ /* on linux this function has an optional extra argument but ... can not be used here because it
152+ * causes issues when intercepting a 4-argument mremap call */
153+ static void * (* original_mremap ) (void * , size_t , size_t , int , void * );
152154
153- static void * intercept_mremap (void * start , size_t oldlen , size_t newlen , int flags , ... )
155+ static void * intercept_mremap (void * start , size_t oldlen , size_t newlen , int flags , void * new_address )
154156{
155157 OPAL_PATCHER_BEGIN ;
156- void * result = 0 ;
157- #ifdef MREMAP_FIXED
158- va_list ap ;
159- #endif
160- void * new_address = NULL ;
158+ void * result = MAP_FAILED ;
161159
162- opal_mem_hooks_release_hook (start , oldlen , false);
163-
164- #ifdef MREMAP_FIXED
165- if (flags & MREMAP_FIXED ) {
166- va_start (ap , flags );
167- new_address = va_arg (ap , void * );
160+ if (MAP_FAILED != start && oldlen > 0 ) {
161+ opal_mem_hooks_release_hook (start , oldlen , true);
162+ }
168163
169- va_end (ap );
164+ if (!(flags & MREMAP_FIXED )) {
165+ new_address = NULL ;
170166 }
171- #endif
172167
173168 if (!original_mremap ) {
174169 result = (void * )(intptr_t ) memory_patcher_syscall (SYS_mremap , start , oldlen , newlen , flags , new_address );
@@ -261,6 +256,87 @@ static int intercept_brk (void *addr)
261256
262257#endif
263258
259+ #if defined(SYS_shmdt ) && defined(__linux__ )
260+
261+ #include <stdio.h>
262+ #include <fcntl.h>
263+ #include <sys/shm.h>
264+
265+ static size_t memory_patcher_get_shm_seg_size (const void * shmaddr )
266+ {
267+ unsigned long start_addr , end_addr ;
268+ char * ptr , * newline ;
269+ char buffer [1024 ];
270+ size_t seg_size = 0 ;
271+ int fd ;
272+
273+ seg_size = 0 ;
274+
275+ fd = open ("/proc/self/maps" , O_RDONLY );
276+ assert (fd >= 0 );
277+
278+ for (size_t read_offset = 0 ; ; ) {
279+ ssize_t nread = read (fd , buffer + read_offset , sizeof (buffer ) - 1 - read_offset );
280+ if (nread <= 0 ) {
281+ if (errno == EINTR ) {
282+ continue ;
283+ }
284+
285+ break ;
286+ } else {
287+ buffer [nread + read_offset ] = '\0' ;
288+ }
289+
290+ ptr = buffer ;
291+ while ( (newline = strchr (ptr , '\n' )) != NULL ) {
292+ /* 00400000-0040b000 r-xp ... \n */
293+ int ret = sscanf (ptr , "%lx-%lx " , & start_addr , & end_addr );
294+ if (ret != 2 ) {
295+ continue ;
296+ }
297+
298+ if (start_addr == (uintptr_t )shmaddr ) {
299+ seg_size = end_addr - start_addr ;
300+ goto out_close ;
301+ }
302+
303+ newline = strchr (ptr , '\n' );
304+ if (newline == NULL ) {
305+ break ;
306+ }
307+
308+ ptr = newline + 1 ;
309+ }
310+
311+ read_offset = strlen (ptr );
312+ memmove (buffer , ptr , read_offset );
313+ }
314+
315+ out_close :
316+ close (fd );
317+ return seg_size ;
318+ }
319+
320+ static int (* original_shmdt ) (const void * );
321+
322+ static int intercept_shmdt (const void * shmaddr )
323+ {
324+ OPAL_PATCHER_BEGIN ;
325+ int result ;
326+
327+ opal_mem_hooks_release_hook (shmaddr , memory_patcher_get_shm_seg_size (shmaddr ), false);
328+
329+ if (original_shmdt ) {
330+ result = original_shmdt (shmaddr );
331+ } else {
332+ result = memory_patcher_syscall (SYS_shmdt , shmaddr );
333+ }
334+
335+ OPAL_PATCHER_END ;
336+ return result ;
337+ }
338+ #endif
339+
264340static int patcher_register (void )
265341{
266342 mca_memory_patcher_priority = 80 ;
@@ -318,6 +394,13 @@ static int patcher_open (void)
318394 return rc ;
319395 }
320396
397+ #if defined(SYS_shmdt ) && defined(__linux__ )
398+ rc = opal_patcher -> patch_symbol ("shmdt" , (uintptr_t ) intercept_shmdt , (uintptr_t * ) & original_shmdt );
399+ if (OPAL_SUCCESS != rc ) {
400+ return rc ;
401+ }
402+ #endif
403+
321404#if defined (SYS_brk )
322405 rc = opal_patcher -> patch_symbol ("brk" , (uintptr_t )intercept_brk , (uintptr_t * ) & original_brk );
323406#endif
0 commit comments