import source from 1.3.40
[external/swig.git] / Tools / WAD / Wad / segment.c
1 /* ----------------------------------------------------------------------------- 
2  * segment.c
3  *
4  *     This file provides access to the virtual memory map of a process
5  *     including the location of the executable, data segments, shared
6  *     libraries, and memory mapped regions. 
7  *
8  *     The primary purpose of this module is to collect this information
9  *     and store it in a form that hides platform specific details (the
10  *     WadSegment structure).
11  * 
12  * Author(s) : David Beazley (beazley@cs.uchicago.edu)
13  *
14  * Copyright (C) 2000.  The University of Chicago. 
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  * 
30  * See the file COPYING for a complete copy of the LGPL.
31  * ----------------------------------------------------------------------------- */
32
33 #include "wad.h"
34
35 static char cvs[] = "$Id: segment.c 10001 2007-10-17 21:33:57Z wsfulton $";
36
37 /* Include the proper code for reading the segment map */
38
39 #ifdef WAD_SOLARIS
40
41 /* This code is used to read the process virtual memory map on Solaris machines */
42
43 static int
44 segment_open() {
45   int f;
46   f = open("/proc/self/map", O_RDONLY);
47   return f;
48 }
49
50 static int
51 segment_read(int fs, WadSegment *s) {
52   int     dz;
53   int     n;
54   prmap_t pmap;
55
56   n = read(fs, &pmap, sizeof(prmap_t));
57   if (n <= 0) return 0;
58   s->mapname = wad_strdup(pmap.pr_mapname);
59   s->mappath = (char *) wad_malloc(20+strlen(pmap.pr_mapname));
60   wad_strcpy(s->mappath,"/proc/self/object/");
61   strcat(s->mappath,pmap.pr_mapname);
62   s->vaddr = (char *) pmap.pr_vaddr;
63
64   /* This is a solaris oddity.  a.out section starts 1 page up, but
65      symbols are relative to a base of 0 */
66
67   if (strcmp(s->mapname,"a.out") == 0) s->base = 0;
68   else s->base = s->vaddr;
69
70   s->size  = pmap.pr_size;
71   s->offset = pmap.pr_offset;
72   return 1;
73 }
74
75 #endif           /* WAD_SOLARIS */
76
77 #ifdef WAD_LINUX
78 static char linux_firstsegment[1024];
79 static int linux_first = 1;
80
81 static int
82 segment_open() {
83   FILE *f;
84   f = fopen("/proc/self/maps", "r");
85   linux_first =1;
86   return (int) f;
87 }
88
89 static int 
90 segment_read(int fd, WadSegment *s)
91 {
92   char pbuffer[1024];
93   char *c;
94   int  len;
95   FILE *fs = (FILE *) fd;
96   c = fgets(pbuffer,1024,fs);
97   if (!c) return 0;
98
99   pbuffer[strlen(pbuffer)-1] = 0;   /* Chop off endline */
100
101   /* Break up the field into records */
102   /*    0-8       : Starting address
103         9-17      : Ending Address
104         18        : r
105         19        : w
106         20        : x
107         21        : p
108         23-31     : Offset 
109         49-       : Filename */
110
111   len = strlen(pbuffer);
112   pbuffer[8] = 0;
113   pbuffer[17] = 0;
114   pbuffer[31] = 0;
115   if (len >= 49) {
116     s->mapname = wad_strdup(pbuffer+49);
117     s->mappath = s->mapname;
118   }  else {
119     s->mapname = "";
120     s->mappath = s->mapname;
121   }
122   if (linux_first) {
123     wad_strcpy(linux_firstsegment, s->mappath);
124     linux_first = 0;
125   }
126   s->vaddr = (char *) strtoul(pbuffer,NULL,16);
127   s->size = strtoul(pbuffer+9,NULL,16) - (long) (s->vaddr);
128   s->offset = strtoul(pbuffer+23,NULL,16);
129   if (strcmp(linux_firstsegment, s->mappath) == 0) {
130     s->base = 0;
131   } else {
132     s->base = s->vaddr;
133   }
134   s++;
135   return 1;
136 }
137
138 #endif   /* WAD_LINUX */
139
140 static WadSegment    *segments = 0;   /* Linked list of segments */
141
142 /* ----------------------------------------------------------------------------- 
143  * wad_segment_read()
144  *
145  * Read all of the memory segments into a linked list.  Any previous segment
146  * map is simply lost.  The only way to reclaim this memory is to call
147  * wad_release_memory().
148  * ----------------------------------------------------------------------------- */
149
150 int
151 wad_segment_read() {
152   int         fs;
153   int         n;
154   WadSegment *s, *lasts;
155
156   segments = 0;
157   lasts = 0;
158   fs = segment_open();
159
160   while (1) {
161     s = (WadSegment *) wad_malloc(sizeof(WadSegment));    
162   skip:
163     n = segment_read(fs,s);
164     if (n <= 0) break;
165     if (wad_file_check(s->vaddr)) goto skip;  /* Skip files we already loaded */
166     s->next = 0;
167     if (!lasts) {
168       segments = s;
169       lasts = s;
170     } else {
171       lasts->next = s;
172       lasts = s;
173     }
174     if (wad_debug_mode & DEBUG_SEGMENT) {
175       wad_printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
176     }
177   }
178   close(fs);
179   return 0;
180 }
181
182 /* -----------------------------------------------------------------------------
183  * wad_segment_find()
184  *
185  * Try to find the virtual memory segment corresponding to a virtual address.
186  * If a segment is mapped to a file, this function actually returns the *first*
187  * segment that is mapped.   This is because symbol relocations are always
188  * performed relative to the beginning of the file (so we need the base address)
189  * ----------------------------------------------------------------------------- */
190
191 WadSegment *
192 wad_segment_find(void *vaddr) {
193   WadSegment *ls;
194   WadSegment *s;
195   char *addr = (char *)vaddr;
196
197   s = segments;
198   ls = segments;
199   while (s) {
200     if (strcmp(s->mapname,ls->mapname) || (!strlen(ls->mapname))) {
201       ls = s;    /* First segment for a given name */
202     }
203     if ((addr >= s->vaddr) && (addr < (s->vaddr + s->size))) {
204       if (wad_debug_mode & DEBUG_SEGMENT) {
205         wad_printf("wad_segment: %08x --> %08x-%08x in %s\n", vaddr, s->vaddr, ((char *) s->vaddr) + s->size, s->mappath);
206       }
207       return ls;
208     }
209     s = s->next;
210   }
211   return 0;
212 }
213
214 /* -----------------------------------------------------------------------------
215  * wad_segment_valid()
216  *
217  * Checks to see if a memory address is valid or not based on data in the
218  * segment map 
219  * ----------------------------------------------------------------------------- */
220
221 int wad_segment_valid(void *vaddr) {
222   return wad_segment_find(vaddr) ? 1 : 0;
223 }
224
225
226
227