C 19
Getpmap.c Guest on 20th July 2020 11:51:34 AM
  1. /*
  2.  * Copyright (c) 2011, Columbia University
  3.  * All rights reserved.
  4.  *
  5.  * This software was developed by Vasileios P. Kemerlis <[email protected]>
  6.  * at Columbia University, New York, NY, USA, in May 2011.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions are met:
  10.  *
  11.  *   * Redistributions of source code must retain the above copyright
  12.  *     notice, this list of conditions and the following disclaimer.
  13.  *   * Redistributions in binary form must reproduce the above copyright
  14.  *     notice, this list of conditions and the following disclaimer in the
  15.  *     documentation and/or other materials provided with the distribution.
  16.  *   * Neither the name of Columbia University nor the
  17.  *     names of its contributors may be used to endorse or promote products
  18.  *     derived from this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  */
  32.  
  33.  
  34. #include <err.h>
  35. #include <errno.h>
  36. #include <getopt.h>
  37. #include <limits.h>
  38. #include <stdint.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43.  
  44. /* unnecessary and boring */
  45. #define __PROG__        "getPAGEMAP"
  46. #define __EXEC__        "getpmap"
  47. #define __VER__         "19042002be"
  48. #define __COPYLEFT__    "Copyright 2011 Columbia University.\nThis is free software; see the source for copying conditions. There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
  49. #define __BUGS__        "<[email protected]>"
  50.  
  51. /* constants */
  52. #define BASE10          10              /* base 10 */
  53. #define BASE16          16              /* base 16 */
  54. #define PATH_SZ         32              /* path size (/proc/<pid>/pagemap) */
  55. #define PRESENT_MASK    (1ULL << 63)    /* get bit 63 from a 64-bit integer */
  56. #define PFN_MASK        ((1ULL << 55) - 1)      /* get bits 0-54 from
  57.                                                    a 64-bit integer */
  58.  
  59.  
  60. /*
  61.  * help
  62.  *
  63.  * display useful information
  64.  */
  65. static void
  66. help(void)
  67. {
  68.         /* usage info */
  69.         (void)fprintf(stdout, "Usage: %s [OPTION]...\n", __EXEC__);
  70.         (void)fprintf(stdout, "Read /proc/<pid>/pagemap.\n\n");
  71.  
  72.         /* options */
  73.         (void)fprintf(stdout,
  74.         "\t-p, --pid=NUM\t\tread the pagemap of process with PID=NUM\n");
  75.         (void)fprintf(stdout,
  76.         "\t-a, --virt=NUM\t\tread the pagemap entry for virtual address=NUM\n");
  77.         (void)fprintf(stdout, "\t-h, --help\t\tdisplay this help and exit\n");
  78.         (void)fprintf(stdout,
  79.                 "\t-v, --version\t\tprint version information and exit\n\n");
  80.  
  81.         /* bugs */
  82.         (void)fprintf(stdout, "Report bugs to %s\n", __BUGS__);
  83. }
  84.  
  85. /*
  86.  * version
  87.  *
  88.  * display version information
  89.  */
  90. static void
  91. version(void)
  92. {
  93.         /* display version */
  94.         (void)fprintf(stdout, "%s %s\n\n", __PROG__, __VER__);
  95.         /* copyright info */
  96.         (void)fprintf(stdout, "%s\n", __COPYLEFT__);
  97. }
  98.  
  99. /*
  100.  * query the pagemap
  101.  *
  102.  * open the /proc/<pid>/pagemap of a process and search the page frame
  103.  * information for a specific virtual address
  104.  *
  105.  * @pid:        the pid of the process that we are interested into
  106.  * @vaddr:      the virtual address (page-aligned)
  107.  * @psize:      page size
  108.  */
  109. static void
  110. querypmap(pid_t pid, unsigned long vaddr, long psize)
  111. {
  112.         /* path in /proc */
  113.         char            path[PATH_SZ];
  114.         /* pagemap entry */
  115.         uint64_t        pentry  = 0;
  116.  
  117.         /* pagemap file */
  118.         FILE            *fp     = NULL;
  119.  
  120.         /* cleanup */
  121.         (void)memset(path, 0, PATH_SZ);
  122.  
  123.         /* format the path variable */
  124.         if (snprintf(path, PATH_SZ, "/proc/%d/pagemap", pid) > PATH_SZ)
  125.                 errx(4, "failed while trying to open /proc/%d/pagemap -- %s",
  126.                                 pid, path);
  127.        
  128.         /* open the pagemap file */
  129.         if ((fp = fopen(path, "r")) == NULL)
  130.                 errx(4, "failed while trying to open %s -- %s", path,
  131.                                 strerror(errno));
  132.        
  133.         /* seek to the appropriate place */
  134.         if (fseek(fp, (vaddr / psize) * sizeof(uint64_t), SEEK_CUR) == -1)
  135.                 errx(5, "failed while trying to seek in pagemap -- %s",
  136.                                 strerror(errno));
  137.  
  138.         /* read the corresponding pagemap entry */
  139.         if (fread(&pentry, sizeof(uint64_t), 1, fp) != 1) {
  140.                 if (ferror(fp))
  141.                         errx(6,
  142.                         "failed while trying to read a pagemap entry -- %s",
  143.                         strerror(errno));
  144.                 else
  145.                 errx(6,
  146.                 "unknown error while trying to read a pagemap entry -- %s",
  147.                         strerror(errno));
  148.         }
  149.  
  150.         /* check the present bit */
  151.         if ((pentry & PRESENT_MASK) == 0)
  152.                 warnx("%#lx is not present in physical memory", vaddr);
  153.         else
  154.                 (void)fprintf(stdout,
  155.                                 "PFN[%#lx]: %llu\n", vaddr, pentry & PFN_MASK);
  156.  
  157.         /* cleanup */
  158.         (void)fclose(fp);
  159. }
  160.  
  161. /*
  162.  * getPAGEMAP
  163.  *
  164.  * read the pagemap of a particular process
  165.  *
  166.  * @argc:       number of command-line options
  167.  * @argv:       command-line options
  168.  * return       0: success
  169.  *              1: illegal option, missing argument
  170.  *              2: failed while trying to read the page size
  171.  *              3: invalid pid or virt parameter
  172.  *              4: failed while trying to open /proc/<pid>/pagemap
  173.  *              5: failed while trying to seek in /proc/<pid>/pagemap
  174.  *              6: failed while trying to read a pagemap entry
  175.  */
  176. int
  177. main(int argc, char **argv)
  178. {
  179.         long            psize;          /* page size            */
  180.         pid_t           pid     = -1;   /* pid                  */
  181.         unsigned long   vaddr   = 0;    /* virtual address      */
  182.  
  183.         /* getopt stuff */
  184.         int             opt;            /* option               */
  185.         int     long_opt_indx   = 0;    /* long option index    */
  186.  
  187.         /* long options */
  188.         struct option long_options[] = {
  189.                 {"pid",         1, NULL, 'p'},  /* -p / --pid           */
  190.                 {"virt",        1, NULL, 'a'},  /* -a / --virt          */
  191.                 {"help",        0, NULL, 'h'},  /* -h / --help          */
  192.                 {"version",     0, NULL, 'v'},  /* -v / --version       */
  193.                 {NULL,          0, NULL, 0}};   /* terminating item     */
  194.        
  195.         /* arguments parsing */
  196.         while ((opt = getopt_long(argc, argv, ":hvp:a:", long_options,
  197.                                                 &long_opt_indx)) != -1) {
  198.                 switch(opt) {
  199.                         case 'p': /* -p / --pid */
  200.                                 pid     = (pid_t)strtol(optarg, NULL, BASE10);
  201.                                 break;
  202.                         case 'a': /* -a / --virt */
  203.                                 vaddr   = (unsigned long)strtoll(optarg, NULL,
  204.                                                 BASE16);
  205.                                 break;
  206.                         case 'h': /* help */
  207.                                 help();
  208.                                 goto done;
  209.                                 break;  /* not reached */
  210.                         case 'v': /* version info */
  211.                                 version();
  212.                                 goto done;
  213.                                 break;  /* not reached */
  214.                         case '?': /* illegal option */
  215.                                 errx(1, "illegal option -- %s",
  216.                                                 (optind == 0) ?
  217.                                                 argv[long_opt_indx] :
  218.                                                 argv[optind - 1]);
  219.                                 break;
  220.                         case ':': /* missing argument */
  221.                                 errx(1, "option requires an argument -- %s",
  222.                                                 (optind == 0) ?
  223.                                                 argv[long_opt_indx] :
  224.                                                 argv[optind - 1]);
  225.                                 break;
  226.                         default: /* not reached */
  227.                                 break; /* make the compiler happy */
  228.                 }
  229.         }
  230.        
  231.         /* get the page size */
  232.         if ((psize = sysconf(_SC_PAGESIZE)) == -1)
  233.                 errx(2, "failed while trying to read page size -- %s",
  234.                                 strerror(errno));
  235.        
  236.         /* validate arguments */
  237.         if (pid == -1)
  238.                 /* pid is missing */
  239.                 errx(3, "missing `pid' argument");
  240.         if (pid <= 0)
  241.                 /* invalid pid value */
  242.                 errx(3, "invalid `pid' argument -- %d", pid);
  243.  
  244.         /* check if the virtual address is page-aligned */
  245.         if ((vaddr & (psize - 1)) != 0) {
  246.                 /* verbose */
  247.         warnx("virtual address %#lx is not page-aligned; converting to %#lx",
  248.                 vaddr, vaddr & (ULONG_MAX - (psize - 1)));
  249.                 /* fix the virtual address */
  250.                 vaddr &= ULONG_MAX - (psize - 1);
  251.         }
  252.  
  253.         /* query pagemap */
  254.         querypmap(pid, vaddr, psize);
  255.        
  256. done:   /* done; return with success */
  257.         return EXIT_SUCCESS;
  258. }

Paste is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.