Add column headers to output
[pagetables.git] / pagetables.c
1 /*
2    Generate readable C-source structures from binary page-table arrays found in hboot images
3    Copyright (C) 2010 TJ
4    Author: TJ <linux@tjworld.net>
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, version 3 of the License.
9
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.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/mman.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <string.h>
28
29 void
30 usage(const char *name) {
31  printf("Usage: %s:  [-d -f <pagetable>\n", name);
32  printf("Copyright 2010 TJ <linux@tjworld.net>\n"
33         "Licensed under the terms of the GNU GPL v3\n\n"
34         "\t-d\tprint addresses in decimal not hexadecimal\n"
35         "\t-f\tpath to the file containing the needle\n\n"
36
37         "\tInformation messages are written to stderr and only matches are written to stdout.\n"
38         "\tThis allows the output to be piped through other filters.\n"
39  );
40 }
41
42 int
43 main(int argc, char *argv[], char *env[]) {
44  int ret = 0;
45  int c, use_decimal, pagetable_fd;
46  char *pagetable_name;
47  void *pagetable_mmap;
48  struct stat pagetable_stat;
49
50  pagetable_name = pagetable_mmap = NULL;
51  use_decimal = 0;
52
53  if (argc > 1) { // must have some parameters
54   opterr = 0;
55
56   while ((c = getopt(argc, argv, "f:d")) != -1 ) { // iterate the options
57    switch(c) {
58     case 'f':
59      pagetable_name = optarg;
60      break;
61     case 'd':
62      use_decimal = 1;
63      break;
64     default:
65      abort();
66    }
67   }
68
69   if ((pagetable_fd = open(pagetable_name, O_RDONLY)) == -1) {
70    perror("Unable to open pagetable");
71    ret |= 1;
72   }
73
74   
75   if (!ret) {
76    fstat(pagetable_fd, &pagetable_stat);
77    fprintf(stderr, "Base:\t%s\n", use_decimal == 1 ? "decimal" : "hexadecimal");
78    fprintf(stderr, "Pagetable:\t\t%12ld\t%s\n", pagetable_stat.st_size, pagetable_name);
79
80    if(MAP_FAILED == (pagetable_mmap = mmap(pagetable_mmap, pagetable_stat.st_size, PROT_READ, MAP_SHARED, pagetable_fd, 0))) {
81     perror("Unable to memory-map pagetable");
82     exit(4);
83    }
84    {
85     void *f = pagetable_mmap; // convenient short names
86     unsigned long offset;
87     unsigned long end = pagetable_stat.st_size;
88     unsigned int virtual;
89     unsigned int physical;
90     unsigned int count;
91     fprintf(stderr, "Processing...\n"
92                     " Virtual     Physical    Count\n");
93     for (offset = 0; offset <= end; offset += 12) {
94      virtual = *(unsigned int *)(f + offset);
95      physical = *(unsigned int *)(f + offset + 4);
96      count = *(unsigned int *)(f + offset + 8);
97      if (use_decimal) fprintf(stdout, "{%010u, %010u, %010u},\n", virtual, physical, count);
98      else fprintf(stdout, "{0x%08X, 0x%08X, 0x%08X},\n", virtual, physical, count);
99     }
100     fprintf(stderr, "Done.\n");
101    }
102   }
103  }
104  else
105   usage(argv[0]);
106
107  if (pagetable_mmap > 0) munmap(pagetable_mmap, pagetable_stat.st_size);
108  if (pagetable_fd > 0) close(pagetable_fd);
109
110  return ret;
111 }