/branches/swig-2.0/Tools/WAD/Wad/segment.c

# · C · 227 lines · 129 code · 33 blank · 65 comment · 23 complexity · b713a363539f8f3ad98e9a81b846084c MD5 · raw file

  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. #include "wad.h"
  33. static char cvs[] = "$Id: segment.c 10001 2007-10-17 21:33:57Z wsfulton $";
  34. /* Include the proper code for reading the segment map */
  35. #ifdef WAD_SOLARIS
  36. /* This code is used to read the process virtual memory map on Solaris machines */
  37. static int
  38. segment_open() {
  39. int f;
  40. f = open("/proc/self/map", O_RDONLY);
  41. return f;
  42. }
  43. static int
  44. segment_read(int fs, WadSegment *s) {
  45. int dz;
  46. int n;
  47. prmap_t pmap;
  48. n = read(fs, &pmap, sizeof(prmap_t));
  49. if (n <= 0) return 0;
  50. s->mapname = wad_strdup(pmap.pr_mapname);
  51. s->mappath = (char *) wad_malloc(20+strlen(pmap.pr_mapname));
  52. wad_strcpy(s->mappath,"/proc/self/object/");
  53. strcat(s->mappath,pmap.pr_mapname);
  54. s->vaddr = (char *) pmap.pr_vaddr;
  55. /* This is a solaris oddity. a.out section starts 1 page up, but
  56. symbols are relative to a base of 0 */
  57. if (strcmp(s->mapname,"a.out") == 0) s->base = 0;
  58. else s->base = s->vaddr;
  59. s->size = pmap.pr_size;
  60. s->offset = pmap.pr_offset;
  61. return 1;
  62. }
  63. #endif /* WAD_SOLARIS */
  64. #ifdef WAD_LINUX
  65. static char linux_firstsegment[1024];
  66. static int linux_first = 1;
  67. static int
  68. segment_open() {
  69. FILE *f;
  70. f = fopen("/proc/self/maps", "r");
  71. linux_first =1;
  72. return (int) f;
  73. }
  74. static int
  75. segment_read(int fd, WadSegment *s)
  76. {
  77. char pbuffer[1024];
  78. char *c;
  79. int len;
  80. FILE *fs = (FILE *) fd;
  81. c = fgets(pbuffer,1024,fs);
  82. if (!c) return 0;
  83. pbuffer[strlen(pbuffer)-1] = 0; /* Chop off endline */
  84. /* Break up the field into records */
  85. /* 0-8 : Starting address
  86. 9-17 : Ending Address
  87. 18 : r
  88. 19 : w
  89. 20 : x
  90. 21 : p
  91. 23-31 : Offset
  92. 49- : Filename */
  93. len = strlen(pbuffer);
  94. pbuffer[8] = 0;
  95. pbuffer[17] = 0;
  96. pbuffer[31] = 0;
  97. if (len >= 49) {
  98. s->mapname = wad_strdup(pbuffer+49);
  99. s->mappath = s->mapname;
  100. } else {
  101. s->mapname = "";
  102. s->mappath = s->mapname;
  103. }
  104. if (linux_first) {
  105. wad_strcpy(linux_firstsegment, s->mappath);
  106. linux_first = 0;
  107. }
  108. s->vaddr = (char *) strtoul(pbuffer,NULL,16);
  109. s->size = strtoul(pbuffer+9,NULL,16) - (long) (s->vaddr);
  110. s->offset = strtoul(pbuffer+23,NULL,16);
  111. if (strcmp(linux_firstsegment, s->mappath) == 0) {
  112. s->base = 0;
  113. } else {
  114. s->base = s->vaddr;
  115. }
  116. s++;
  117. return 1;
  118. }
  119. #endif /* WAD_LINUX */
  120. static WadSegment *segments = 0; /* Linked list of segments */
  121. /* -----------------------------------------------------------------------------
  122. * wad_segment_read()
  123. *
  124. * Read all of the memory segments into a linked list. Any previous segment
  125. * map is simply lost. The only way to reclaim this memory is to call
  126. * wad_release_memory().
  127. * ----------------------------------------------------------------------------- */
  128. int
  129. wad_segment_read() {
  130. int fs;
  131. int n;
  132. WadSegment *s, *lasts;
  133. segments = 0;
  134. lasts = 0;
  135. fs = segment_open();
  136. while (1) {
  137. s = (WadSegment *) wad_malloc(sizeof(WadSegment));
  138. skip:
  139. n = segment_read(fs,s);
  140. if (n <= 0) break;
  141. if (wad_file_check(s->vaddr)) goto skip; /* Skip files we already loaded */
  142. s->next = 0;
  143. if (!lasts) {
  144. segments = s;
  145. lasts = s;
  146. } else {
  147. lasts->next = s;
  148. lasts = s;
  149. }
  150. if (wad_debug_mode & DEBUG_SEGMENT) {
  151. wad_printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
  152. }
  153. }
  154. close(fs);
  155. return 0;
  156. }
  157. /* -----------------------------------------------------------------------------
  158. * wad_segment_find()
  159. *
  160. * Try to find the virtual memory segment corresponding to a virtual address.
  161. * If a segment is mapped to a file, this function actually returns the *first*
  162. * segment that is mapped. This is because symbol relocations are always
  163. * performed relative to the beginning of the file (so we need the base address)
  164. * ----------------------------------------------------------------------------- */
  165. WadSegment *
  166. wad_segment_find(void *vaddr) {
  167. WadSegment *ls;
  168. WadSegment *s;
  169. char *addr = (char *)vaddr;
  170. s = segments;
  171. ls = segments;
  172. while (s) {
  173. if (strcmp(s->mapname,ls->mapname) || (!strlen(ls->mapname))) {
  174. ls = s; /* First segment for a given name */
  175. }
  176. if ((addr >= s->vaddr) && (addr < (s->vaddr + s->size))) {
  177. if (wad_debug_mode & DEBUG_SEGMENT) {
  178. wad_printf("wad_segment: %08x --> %08x-%08x in %s\n", vaddr, s->vaddr, ((char *) s->vaddr) + s->size, s->mappath);
  179. }
  180. return ls;
  181. }
  182. s = s->next;
  183. }
  184. return 0;
  185. }
  186. /* -----------------------------------------------------------------------------
  187. * wad_segment_valid()
  188. *
  189. * Checks to see if a memory address is valid or not based on data in the
  190. * segment map
  191. * ----------------------------------------------------------------------------- */
  192. int wad_segment_valid(void *vaddr) {
  193. return wad_segment_find(vaddr) ? 1 : 0;
  194. }