gdb-blocks.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* gdb_block.c - Deal with GDB blocks
  2. Copyright (C) 1987 Free Software Foundation, Inc.
  3. This file is part of GAS, the GNU Assembler.
  4. GAS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8. GAS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GAS; see the file COPYING. If not, write to
  14. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. /*
  16. * Implements .gdbblk, .gdbbeg, .gdbend concepts.
  17. * No other modules need to know the details of these concepts.
  18. *
  19. * During assembly, note the addresses of block beginnings and ends.
  20. * Each block has a begin-address, an end-address, a number, and
  21. * a place in the GDB symbol file to place the 2 addresses.
  22. * Block numbers are 0, 1, ... with no gaps.
  23. *
  24. * During assembly, we don't actually know the addresses, so they are
  25. * expressed as {frag-address + offset-in-frag}.
  26. *
  27. * gdb_block_begin ()
  28. * Call once before using this package.
  29. *
  30. * gdb_block_beg (number, frag, offset)
  31. * Note a block beginning.
  32. *
  33. * gdb_block_end (number, frag, offset)
  34. * Note a block end.
  35. *
  36. * gdb_block_position (block_number, pos)
  37. * Remember, after assembly, to copy a structure containing
  38. * the beginning and ending addresses of block number
  39. * block_number into the gdb file, starting at position pos.
  40. *
  41. * gdb_block_emit (block_number, where_in_gdb_symbol_file)
  42. * Emit a block begin/end locations to a place in the GDB symbol
  43. * file.
  44. *
  45. * uses:
  46. * xmalloc()
  47. * gdb_alter()
  48. */
  49. #include "as.h"
  50. /*
  51. * malloc() calls are considered expensive. So ...
  52. *
  53. * We remember blocks by making a tree, and each block number has a leaf.
  54. * The tree is 3 levels, and we don't allocate interior nodes until they
  55. * are needed. Both leaves and interior nodes are allocated in lumps,
  56. * which should save on malloc() calls. Due to the way we break up a
  57. * block number to navigate through the tree, we insist that lumps of
  58. * memory contain a power of 2 items each. Powers of 2 may differ
  59. * for different levels of tree.
  60. */
  61. /*
  62. * A block number:
  63. *
  64. * +---------------+---------------+---------------+
  65. * | | | |
  66. * | Z2-part bits | Z1-part bits | Z0-part bits |
  67. * | | | |
  68. * +---------------+---------------+---------------+
  69. *
  70. * High order Low order
  71. *
  72. * "Z" is short for "siZe".
  73. */
  74. #define LOG_2_Z0 (8) /* How many bits are in Z0 part? */
  75. #define LOG_2_Z1 (8) /* How many bits are in Z1 part? */
  76. #define LOG_2_Z2 (8) /* How many bits are in Z2 part? */
  77. #define BLOCK_NUMBER_LIMIT (1 << (LOG_2_Z0 + LOG_2_Z1 + LOG_2_Z2))
  78. /* What is the first block number that is */
  79. /* "too big"? */
  80. struct gdb_block
  81. {
  82. fragS * begin_frag;
  83. fragS * end_frag;
  84. long int begin_where_in_frag;
  85. long int end_where_in_frag;
  86. long int position; /* In GDB symbols file. */
  87. };
  88. typedef struct gdb_block node_0_T [1 << LOG_2_Z0];
  89. typedef node_0_T * node_1_T [1 << LOG_2_Z1];
  90. typedef node_1_T * node_2_T [1 << LOG_2_Z2];
  91. static long int highest_block_number_seen;
  92. static node_2_T * root; /* 3 level tree of block locations. */
  93. static node_2_T * new_2 ();
  94. char * xmalloc();
  95. void gdb_alter();
  96. void
  97. gdb_block_begin ()
  98. {
  99. root = new_2 ();
  100. highest_block_number_seen = -1;
  101. }
  102. static node_0_T *
  103. new_0 ()
  104. {
  105. register node_0_T * place;
  106. place = (node_0_T *) xmalloc ((long)sizeof(node_0_T));
  107. bzero ((char *)place, sizeof(node_0_T));
  108. return (place);
  109. }
  110. static node_1_T *
  111. new_1 ()
  112. {
  113. register node_1_T * place;
  114. place = (node_1_T *) xmalloc ((long)sizeof(node_1_T));
  115. bzero ((char *)place, sizeof(node_1_T));
  116. return (place);
  117. }
  118. static node_2_T *
  119. new_2 ()
  120. {
  121. register node_2_T * place;
  122. place = (node_2_T *) xmalloc ((long)sizeof(node_2_T));
  123. bzero ((char *)place, sizeof(node_2_T));
  124. return (place);
  125. }
  126. static struct gdb_block *
  127. find (block_number)
  128. register long int block_number;
  129. {
  130. register node_1_T ** pp_1;
  131. register node_0_T ** pp_0;
  132. register struct gdb_block * b;
  133. register int index0;
  134. register int index1;
  135. register int index2;
  136. #ifdef SUSPECT
  137. if (block_number >= BLOCK_NUMBER_LIMIT)
  138. {
  139. as_fatal ("gdb_block: Block number = %ld.", block_number);
  140. }
  141. #endif
  142. index2 = block_number >> (LOG_2_Z0 + LOG_2_Z1);
  143. index1 = block_number >> (LOG_2_Z0) & ((1 << LOG_2_Z1) - 1);
  144. index0 = block_number & ((1 << LOG_2_Z0) - 1);
  145. pp_1 = * root + index2;
  146. if (* pp_1 == 0)
  147. {
  148. * pp_1 = new_1 ();
  149. }
  150. pp_0 = ** pp_1 + index1;
  151. if (* pp_0 == 0)
  152. {
  153. * pp_0 = new_0 ();
  154. }
  155. b = ** pp_0 + index0;
  156. return (b);
  157. }
  158. static struct gdb_block *
  159. find_create (block_number)
  160. long int block_number;
  161. {
  162. if (highest_block_number_seen < block_number)
  163. {
  164. highest_block_number_seen = block_number;
  165. }
  166. return (find (block_number));
  167. }
  168. void
  169. gdb_block_beg (block_number, frag, offset)
  170. long int block_number;
  171. fragS * frag;
  172. long int offset;
  173. {
  174. struct gdb_block * pointer;
  175. pointer = find_create (block_number);
  176. #ifdef SUSPECT
  177. if (pointer -> begin_frag != 0)
  178. {
  179. as_warn( "Overwriting begin_frag for block # %ld.", block_number );
  180. }
  181. if (pointer -> begin_where_in_frag != 0)
  182. {
  183. as_warn( "Overwriting begin_where_in_frag for block # %ld.", block_number );
  184. }
  185. #endif
  186. pointer -> begin_frag = frag;
  187. pointer -> begin_where_in_frag = offset;
  188. }
  189. void
  190. gdb_block_end (block_number, frag, offset)
  191. long int block_number;
  192. fragS * frag;
  193. long int offset;
  194. {
  195. struct gdb_block * pointer;
  196. pointer = find_create (block_number);
  197. #ifdef SUSPECT
  198. if (pointer -> end_frag != 0)
  199. {
  200. as_warn( "Overwriting end_frag for block # %ld.", block_number );
  201. }
  202. if (pointer -> end_where_in_frag != 0)
  203. {
  204. as_warn( "Overwriting end_where_in_frag for block # %ld.", block_number );
  205. }
  206. #endif
  207. pointer -> end_frag = frag;
  208. pointer -> end_where_in_frag = offset;
  209. }
  210. void
  211. gdb_block_position (block_number, pos)
  212. long int block_number;
  213. long int pos;
  214. {
  215. struct gdb_block * pointer;
  216. pointer = find_create (block_number);
  217. if (pointer -> position != 0)
  218. {
  219. as_warn( "Overwriting old position %ld. in block #%ld.",
  220. pointer -> position, block_number);
  221. }
  222. pointer -> position = pos;
  223. }
  224. void
  225. gdb_block_emit ()
  226. {
  227. long int block_number;
  228. struct gdb_block * b;
  229. for (block_number = 0;
  230. block_number <= highest_block_number_seen;
  231. block_number ++)
  232. {
  233. b = find (block_number);
  234. if (b -> begin_frag)
  235. {
  236. gdb_alter (b -> position,
  237. (long int)
  238. (b -> begin_frag -> fr_address + b -> begin_where_in_frag));
  239. }
  240. if (b -> end_frag)
  241. {
  242. gdb_alter (b -> position + sizeof( long int ),
  243. (long int)
  244. (b -> end_frag -> fr_address + b -> end_where_in_frag));
  245. }
  246. }
  247. }
  248. /* end: gdb_block.c */