position.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* $Header$ */
  2. #include <stdio.h>
  3. #include <assert.h>
  4. #include <alloc.h>
  5. #include <out.h>
  6. #include <stb.h>
  7. #include "position.h"
  8. #include "scope.h"
  9. #include "file.h"
  10. #include "idf.h"
  11. #include "symbol.h"
  12. extern FILE *db_out;
  13. static p_file mapping;
  14. static int nfiles = 0;
  15. /* static p_file get_map_from_addr(t_addr t);
  16. Returns the file entry that contains the code at the address 't',
  17. or 0 if there is no information available, or 't' represents an address
  18. below the start address of the first file.
  19. */
  20. static p_file
  21. get_map_from_addr(t)
  22. t_addr t;
  23. {
  24. register p_file p = mapping, oldp = 0;
  25. /* linear search is probably acceptable here */
  26. while (p && p->f_start->on_valu <= t) {
  27. oldp = p;
  28. p = p->f_nextmap;
  29. }
  30. return oldp ? oldp : p->f_start->on_valu <= t ? p : 0;
  31. }
  32. /* extern char *get_filename_from_addr(t_addr t);
  33. Returns the source filename that contains the code at the address 't',
  34. or 0 if there is no information available, or 't' represents an address
  35. below the start address of the first file.
  36. */
  37. char *
  38. get_filename_from_addr(t)
  39. t_addr t;
  40. {
  41. register p_file map = get_map_from_addr(t);
  42. if (! map) return 0;
  43. return map->f_sym->sy_idf->id_text;
  44. }
  45. /* extern t_lineno get_lineno_from_addr(t_addr t);
  46. Returns the source line number of the line that contains the code at address
  47. 't'. 0 is returned if no source line number could be found.
  48. */
  49. t_lineno
  50. get_lineno_from_addr(t)
  51. t_addr t;
  52. {
  53. p_position p;
  54. p = get_position_from_addr(t);
  55. return p == 0 ? 0 : p->lineno;
  56. }
  57. /* extern p_position get_position_from_addr(t_addr t);
  58. Returns a pointer to a structure containing the source position of the code
  59. at address 't'. 0 is returned if no source position could be found.
  60. */
  61. p_position
  62. get_position_from_addr(t)
  63. t_addr t;
  64. {
  65. register p_file map = get_map_from_addr(t);
  66. static t_position retval;
  67. register int i,j,m;
  68. if (! map) return 0;
  69. i = 0;
  70. j = map->f_end - map->f_start;
  71. do {
  72. m = ((i + j) >> 1) + ((i + j) & 1);
  73. while ((map->f_start[m].on_type >> 8) != N_SLINE) m++;
  74. assert(m <= j);
  75. if (map->f_start[m].on_valu > t) {
  76. j = m - 1;
  77. while (j > i && (map->f_start[j].on_type >> 8) != N_SLINE) j--;
  78. }
  79. else i = m;
  80. } while (i < j);
  81. retval.filename = map->f_sym->sy_idf->id_text;
  82. retval.lineno = map->f_start[j].on_desc;
  83. return &retval;
  84. }
  85. /* extern t_addr get_addr_from_position(p_position p);
  86. Returns the address of the code at position 'p', or ILL_ADDR if it could
  87. not be found. If there is no symbolic information for the filename in
  88. position 'p', an error message will be given.
  89. */
  90. t_addr
  91. get_addr_from_position(p)
  92. p_position p;
  93. {
  94. register p_symbol sym = Lookup(findidf(p->filename), PervasiveScope, FILESYM);
  95. if (sym) {
  96. register unsigned int i;
  97. register p_file map = sym->sy_file;
  98. for (i = p->lineno; i > 0; i--) {
  99. register struct outname *n = map->f_line_addr[HASH(i)];
  100. while (n) {
  101. if (n->on_desc == i) return (t_addr) n->on_valu;
  102. n = next_outname(n);
  103. }
  104. }
  105. return ILL_ADDR;
  106. }
  107. error("no symbolic information for file %s", p->filename);
  108. return ILL_ADDR;
  109. }
  110. /* extern add_position_addr(char *filename, struct outname *n);
  111. Adds the ('filename','lineno'),'t' pair to the mapping information.
  112. */
  113. add_position_addr(filename, n)
  114. char *filename;
  115. register struct outname *n;
  116. {
  117. static char *lastfile = 0;
  118. static p_file lastmap = 0;
  119. register p_file map = lastmap;
  120. if (filename != lastfile) { /* new file ... */
  121. register p_symbol sym;
  122. nfiles++;
  123. lastfile = filename;
  124. if (! filename) { /* last call */
  125. return;
  126. }
  127. sym = Lookup(findidf(filename), PervasiveScope, FILESYM);
  128. if (sym) map = sym->sy_file;
  129. else {
  130. sym = add_file(filename);
  131. map = sym->sy_file;
  132. map->f_scope = FileScope;
  133. }
  134. if (! mapping) mapping = map;
  135. else lastmap->f_nextmap = map;
  136. lastmap = map;
  137. map->f_start = n;
  138. }
  139. else map = lastmap;
  140. map->f_end = n;
  141. setnext_outname(n, map->f_line_addr[HASH(n->on_desc)]);
  142. map->f_line_addr[HASH(n->on_desc)] = n;
  143. }
  144. /* extern struct scope *get_scope_from_position(p_position p);
  145. Returns the scope of the code at position 'p', or 0 if it could not be found.
  146. */
  147. struct scope *
  148. get_scope_from_position(p)
  149. p_position p;
  150. {
  151. t_addr a = get_addr_from_position(p);
  152. if (a != ILL_ADDR) {
  153. return get_scope_from_addr(a);
  154. }
  155. return 0;
  156. }
  157. /* extern p_position print_position(t_addr a, int print_function);
  158. Prints position 'a' and returns it. If 'print_function' is set,
  159. an attempt is made to print the function name as well.
  160. */
  161. p_position
  162. print_position(a, print_function)
  163. t_addr a;
  164. int print_function;
  165. {
  166. register p_scope sc = base_scope(get_scope_from_addr(a));
  167. register p_position pos = get_position_from_addr(a);
  168. if (sc && print_function) {
  169. fprintf(db_out, "in %s ", sc->sc_definedby->sy_idf->id_text);
  170. }
  171. if (pos) fprintf(db_out, "at \"%s\":%u", pos->filename, pos->lineno);
  172. return pos;
  173. }