Fixed multi-archness of the `demo' script.
[libobjid.git] / maps.c
1 /* $Id$ */
2
3
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <asm/page.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "maps.h"
13 #include "common.h"
14 #include "hook.h"
15
16
17 struct range
18   {
19     void *start;
20     void *end;
21   };
22 /* FIXME: Dynamic allocation.  */
23 static struct range ranges[PAGE_SIZE * 8 / sizeof (struct range)];
24 static struct range *ranges_static_end = ranges;
25 static struct range *ranges_end = ranges;       /* = ranges_static_end */
26
27
28 /* Returns 0 on readable start..end-1.  */
29 /* TODO: Sort + binary search.  */
30 INTERNAL int maps_verify (void *start, void *end)
31 {
32   int changed;
33
34   do
35     {
36       struct range *range;
37
38       changed = 0;
39       for (range = ranges; start < end && range < ranges_end; range++)
40         if (start >= range->start && start < range->end)
41           {
42             start = range->end;
43             changed = 1;
44           }
45     }
46   while (start < end && changed);
47
48   if (start < end)
49     return -1;
50   /* Success.  */
51   return 0;
52 }
53
54 INTERNAL void maps_static_setup (void *start, void *end)
55 {
56   if (ranges_static_end >= ranges + N_ELEMENTS (ranges))
57     return;
58
59   ranges_static_end->start = start;
60   ranges_static_end->end = end;
61   ranges_static_end++;
62
63   if (debug >= 1)
64     fprintf (stderr,"static: %p - %p\n", start, end);
65 }
66
67 INTERNAL void maps_read (void)
68 {
69   int fd;
70   ssize_t bytes_read;
71   char *s;
72
73   /* Reset.  */
74   ranges_end = ranges_static_end;
75
76   /* Do not use level 3 I/O as it may be too SIGSEGV intrusive.  */
77   fd = open (MAPS_FILENAME, O_RDONLY);
78   if (fd == -1)
79     return;
80   bytes_read = read (fd, ranges_end, (char *) ranges + sizeof (ranges)
81                                      - (char *) ranges_end - 1);
82   if (close (fd))
83     return;
84   if (bytes_read <= 0)
85     return;
86   s = (char *) ranges_end;
87   s[bytes_read] = 0;
88
89   while (*s)
90     {
91       unsigned long start, end;
92       char prot_read, prot_write, prot_exec, prot_mayshare;
93       int offset, i;
94       const char *vdso_name = " [vdso]";
95       const size_t vdso_len = strlen (vdso_name);
96
97       i = sscanf (s, "%lx-%lx %c%c%c%c %n", &start, &end, &prot_read,
98                   &prot_write, &prot_exec, &prot_mayshare, &offset);
99       if (i != 6)
100         break;
101       s += offset;
102       /* Reuse the trailing absolute pathname?
103          Currently we use the relative one from dl_iterate_phdr(3).  */
104       while (*s && *s != '\n')
105         s++;
106       /* Skip [vdso] entry to discard its dl_iterate_phdr(3) which has the
107          same name as the main executable - "".  */
108       if (s >= (char *) ranges + vdso_len
109           && memcmp (s - vdso_len, vdso_name, vdso_len) == 0)
110         continue;
111       if (prot_read != 'r')
112         continue;
113       if (prot_write != '-')
114         continue;
115       if (prot_exec != 'x')
116         continue;
117       if (prot_mayshare != 'p')
118         continue;
119       ranges_end->start = (void *) start;
120       ranges_end->end = (void *) end;
121       ranges_end++;
122
123       if (debug >= 1)
124         fprintf (stderr,"range: %p - %p\n", (void *) start, (void *) end);
125
126       if (ranges_end >= ranges + N_ELEMENTS (ranges))
127         return;
128     }
129 }