This source file includes following definitions.
- rof_open
 
- rof_peekchar
 
- rof_getchar
 
- rof_scanf_lx
 
- rof_close
 
- vma_iterate_proc
 
- vma_iterate_proc
 
- vma_iterate_proc
 
- vma_iterate_proc
 
- vma_iterate_bsd
 
- vma_iterate_bsd
 
- vma_iterate_bsd
 
- vma_iterate_bsd
 
- vma_iterate
 
- vma_iterate_callback
 
- main
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 #include <config.h>
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 #if defined __sun || defined __ANDROID__
  32 # undef _FILE_OFFSET_BITS
  33 #endif
  34 
  35 
  36 #include "vma-iter.h"
  37 
  38 #include <errno.h> 
  39 #include <stdlib.h> 
  40 #include <fcntl.h> 
  41 #include <unistd.h> 
  42 
  43 #if defined __linux__ || defined __ANDROID__
  44 # include <limits.h> 
  45 #endif
  46 
  47 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix 
  48 # include <sys/types.h>
  49 # include <sys/mman.h> 
  50 #endif
  51 #if defined __minix
  52 # include <string.h> 
  53 #endif
  54 
  55 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ 
  56 # include <sys/types.h>
  57 # include <sys/mman.h> 
  58 # include <sys/user.h> 
  59 # include <sys/sysctl.h> 
  60 #endif
  61 #if defined __NetBSD__ || defined __OpenBSD__ 
  62 # include <sys/types.h>
  63 # include <sys/mman.h> 
  64 # include <sys/sysctl.h> 
  65 #endif
  66 
  67 #if defined __sgi || defined __osf__ 
  68 # include <string.h> 
  69 # include <sys/types.h>
  70 # include <sys/mman.h> 
  71 # include <sys/procfs.h> 
  72 #endif
  73 
  74 #if defined __sun 
  75 # include <string.h> 
  76 # include <sys/types.h>
  77 # include <sys/mman.h> 
  78 
  79 # define _STRUCTURED_PROC 1
  80 # include <sys/procfs.h> 
  81 #endif
  82 
  83 #if HAVE_PSTAT_GETPROCVM 
  84 # include <sys/pstat.h> 
  85 #endif
  86 
  87 #if defined __APPLE__ && defined __MACH__ 
  88 # include <mach/mach.h>
  89 #endif
  90 
  91 #if defined __GNU__ 
  92 # include <mach/mach.h>
  93 #endif
  94 
  95 #if defined _WIN32 || defined __CYGWIN__ 
  96 # include <windows.h>
  97 #endif
  98 
  99 #if defined __BEOS__ || defined __HAIKU__ 
 100 # include <OS.h>
 101 #endif
 102 
 103 #if HAVE_MQUERY 
 104 # include <sys/types.h>
 105 # include <sys/mman.h> 
 106 #endif
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 # if defined __linux__ || defined __ANDROID__
 133   
 134 
 135 
 136 
 137 
 138 #  define MIN_LEFTOVER (73 + PATH_MAX)
 139 # else
 140 #  define MIN_LEFTOVER 1
 141 # endif
 142 
 143 # ifdef TEST
 144 
 145 #  define STACK_ALLOCATED_BUFFER_SIZE 32
 146 # else
 147 #  if MIN_LEFTOVER < 1024
 148 #   define STACK_ALLOCATED_BUFFER_SIZE 1024
 149 #  else
 150     
 151 #   define STACK_ALLOCATED_BUFFER_SIZE 1
 152 #  endif
 153 # endif
 154 
 155 struct rofile
 156   {
 157     size_t position;
 158     size_t filled;
 159     int eof_seen;
 160     
 161     char *buffer;
 162     char *auxmap;
 163     size_t auxmap_length;
 164     unsigned long auxmap_start;
 165     unsigned long auxmap_end;
 166     char stack_allocated_buffer[STACK_ALLOCATED_BUFFER_SIZE];
 167   };
 168 
 169 
 170 static int
 171 rof_open (struct rofile *rof, const char *filename)
     
 172 {
 173   int fd;
 174   unsigned long pagesize;
 175   size_t size;
 176 
 177   fd = open (filename, O_RDONLY | O_CLOEXEC);
 178   if (fd < 0)
 179     return -1;
 180   rof->position = 0;
 181   rof->eof_seen = 0;
 182   
 183   pagesize = 0;
 184   rof->buffer = rof->stack_allocated_buffer;
 185   size = sizeof (rof->stack_allocated_buffer);
 186   rof->auxmap = NULL;
 187   rof->auxmap_start = 0;
 188   rof->auxmap_end = 0;
 189   for (;;)
 190     {
 191       
 192       if (size > MIN_LEFTOVER)
 193         {
 194           int n = read (fd, rof->buffer, size);
 195           if (n < 0 && errno == EINTR)
 196             goto retry;
 197 # if defined __DragonFly__
 198           if (!(n < 0 && errno == EFBIG))
 199 # endif
 200             {
 201               if (n <= 0)
 202                 
 203                 goto fail1;
 204               if (n + MIN_LEFTOVER <= size)
 205                 {
 206                   
 207                   rof->filled = n;
 208 # if defined __linux__ || defined __ANDROID__
 209                   
 210 
 211                   for (;;)
 212                     {
 213                       n = read (fd, rof->buffer + rof->filled, size - rof->filled);
 214                       if (n < 0 && errno == EINTR)
 215                         goto retry;
 216                       if (n < 0)
 217                         
 218                         goto fail1;
 219                       if (n + MIN_LEFTOVER > size - rof->filled)
 220                         
 221                         break;
 222                       if (n == 0)
 223                         {
 224                           
 225                           close (fd);
 226                           return 0;
 227                         }
 228                       rof->filled += n;
 229                     }
 230 # else
 231                   close (fd);
 232                   return 0;
 233 # endif
 234                 }
 235             }
 236         }
 237       
 238       if (pagesize == 0)
 239         {
 240           pagesize = getpagesize ();
 241           size = pagesize;
 242           while (size <= MIN_LEFTOVER)
 243             size = 2 * size;
 244         }
 245       else
 246         {
 247           size = 2 * size;
 248           if (size == 0)
 249             
 250             goto fail1;
 251           if (rof->auxmap != NULL)
 252             munmap (rof->auxmap, rof->auxmap_length);
 253         }
 254       rof->auxmap = (void *) mmap ((void *) 0, size, PROT_READ | PROT_WRITE,
 255                                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 256       if (rof->auxmap == (void *) -1)
 257         {
 258           close (fd);
 259           return -1;
 260         }
 261       rof->auxmap_length = size;
 262       rof->auxmap_start = (unsigned long) rof->auxmap;
 263       rof->auxmap_end = rof->auxmap_start + size;
 264       rof->buffer = (char *) rof->auxmap;
 265      retry:
 266       
 267       if (lseek (fd, 0, SEEK_SET) < 0)
 268         {
 269           close (fd);
 270           fd = open (filename, O_RDONLY | O_CLOEXEC);
 271           if (fd < 0)
 272             goto fail2;
 273         }
 274     }
 275  fail1:
 276   close (fd);
 277  fail2:
 278   if (rof->auxmap != NULL)
 279     munmap (rof->auxmap, rof->auxmap_length);
 280   return -1;
 281 }
 282 
 283 
 284 
 285 static int
 286 rof_peekchar (struct rofile *rof)
     
 287 {
 288   if (rof->position == rof->filled)
 289     {
 290       rof->eof_seen = 1;
 291       return -1;
 292     }
 293   return (unsigned char) rof->buffer[rof->position];
 294 }
 295 
 296 
 297 static int
 298 rof_getchar (struct rofile *rof)
     
 299 {
 300   int c = rof_peekchar (rof);
 301   if (c >= 0)
 302     rof->position++;
 303   return c;
 304 }
 305 
 306 
 307 static int
 308 rof_scanf_lx (struct rofile *rof, unsigned long *valuep)
     
 309 {
 310   unsigned long value = 0;
 311   unsigned int numdigits = 0;
 312   for (;;)
 313     {
 314       int c = rof_peekchar (rof);
 315       if (c >= '0' && c <= '9')
 316         value = (value << 4) + (c - '0');
 317       else if (c >= 'A' && c <= 'F')
 318         value = (value << 4) + (c - 'A' + 10);
 319       else if (c >= 'a' && c <= 'f')
 320         value = (value << 4) + (c - 'a' + 10);
 321       else
 322         break;
 323       rof_getchar (rof);
 324       numdigits++;
 325     }
 326   if (numdigits == 0)
 327     return -1;
 328   *valuep = value;
 329   return 0;
 330 }
 331 
 332 
 333 static void
 334 rof_close (struct rofile *rof)
     
 335 {
 336   if (rof->auxmap != NULL)
 337     munmap (rof->auxmap, rof->auxmap_length);
 338 }
 339 
 340 #endif
 341 
 342 
 343 
 344 
 345 #if defined __linux__ || defined __ANDROID__ || (defined __FreeBSD_kernel__ && !defined __FreeBSD__) 
 346 
 347 
 348 
 349 static int
 350 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
     
 351 {
 352   struct rofile rof;
 353 
 354   
 355   if (rof_open (&rof, "/proc/self/maps") >= 0)
 356     {
 357       unsigned long auxmap_start = rof.auxmap_start;
 358       unsigned long auxmap_end = rof.auxmap_end;
 359 
 360       for (;;)
 361         {
 362           unsigned long start, end;
 363           unsigned int flags;
 364           int c;
 365 
 366           
 367           if (!(rof_scanf_lx (&rof, &start) >= 0
 368                 && rof_getchar (&rof) == '-'
 369                 && rof_scanf_lx (&rof, &end) >= 0))
 370             break;
 371           
 372           do
 373             c = rof_getchar (&rof);
 374           while (c == ' ');
 375           flags = 0;
 376           if (c == 'r')
 377             flags |= VMA_PROT_READ;
 378           c = rof_getchar (&rof);
 379           if (c == 'w')
 380             flags |= VMA_PROT_WRITE;
 381           c = rof_getchar (&rof);
 382           if (c == 'x')
 383             flags |= VMA_PROT_EXECUTE;
 384           while (c = rof_getchar (&rof), c != -1 && c != '\n')
 385             ;
 386 
 387           if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 388             {
 389               
 390 
 391               if (start < auxmap_start)
 392                 if (callback (data, start, auxmap_start, flags))
 393                   break;
 394               if (auxmap_end - 1 < end - 1)
 395                 if (callback (data, auxmap_end, end, flags))
 396                   break;
 397             }
 398           else
 399             {
 400               if (callback (data, start, end, flags))
 401                 break;
 402             }
 403         }
 404       rof_close (&rof);
 405       return 0;
 406     }
 407 
 408   return -1;
 409 }
 410 
 411 #elif defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__
 412 
 413 static int
 414 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
     
 415 {
 416   struct rofile rof;
 417 
 418   
 419   if (rof_open (&rof, "/proc/curproc/map") >= 0)
 420     {
 421       unsigned long auxmap_start = rof.auxmap_start;
 422       unsigned long auxmap_end = rof.auxmap_end;
 423 
 424       for (;;)
 425         {
 426           unsigned long start, end;
 427           unsigned int flags;
 428           int c;
 429 
 430           
 431           if (!(rof_getchar (&rof) == '0'
 432                 && rof_getchar (&rof) == 'x'
 433                 && rof_scanf_lx (&rof, &start) >= 0))
 434             break;
 435           while (c = rof_peekchar (&rof), c == ' ' || c == '\t')
 436             rof_getchar (&rof);
 437           
 438           if (!(rof_getchar (&rof) == '0'
 439                 && rof_getchar (&rof) == 'x'
 440                 && rof_scanf_lx (&rof, &end) >= 0))
 441             break;
 442 # if defined __FreeBSD__ || defined __DragonFly__
 443           
 444           do
 445             c = rof_getchar (&rof);
 446           while (c == ' ');
 447           do
 448             c = rof_getchar (&rof);
 449           while (c != -1 && c != '\n' && c != ' ');
 450           
 451           do
 452             c = rof_getchar (&rof);
 453           while (c == ' ');
 454           do
 455             c = rof_getchar (&rof);
 456           while (c != -1 && c != '\n' && c != ' ');
 457           
 458           do
 459             c = rof_getchar (&rof);
 460           while (c == ' ');
 461           do
 462             c = rof_getchar (&rof);
 463           while (c != -1 && c != '\n' && c != ' ');
 464 # endif
 465           
 466           do
 467             c = rof_getchar (&rof);
 468           while (c == ' ');
 469           flags = 0;
 470           if (c == 'r')
 471             flags |= VMA_PROT_READ;
 472           c = rof_getchar (&rof);
 473           if (c == 'w')
 474             flags |= VMA_PROT_WRITE;
 475           c = rof_getchar (&rof);
 476           if (c == 'x')
 477             flags |= VMA_PROT_EXECUTE;
 478           while (c = rof_getchar (&rof), c != -1 && c != '\n')
 479             ;
 480 
 481           if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 482             {
 483               
 484 
 485               if (start < auxmap_start)
 486                 if (callback (data, start, auxmap_start, flags))
 487                   break;
 488               if (auxmap_end - 1 < end - 1)
 489                 if (callback (data, auxmap_end, end, flags))
 490                   break;
 491             }
 492           else
 493             {
 494               if (callback (data, start, end, flags))
 495                 break;
 496             }
 497         }
 498       rof_close (&rof);
 499       return 0;
 500     }
 501 
 502   return -1;
 503 }
 504 
 505 #elif defined __minix
 506 
 507 static int
 508 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
     
 509 {
 510   char fnamebuf[6+10+4+1];
 511   char *fname;
 512   struct rofile rof;
 513 
 514   
 515   fname = fnamebuf + sizeof (fnamebuf) - (4 + 1);
 516   memcpy (fname, "/map", 4 + 1);
 517   {
 518     unsigned int value = getpid ();
 519     do
 520       *--fname = (value % 10) + '0';
 521     while ((value = value / 10) > 0);
 522   }
 523   fname -= 6;
 524   memcpy (fname, "/proc/", 6);
 525 
 526   
 527   if (rof_open (&rof, fname) >= 0)
 528     {
 529       unsigned long auxmap_start = rof.auxmap_start;
 530       unsigned long auxmap_end = rof.auxmap_end;
 531 
 532       for (;;)
 533         {
 534           unsigned long start, end;
 535           unsigned int flags;
 536           int c;
 537 
 538           
 539           if (!(rof_scanf_lx (&rof, &start) >= 0
 540                 && rof_getchar (&rof) == '-'
 541                 && rof_scanf_lx (&rof, &end) >= 0))
 542             break;
 543           
 544           do
 545             c = rof_getchar (&rof);
 546           while (c == ' ');
 547           flags = 0;
 548           if (c == 'r')
 549             flags |= VMA_PROT_READ;
 550           c = rof_getchar (&rof);
 551           if (c == 'w')
 552             flags |= VMA_PROT_WRITE;
 553           c = rof_getchar (&rof);
 554           if (c == 'x')
 555             flags |= VMA_PROT_EXECUTE;
 556           while (c = rof_getchar (&rof), c != -1 && c != '\n')
 557             ;
 558 
 559           if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 560             {
 561               
 562 
 563               if (start < auxmap_start)
 564                 if (callback (data, start, auxmap_start, flags))
 565                   break;
 566               if (auxmap_end - 1 < end - 1)
 567                 if (callback (data, auxmap_end, end, flags))
 568                   break;
 569             }
 570           else
 571             {
 572               if (callback (data, start, end, flags))
 573                 break;
 574             }
 575         }
 576       rof_close (&rof);
 577       return 0;
 578     }
 579 
 580   return -1;
 581 }
 582 
 583 #else
 584 
 585 static inline int
 586 vma_iterate_proc (vma_iterate_callback_fn callback, void *data)
     
 587 {
 588   return -1;
 589 }
 590 
 591 #endif
 592 
 593 
 594 
 595 
 596 #if (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined KERN_PROC_VMMAP 
 597 
 598 static int
 599 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
     
 600 {
 601   
 602   int info_path[] = { CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid () };
 603   size_t len;
 604   size_t pagesize;
 605   size_t memneed;
 606   void *auxmap;
 607   unsigned long auxmap_start;
 608   unsigned long auxmap_end;
 609   char *mem;
 610   char *p;
 611   char *p_end;
 612 
 613   len = 0;
 614   if (sysctl (info_path, 4, NULL, &len, NULL, 0) < 0)
 615     return -1;
 616   
 617 
 618   len = 2 * len + 200;
 619   
 620 
 621 
 622 
 623 
 624   pagesize = getpagesize ();
 625   memneed = len;
 626   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
 627   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
 628                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 629   if (auxmap == (void *) -1)
 630     return -1;
 631   auxmap_start = (unsigned long) auxmap;
 632   auxmap_end = auxmap_start + memneed;
 633   mem = (char *) auxmap;
 634   if (sysctl (info_path, 4, mem, &len, NULL, 0) < 0)
 635     {
 636       munmap (auxmap, memneed);
 637       return -1;
 638     }
 639   p = mem;
 640   p_end = mem + len;
 641   while (p < p_end)
 642     {
 643       struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
 644       unsigned long start = kve->kve_start;
 645       unsigned long end = kve->kve_end;
 646       unsigned int flags = 0;
 647       if (kve->kve_protection & KVME_PROT_READ)
 648         flags |= VMA_PROT_READ;
 649       if (kve->kve_protection & KVME_PROT_WRITE)
 650         flags |= VMA_PROT_WRITE;
 651       if (kve->kve_protection & KVME_PROT_EXEC)
 652         flags |= VMA_PROT_EXECUTE;
 653       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 654         {
 655           
 656 
 657           if (start < auxmap_start)
 658             if (callback (data, start, auxmap_start, flags))
 659               break;
 660           if (auxmap_end - 1 < end - 1)
 661             if (callback (data, auxmap_end, end, flags))
 662               break;
 663         }
 664       else
 665         {
 666           if (callback (data, start, end, flags))
 667             break;
 668         }
 669       p += kve->kve_structsize;
 670     }
 671   munmap (auxmap, memneed);
 672   return 0;
 673 }
 674 
 675 #elif defined __NetBSD__ && defined VM_PROC_MAP 
 676 
 677 static int
 678 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
     
 679 {
 680   
 681   unsigned int entry_size =
 682     
 683 
 684 
 685     offsetof (struct kinfo_vmentry, kve_path);
 686   int info_path[] = { CTL_VM, VM_PROC, VM_PROC_MAP, getpid (), entry_size };
 687   size_t len;
 688   size_t pagesize;
 689   size_t memneed;
 690   void *auxmap;
 691   unsigned long auxmap_start;
 692   unsigned long auxmap_end;
 693   char *mem;
 694   char *p;
 695   char *p_end;
 696 
 697   len = 0;
 698   if (sysctl (info_path, 5, NULL, &len, NULL, 0) < 0)
 699     return -1;
 700   
 701 
 702   len = 2 * len + 10 * entry_size;
 703   
 704   if (len > 0x100000)
 705     len = 0x100000;
 706   
 707 
 708   len = (len / entry_size) * entry_size;
 709   
 710 
 711 
 712 
 713 
 714   pagesize = getpagesize ();
 715   memneed = len;
 716   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
 717   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
 718                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 719   if (auxmap == (void *) -1)
 720     return -1;
 721   auxmap_start = (unsigned long) auxmap;
 722   auxmap_end = auxmap_start + memneed;
 723   mem = (char *) auxmap;
 724   if (sysctl (info_path, 5, mem, &len, NULL, 0) < 0
 725       || len > 0x100000 - entry_size)
 726     {
 727       
 728       munmap (auxmap, memneed);
 729       return -1;
 730     }
 731   p = mem;
 732   p_end = mem + len;
 733   while (p < p_end)
 734     {
 735       struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
 736       unsigned long start = kve->kve_start;
 737       unsigned long end = kve->kve_end;
 738       unsigned int flags = 0;
 739       if (kve->kve_protection & KVME_PROT_READ)
 740         flags |= VMA_PROT_READ;
 741       if (kve->kve_protection & KVME_PROT_WRITE)
 742         flags |= VMA_PROT_WRITE;
 743       if (kve->kve_protection & KVME_PROT_EXEC)
 744         flags |= VMA_PROT_EXECUTE;
 745       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 746         {
 747           
 748 
 749           if (start < auxmap_start)
 750             if (callback (data, start, auxmap_start, flags))
 751               break;
 752           if (auxmap_end - 1 < end - 1)
 753             if (callback (data, auxmap_end, end, flags))
 754               break;
 755         }
 756       else
 757         {
 758           if (callback (data, start, end, flags))
 759             break;
 760         }
 761       p += entry_size;
 762     }
 763   munmap (auxmap, memneed);
 764   return 0;
 765 }
 766 
 767 #elif defined __OpenBSD__ && defined KERN_PROC_VMMAP 
 768 
 769 static int
 770 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
     
 771 {
 772   
 773   int info_path[] = { CTL_KERN, KERN_PROC_VMMAP, getpid () };
 774   size_t len;
 775   size_t pagesize;
 776   size_t memneed;
 777   void *auxmap;
 778   unsigned long auxmap_start;
 779   unsigned long auxmap_end;
 780   char *mem;
 781   char *p;
 782   char *p_end;
 783 
 784   len = 0;
 785   if (sysctl (info_path, 3, NULL, &len, NULL, 0) < 0)
 786     return -1;
 787   
 788 
 789   len = 2 * len + 10 * sizeof (struct kinfo_vmentry);
 790   
 791   if (len > 0x10000)
 792     len = 0x10000;
 793   
 794 
 795   len = (len / sizeof (struct kinfo_vmentry)) * sizeof (struct kinfo_vmentry);
 796   
 797 
 798 
 799 
 800 
 801   pagesize = getpagesize ();
 802   memneed = len;
 803   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
 804   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
 805                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 806   if (auxmap == (void *) -1)
 807     return -1;
 808   auxmap_start = (unsigned long) auxmap;
 809   auxmap_end = auxmap_start + memneed;
 810   mem = (char *) auxmap;
 811   if (sysctl (info_path, 3, mem, &len, NULL, 0) < 0
 812       || len > 0x10000 - sizeof (struct kinfo_vmentry))
 813     {
 814       
 815       munmap (auxmap, memneed);
 816       return -1;
 817     }
 818   p = mem;
 819   p_end = mem + len;
 820   while (p < p_end)
 821     {
 822       struct kinfo_vmentry *kve = (struct kinfo_vmentry *) p;
 823       unsigned long start = kve->kve_start;
 824       unsigned long end = kve->kve_end;
 825       unsigned int flags = 0;
 826       if (kve->kve_protection & KVE_PROT_READ)
 827         flags |= VMA_PROT_READ;
 828       if (kve->kve_protection & KVE_PROT_WRITE)
 829         flags |= VMA_PROT_WRITE;
 830       if (kve->kve_protection & KVE_PROT_EXEC)
 831         flags |= VMA_PROT_EXECUTE;
 832       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 833         {
 834           
 835 
 836           if (start < auxmap_start)
 837             if (callback (data, start, auxmap_start, flags))
 838               break;
 839           if (auxmap_end - 1 < end - 1)
 840             if (callback (data, auxmap_end, end, flags))
 841               break;
 842         }
 843       else
 844         {
 845           if (start != end)
 846             if (callback (data, start, end, flags))
 847               break;
 848         }
 849       p += sizeof (struct kinfo_vmentry);
 850     }
 851   munmap (auxmap, memneed);
 852   return 0;
 853 }
 854 
 855 #else
 856 
 857 static inline int
 858 vma_iterate_bsd (vma_iterate_callback_fn callback, void *data)
     
 859 {
 860   return -1;
 861 }
 862 
 863 #endif
 864 
 865 
 866 int
 867 vma_iterate (vma_iterate_callback_fn callback, void *data)
     
 868 {
 869 #if defined __linux__ || defined __ANDROID__ || defined __FreeBSD_kernel__ || defined __FreeBSD__ || defined __DragonFly__ || defined __NetBSD__ || defined __minix 
 870 
 871 # if defined __FreeBSD__
 872   
 873 
 874 
 875 
 876 
 877   int retval = vma_iterate_bsd (callback, data);
 878   if (retval == 0)
 879       return 0;
 880 
 881   return vma_iterate_proc (callback, data);
 882 # else
 883   
 884 
 885   int retval = vma_iterate_proc (callback, data);
 886   if (retval == 0)
 887       return 0;
 888 
 889   return vma_iterate_bsd (callback, data);
 890 # endif
 891 
 892 #elif defined __sgi || defined __osf__ 
 893 
 894   size_t pagesize;
 895   char fnamebuf[6+10+1];
 896   char *fname;
 897   int fd;
 898   int nmaps;
 899   size_t memneed;
 900 # if HAVE_MAP_ANONYMOUS
 901 #  define zero_fd -1
 902 #  define map_flags MAP_ANONYMOUS
 903 # else
 904   int zero_fd;
 905 #  define map_flags 0
 906 # endif
 907   void *auxmap;
 908   unsigned long auxmap_start;
 909   unsigned long auxmap_end;
 910   prmap_t* maps;
 911   prmap_t* mp;
 912 
 913   pagesize = getpagesize ();
 914 
 915   
 916   fname = fnamebuf + sizeof (fnamebuf) - 1;
 917   *fname = '\0';
 918   {
 919     unsigned int value = getpid ();
 920     do
 921       *--fname = (value % 10) + '0';
 922     while ((value = value / 10) > 0);
 923   }
 924   fname -= 6;
 925   memcpy (fname, "/proc/", 6);
 926 
 927   fd = open (fname, O_RDONLY | O_CLOEXEC);
 928   if (fd < 0)
 929     return -1;
 930 
 931   if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
 932     goto fail2;
 933 
 934   memneed = (nmaps + 10) * sizeof (prmap_t);
 935   
 936 
 937 
 938 
 939 
 940   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
 941 # if !HAVE_MAP_ANONYMOUS
 942   zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
 943   if (zero_fd < 0)
 944     goto fail2;
 945 # endif
 946   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
 947                           map_flags | MAP_PRIVATE, zero_fd, 0);
 948 # if !HAVE_MAP_ANONYMOUS
 949   close (zero_fd);
 950 # endif
 951   if (auxmap == (void *) -1)
 952     goto fail2;
 953   auxmap_start = (unsigned long) auxmap;
 954   auxmap_end = auxmap_start + memneed;
 955   maps = (prmap_t *) auxmap;
 956 
 957   if (ioctl (fd, PIOCMAP, maps) < 0)
 958     goto fail1;
 959 
 960   for (mp = maps;;)
 961     {
 962       unsigned long start, end;
 963       unsigned int flags;
 964 
 965       start = (unsigned long) mp->pr_vaddr;
 966       end = start + mp->pr_size;
 967       if (start == 0 && end == 0)
 968         break;
 969       flags = 0;
 970       if (mp->pr_mflags & MA_READ)
 971         flags |= VMA_PROT_READ;
 972       if (mp->pr_mflags & MA_WRITE)
 973         flags |= VMA_PROT_WRITE;
 974       if (mp->pr_mflags & MA_EXEC)
 975         flags |= VMA_PROT_EXECUTE;
 976       mp++;
 977       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
 978         {
 979           
 980 
 981           if (start < auxmap_start)
 982             if (callback (data, start, auxmap_start, flags))
 983               break;
 984           if (auxmap_end - 1 < end - 1)
 985             if (callback (data, auxmap_end, end, flags))
 986               break;
 987         }
 988       else
 989         {
 990           if (callback (data, start, end, flags))
 991             break;
 992         }
 993     }
 994   munmap (auxmap, memneed);
 995   close (fd);
 996   return 0;
 997 
 998  fail1:
 999   munmap (auxmap, memneed);
1000  fail2:
1001   close (fd);
1002   return -1;
1003 
1004 #elif defined __sun 
1005 
1006   
1007 
1008 
1009 
1010 
1011 
1012 
1013 
1014 
1015 
1016 # if defined PIOCNMAP && defined PIOCMAP
1017   
1018 
1019   size_t pagesize;
1020   char fnamebuf[6+10+1];
1021   char *fname;
1022   int fd;
1023   int nmaps;
1024   size_t memneed;
1025 #  if HAVE_MAP_ANONYMOUS
1026 #   define zero_fd -1
1027 #   define map_flags MAP_ANONYMOUS
1028 #  else 
1029   int zero_fd;
1030 #   define map_flags 0
1031 #  endif
1032   void *auxmap;
1033   unsigned long auxmap_start;
1034   unsigned long auxmap_end;
1035   prmap_t* maps;
1036   prmap_t* mp;
1037 
1038   pagesize = getpagesize ();
1039 
1040   
1041   fname = fnamebuf + sizeof (fnamebuf) - 1;
1042   *fname = '\0';
1043   {
1044     unsigned int value = getpid ();
1045     do
1046       *--fname = (value % 10) + '0';
1047     while ((value = value / 10) > 0);
1048   }
1049   fname -= 6;
1050   memcpy (fname, "/proc/", 6);
1051 
1052   fd = open (fname, O_RDONLY | O_CLOEXEC);
1053   if (fd < 0)
1054     return -1;
1055 
1056   if (ioctl (fd, PIOCNMAP, &nmaps) < 0)
1057     goto fail2;
1058 
1059   memneed = (nmaps + 10) * sizeof (prmap_t);
1060   
1061 
1062 
1063 
1064 
1065   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1066 #  if !HAVE_MAP_ANONYMOUS
1067   zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
1068   if (zero_fd < 0)
1069     goto fail2;
1070 #  endif
1071   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1072                           map_flags | MAP_PRIVATE, zero_fd, 0);
1073 #  if !HAVE_MAP_ANONYMOUS
1074   close (zero_fd);
1075 #  endif
1076   if (auxmap == (void *) -1)
1077     goto fail2;
1078   auxmap_start = (unsigned long) auxmap;
1079   auxmap_end = auxmap_start + memneed;
1080   maps = (prmap_t *) auxmap;
1081 
1082   if (ioctl (fd, PIOCMAP, maps) < 0)
1083     goto fail1;
1084 
1085   for (mp = maps;;)
1086     {
1087       unsigned long start, end;
1088       unsigned int flags;
1089 
1090       start = (unsigned long) mp->pr_vaddr;
1091       end = start + mp->pr_size;
1092       if (start == 0 && end == 0)
1093         break;
1094       flags = 0;
1095       if (mp->pr_mflags & MA_READ)
1096         flags |= VMA_PROT_READ;
1097       if (mp->pr_mflags & MA_WRITE)
1098         flags |= VMA_PROT_WRITE;
1099       if (mp->pr_mflags & MA_EXEC)
1100         flags |= VMA_PROT_EXECUTE;
1101       mp++;
1102       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1103         {
1104           
1105 
1106           if (start < auxmap_start)
1107             if (callback (data, start, auxmap_start, flags))
1108               break;
1109           if (auxmap_end - 1 < end - 1)
1110             if (callback (data, auxmap_end, end, flags))
1111               break;
1112         }
1113       else
1114         {
1115           if (callback (data, start, end, flags))
1116             break;
1117         }
1118     }
1119   munmap (auxmap, memneed);
1120   close (fd);
1121   return 0;
1122 
1123  fail1:
1124   munmap (auxmap, memneed);
1125  fail2:
1126   close (fd);
1127   return -1;
1128 
1129 # else
1130   
1131 
1132 
1133 
1134 
1135 
1136 
1137   size_t pagesize;
1138   char fnamebuf[6+10+4+1];
1139   char *fname;
1140   int fd;
1141   int nmaps;
1142   size_t memneed;
1143 #  if HAVE_MAP_ANONYMOUS
1144 #   define zero_fd -1
1145 #   define map_flags MAP_ANONYMOUS
1146 #  else 
1147   int zero_fd;
1148 #   define map_flags 0
1149 #  endif
1150   void *auxmap;
1151   unsigned long auxmap_start;
1152   unsigned long auxmap_end;
1153   prmap_t* maps;
1154   prmap_t* maps_end;
1155   prmap_t* mp;
1156 
1157   pagesize = getpagesize ();
1158 
1159   
1160   fname = fnamebuf + sizeof (fnamebuf) - 1 - 4;
1161   memcpy (fname, "/map", 4 + 1);
1162   {
1163     unsigned int value = getpid ();
1164     do
1165       *--fname = (value % 10) + '0';
1166     while ((value = value / 10) > 0);
1167   }
1168   fname -= 6;
1169   memcpy (fname, "/proc/", 6);
1170 
1171   fd = open (fname, O_RDONLY | O_CLOEXEC);
1172   if (fd < 0)
1173     return -1;
1174 
1175   {
1176     struct stat statbuf;
1177     if (fstat (fd, &statbuf) < 0)
1178       goto fail2;
1179     nmaps = statbuf.st_size / sizeof (prmap_t);
1180   }
1181 
1182   memneed = (nmaps + 10) * sizeof (prmap_t);
1183   
1184 
1185 
1186 
1187 
1188   memneed = ((memneed - 1) / pagesize + 1) * pagesize;
1189 #  if !HAVE_MAP_ANONYMOUS
1190   zero_fd = open ("/dev/zero", O_RDONLY | O_CLOEXEC, 0644);
1191   if (zero_fd < 0)
1192     goto fail2;
1193 #  endif
1194   auxmap = (void *) mmap ((void *) 0, memneed, PROT_READ | PROT_WRITE,
1195                           map_flags | MAP_PRIVATE, zero_fd, 0);
1196 #  if !HAVE_MAP_ANONYMOUS
1197   close (zero_fd);
1198 #  endif
1199   if (auxmap == (void *) -1)
1200     goto fail2;
1201   auxmap_start = (unsigned long) auxmap;
1202   auxmap_end = auxmap_start + memneed;
1203   maps = (prmap_t *) auxmap;
1204 
1205   
1206   {
1207     size_t remaining = memneed;
1208     size_t total_read = 0;
1209     char *ptr = (char *) maps;
1210 
1211     do
1212       {
1213         size_t nread = read (fd, ptr, remaining);
1214         if (nread == (size_t)-1)
1215           {
1216             if (errno == EINTR)
1217               continue;
1218             goto fail1;
1219           }
1220         if (nread == 0)
1221           
1222           break;
1223         total_read += nread;
1224         ptr += nread;
1225         remaining -= nread;
1226       }
1227     while (remaining > 0);
1228 
1229     nmaps = (memneed - remaining) / sizeof (prmap_t);
1230     maps_end = maps + nmaps;
1231   }
1232 
1233   for (mp = maps; mp < maps_end; mp++)
1234     {
1235       unsigned long start, end;
1236       unsigned int flags;
1237 
1238       start = (unsigned long) mp->pr_vaddr;
1239       end = start + mp->pr_size;
1240       flags = 0;
1241       if (mp->pr_mflags & MA_READ)
1242         flags |= VMA_PROT_READ;
1243       if (mp->pr_mflags & MA_WRITE)
1244         flags |= VMA_PROT_WRITE;
1245       if (mp->pr_mflags & MA_EXEC)
1246         flags |= VMA_PROT_EXECUTE;
1247       if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
1248         {
1249           
1250 
1251           if (start < auxmap_start)
1252             if (callback (data, start, auxmap_start, flags))
1253               break;
1254           if (auxmap_end - 1 < end - 1)
1255             if (callback (data, auxmap_end, end, flags))
1256               break;
1257         }
1258       else
1259         {
1260           if (callback (data, start, end, flags))
1261             break;
1262         }
1263     }
1264   munmap (auxmap, memneed);
1265   close (fd);
1266   return 0;
1267 
1268  fail1:
1269   munmap (auxmap, memneed);
1270  fail2:
1271   close (fd);
1272   return -1;
1273 
1274 # endif
1275 
1276 #elif HAVE_PSTAT_GETPROCVM 
1277 
1278   unsigned long pagesize = getpagesize ();
1279   int i;
1280 
1281   for (i = 0; ; i++)
1282     {
1283       struct pst_vm_status info;
1284       int ret = pstat_getprocvm (&info, sizeof (info), 0, i);
1285       if (ret < 0)
1286         return -1;
1287       if (ret == 0)
1288         break;
1289       {
1290         unsigned long start = info.pst_vaddr;
1291         unsigned long end = start + info.pst_length * pagesize;
1292         unsigned int flags = 0;
1293         if (info.pst_permission & PS_PROT_READ)
1294           flags |= VMA_PROT_READ;
1295         if (info.pst_permission & PS_PROT_WRITE)
1296           flags |= VMA_PROT_WRITE;
1297         if (info.pst_permission & PS_PROT_EXECUTE)
1298           flags |= VMA_PROT_EXECUTE;
1299 
1300         if (callback (data, start, end, flags))
1301           break;
1302       }
1303     }
1304 
1305 #elif defined __APPLE__ && defined __MACH__ 
1306 
1307   task_t task = mach_task_self ();
1308   vm_address_t address;
1309   vm_size_t size;
1310 
1311   for (address = VM_MIN_ADDRESS;; address += size)
1312     {
1313       int more;
1314       mach_port_t object_name;
1315       unsigned int flags;
1316       
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 
1333 
1334 
1335 
1336 # if defined __aarch64__ || defined __ppc64__ || defined __x86_64__
1337       struct vm_region_basic_info_64 info;
1338       mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
1339 
1340       more = (vm_region_64 (task, &address, &size, VM_REGION_BASIC_INFO_64,
1341                             (vm_region_info_t)&info, &info_count, &object_name)
1342               == KERN_SUCCESS);
1343 # else
1344       struct vm_region_basic_info info;
1345       mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
1346 
1347       more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
1348                          (vm_region_info_t)&info, &info_count, &object_name)
1349               == KERN_SUCCESS);
1350 # endif
1351       if (object_name != MACH_PORT_NULL)
1352         mach_port_deallocate (mach_task_self (), object_name);
1353       if (!more)
1354         break;
1355       flags = 0;
1356       if (info.protection & VM_PROT_READ)
1357         flags |= VMA_PROT_READ;
1358       if (info.protection & VM_PROT_WRITE)
1359         flags |= VMA_PROT_WRITE;
1360       if (info.protection & VM_PROT_EXECUTE)
1361         flags |= VMA_PROT_EXECUTE;
1362       if (callback (data, address, address + size, flags))
1363         break;
1364     }
1365   return 0;
1366 
1367 #elif defined __GNU__ 
1368 
1369   
1370 
1371 
1372 
1373 
1374 
1375   task_t task = mach_task_self ();
1376   vm_address_t address;
1377   vm_size_t size;
1378 
1379   for (address = 0;; address += size)
1380     {
1381       vm_prot_t protection;
1382       vm_prot_t max_protection;
1383       vm_inherit_t inheritance;
1384       boolean_t shared;
1385       memory_object_name_t object_name;
1386       vm_offset_t offset;
1387       unsigned int flags;
1388 
1389       if (!(vm_region (task, &address, &size, &protection, &max_protection,
1390                          &inheritance, &shared, &object_name, &offset)
1391             == KERN_SUCCESS))
1392         break;
1393       mach_port_deallocate (task, object_name);
1394       flags = 0;
1395       if (protection & VM_PROT_READ)
1396         flags |= VMA_PROT_READ;
1397       if (protection & VM_PROT_WRITE)
1398         flags |= VMA_PROT_WRITE;
1399       if (protection & VM_PROT_EXECUTE)
1400         flags |= VMA_PROT_EXECUTE;
1401       if (callback (data, address, address + size, flags))
1402         break;
1403     }
1404   return 0;
1405 
1406 #elif defined _WIN32 || defined __CYGWIN__
1407   
1408 
1409   MEMORY_BASIC_INFORMATION info;
1410   uintptr_t address = 0;
1411 
1412   while (VirtualQuery ((void*)address, &info, sizeof(info)) == sizeof(info))
1413     {
1414       if (info.State != MEM_FREE)
1415         
1416 
1417 
1418 
1419         if (info.State != MEM_RESERVE)
1420           {
1421             uintptr_t start, end;
1422             unsigned int flags;
1423 
1424             start = (uintptr_t)info.BaseAddress;
1425             end = start + info.RegionSize;
1426             switch (info.Protect & ~(PAGE_GUARD|PAGE_NOCACHE))
1427               {
1428               case PAGE_READONLY:
1429                 flags = VMA_PROT_READ;
1430                 break;
1431               case PAGE_READWRITE:
1432               case PAGE_WRITECOPY:
1433                 flags = VMA_PROT_READ | VMA_PROT_WRITE;
1434                 break;
1435               case PAGE_EXECUTE:
1436                 flags = VMA_PROT_EXECUTE;
1437                 break;
1438               case PAGE_EXECUTE_READ:
1439                 flags = VMA_PROT_READ | VMA_PROT_EXECUTE;
1440                 break;
1441               case PAGE_EXECUTE_READWRITE:
1442               case PAGE_EXECUTE_WRITECOPY:
1443                 flags = VMA_PROT_READ | VMA_PROT_WRITE | VMA_PROT_EXECUTE;
1444                 break;
1445               case PAGE_NOACCESS:
1446               default:
1447                 flags = 0;
1448                 break;
1449               }
1450 
1451             if (callback (data, start, end, flags))
1452               break;
1453           }
1454       address = (uintptr_t)info.BaseAddress + info.RegionSize;
1455     }
1456   return 0;
1457 
1458 #elif defined __BEOS__ || defined __HAIKU__
1459   
1460 
1461   area_info info;
1462   ssize_t cookie;
1463 
1464   cookie = 0;
1465   while (get_next_area_info (0, &cookie, &info) == B_OK)
1466     {
1467       unsigned long start, end;
1468       unsigned int flags;
1469 
1470       start = (unsigned long) info.address;
1471       end = start + info.size;
1472       flags = 0;
1473       if (info.protection & B_READ_AREA)
1474         flags |= VMA_PROT_READ | VMA_PROT_EXECUTE;
1475       if (info.protection & B_WRITE_AREA)
1476         flags |= VMA_PROT_WRITE;
1477 
1478       if (callback (data, start, end, flags))
1479         break;
1480     }
1481   return 0;
1482 
1483 #elif HAVE_MQUERY 
1484 
1485 # if defined __OpenBSD__
1486   
1487 
1488   {
1489     int retval = vma_iterate_bsd (callback, data);
1490     if (retval == 0)
1491       return 0;
1492   }
1493 # endif
1494 
1495   {
1496     uintptr_t pagesize;
1497     uintptr_t address;
1498     int  address_known_mapped;
1499 
1500     pagesize = getpagesize ();
1501     
1502 
1503     address = pagesize;
1504     address_known_mapped = 0;
1505     for (;;)
1506       {
1507         
1508         if (address_known_mapped
1509             || mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0)
1510                == (void *) -1)
1511           {
1512             
1513 
1514             uintptr_t start = address;
1515             uintptr_t end;
1516 
1517             
1518             end = (uintptr_t) mquery ((void *) address, pagesize, 0, 0, -1, 0);
1519             if (end == (uintptr_t) (void *) -1)
1520               end = 0; 
1521             address = end;
1522 
1523             
1524 
1525             if (callback (data, start, end, 0))
1526               break;
1527 
1528             if (address < pagesize) 
1529               break;
1530           }
1531         
1532         {
1533           uintptr_t query_size = pagesize;
1534 
1535           address += pagesize;
1536 
1537           
1538 
1539           for (;;)
1540             {
1541               if (2 * query_size > query_size)
1542                 query_size = 2 * query_size;
1543               if (address + query_size - 1 < query_size) 
1544                 {
1545                   address_known_mapped = 0;
1546                   break;
1547                 }
1548               if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0)
1549                   == (void *) -1)
1550                 {
1551                   
1552 
1553                   address_known_mapped = (query_size == pagesize);
1554                   break;
1555                 }
1556               
1557 
1558               address += query_size;
1559             }
1560           
1561 
1562           while (query_size > pagesize)
1563             {
1564               query_size = query_size / 2;
1565               if (address + query_size - 1 >= query_size)
1566                 {
1567                   if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0)
1568                       != (void *) -1)
1569                     {
1570                       
1571 
1572                       address += query_size;
1573                       address_known_mapped = 0;
1574                     }
1575                   else
1576                     address_known_mapped = (query_size == pagesize);
1577                 }
1578             }
1579           
1580 
1581 
1582 
1583         }
1584         if (address + pagesize - 1 < pagesize) 
1585           break;
1586       }
1587     return 0;
1588   }
1589 
1590 #else
1591 
1592   
1593   return -1;
1594 
1595 #endif
1596 }
1597 
1598 
1599 #ifdef TEST
1600 
1601 #include <stdio.h>
1602 
1603 
1604 
1605 
1606 static int
1607 vma_iterate_callback (void *data, uintptr_t start, uintptr_t end,
     
1608                       unsigned int flags)
1609 {
1610   printf ("%08lx-%08lx %c%c%c\n",
1611           (unsigned long) start, (unsigned long) end,
1612           flags & VMA_PROT_READ ? 'r' : '-',
1613           flags & VMA_PROT_WRITE ? 'w' : '-',
1614           flags & VMA_PROT_EXECUTE ? 'x' : '-');
1615   return 0;
1616 }
1617 
1618 int
1619 main ()
     
1620 {
1621   vma_iterate (vma_iterate_callback, NULL);
1622 
1623   
1624   sleep (10);
1625 
1626   return 0;
1627 }
1628 
1629 
1630 
1631 
1632 
1633 
1634 
1635 #endif