vax.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 1983, 1993, 2001
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include "gprof.h"
  30. #include "search_list.h"
  31. #include "source.h"
  32. #include "symtab.h"
  33. #include "cg_arcs.h"
  34. #include "corefile.h"
  35. #include "hist.h"
  36. /*
  37. * opcode of the `calls' instruction
  38. */
  39. #define CALLS 0xfb
  40. /*
  41. * register for pc relative addressing
  42. */
  43. #define PC 0xf
  44. enum opermodes
  45. {
  46. literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
  47. bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
  48. immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
  49. longrel, longreldef
  50. };
  51. typedef enum opermodes operandenum;
  52. /* *INDENT-OFF* */
  53. /* Here to document only. We can't use this when cross compiling as
  54. the bitfield layout might not be the same as native.
  55. struct modebyte
  56. {
  57. unsigned int regfield:4;
  58. unsigned int modefield:4;
  59. };
  60. */
  61. /* *INDENT-ON* */
  62. /*
  63. * A symbol to be the child of indirect calls:
  64. */
  65. static Sym indirectchild;
  66. static operandenum vax_operandmode (unsigned char *);
  67. static char *vax_operandname (operandenum);
  68. static long vax_operandlength (unsigned char *);
  69. static bfd_signed_vma vax_offset (unsigned char *);
  70. void vax_find_call (Sym *, bfd_vma, bfd_vma);
  71. static operandenum
  72. vax_operandmode (unsigned char *modep)
  73. {
  74. int usesreg = *modep & 0xf;
  75. switch ((*modep >> 4) & 0xf)
  76. {
  77. case 0:
  78. case 1:
  79. case 2:
  80. case 3:
  81. return literal;
  82. case 4:
  83. return indexed;
  84. case 5:
  85. return reg;
  86. case 6:
  87. return regdef;
  88. case 7:
  89. return autodec;
  90. case 8:
  91. return usesreg != PC ? autoinc : immediate;
  92. case 9:
  93. return usesreg != PC ? autoincdef : absolute;
  94. case 10:
  95. return usesreg != PC ? bytedisp : byterel;
  96. case 11:
  97. return usesreg != PC ? bytedispdef : bytereldef;
  98. case 12:
  99. return usesreg != PC ? worddisp : wordrel;
  100. case 13:
  101. return usesreg != PC ? worddispdef : wordreldef;
  102. case 14:
  103. return usesreg != PC ? longdisp : longrel;
  104. case 15:
  105. return usesreg != PC ? longdispdef : longreldef;
  106. }
  107. /* NOTREACHED */
  108. abort ();
  109. }
  110. static char *
  111. vax_operandname (operandenum mode)
  112. {
  113. switch (mode)
  114. {
  115. case literal:
  116. return "literal";
  117. case indexed:
  118. return "indexed";
  119. case reg:
  120. return "register";
  121. case regdef:
  122. return "register deferred";
  123. case autodec:
  124. return "autodecrement";
  125. case autoinc:
  126. return "autoincrement";
  127. case autoincdef:
  128. return "autoincrement deferred";
  129. case bytedisp:
  130. return "byte displacement";
  131. case bytedispdef:
  132. return "byte displacement deferred";
  133. case byterel:
  134. return "byte relative";
  135. case bytereldef:
  136. return "byte relative deferred";
  137. case worddisp:
  138. return "word displacement";
  139. case worddispdef:
  140. return "word displacement deferred";
  141. case wordrel:
  142. return "word relative";
  143. case wordreldef:
  144. return "word relative deferred";
  145. case immediate:
  146. return "immediate";
  147. case absolute:
  148. return "absolute";
  149. case longdisp:
  150. return "long displacement";
  151. case longdispdef:
  152. return "long displacement deferred";
  153. case longrel:
  154. return "long relative";
  155. case longreldef:
  156. return "long relative deferred";
  157. }
  158. /* NOTREACHED */
  159. abort ();
  160. }
  161. static long
  162. vax_operandlength (unsigned char *modep)
  163. {
  164. switch (vax_operandmode (modep))
  165. {
  166. case literal:
  167. case reg:
  168. case regdef:
  169. case autodec:
  170. case autoinc:
  171. case autoincdef:
  172. return 1;
  173. case bytedisp:
  174. case bytedispdef:
  175. case byterel:
  176. case bytereldef:
  177. return 2;
  178. case worddisp:
  179. case worddispdef:
  180. case wordrel:
  181. case wordreldef:
  182. return 3;
  183. case immediate:
  184. case absolute:
  185. case longdisp:
  186. case longdispdef:
  187. case longrel:
  188. case longreldef:
  189. return 5;
  190. case indexed:
  191. return 1 + vax_operandlength (modep + 1);
  192. }
  193. /* NOTREACHED */
  194. abort ();
  195. }
  196. static bfd_signed_vma
  197. vax_offset (unsigned char *modep)
  198. {
  199. operandenum mode = vax_operandmode (modep);
  200. ++modep; /* skip over the mode */
  201. switch (mode)
  202. {
  203. default:
  204. fprintf (stderr, "[reladdr] not relative address\n");
  205. return 0;
  206. case byterel:
  207. return 1 + bfd_get_signed_8 (core_bfd, modep);
  208. case wordrel:
  209. return 2 + bfd_get_signed_16 (core_bfd, modep);
  210. case longrel:
  211. return 4 + bfd_get_signed_32 (core_bfd, modep);
  212. }
  213. }
  214. void
  215. vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
  216. {
  217. unsigned char *instructp;
  218. long length;
  219. Sym *child;
  220. operandenum mode;
  221. operandenum firstmode;
  222. bfd_vma pc, destpc;
  223. static bool inited = false;
  224. if (!inited)
  225. {
  226. inited = true;
  227. sym_init (&indirectchild);
  228. indirectchild.cg.prop.fract = 1.0;
  229. indirectchild.cg.cyc.head = &indirectchild;
  230. }
  231. DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
  232. parent->name, (unsigned long) p_lowpc,
  233. (unsigned long) p_highpc));
  234. for (pc = p_lowpc; pc < p_highpc; pc += length)
  235. {
  236. length = 1;
  237. instructp = ((unsigned char *) core_text_space
  238. + pc - core_text_sect->vma);
  239. if ((*instructp & 0xff) == CALLS)
  240. {
  241. /*
  242. * maybe a calls, better check it out.
  243. * skip the count of the number of arguments.
  244. */
  245. DBG (CALLDEBUG,
  246. printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
  247. firstmode = vax_operandmode (instructp + length);
  248. switch (firstmode)
  249. {
  250. case literal:
  251. case immediate:
  252. break;
  253. default:
  254. goto botched;
  255. }
  256. length += vax_operandlength (instructp + length);
  257. mode = vax_operandmode (instructp + length);
  258. DBG (CALLDEBUG,
  259. printf ("\tfirst operand is %s", vax_operandname (firstmode));
  260. printf ("\tsecond operand is %s\n", vax_operandname (mode)));
  261. switch (mode)
  262. {
  263. case regdef:
  264. case bytedispdef:
  265. case worddispdef:
  266. case longdispdef:
  267. case bytereldef:
  268. case wordreldef:
  269. case longreldef:
  270. /*
  271. * indirect call: call through pointer
  272. * either *d(r) as a parameter or local
  273. * (r) as a return value
  274. * *f as a global pointer
  275. * [are there others that we miss?,
  276. * e.g. arrays of pointers to functions???]
  277. */
  278. arc_add (parent, &indirectchild, (unsigned long) 0);
  279. length += vax_operandlength (instructp + length);
  280. continue;
  281. case byterel:
  282. case wordrel:
  283. case longrel:
  284. /*
  285. * regular pc relative addressing
  286. * check that this is the address of
  287. * a function.
  288. */
  289. destpc = pc + vax_offset (instructp + length);
  290. if (hist_check_address (destpc))
  291. {
  292. child = sym_lookup (&symtab, destpc);
  293. if (child)
  294. {
  295. DBG (CALLDEBUG,
  296. printf ("[findcall]\tdestpc 0x%lx",
  297. (unsigned long) destpc);
  298. printf (" child->name %s", child->name);
  299. printf (" child->addr 0x%lx\n",
  300. (unsigned long) child->addr);
  301. );
  302. if (child->addr == destpc)
  303. {
  304. /*
  305. * a hit
  306. */
  307. arc_add (parent, child, (unsigned long) 0);
  308. length += vax_operandlength (instructp + length);
  309. continue;
  310. }
  311. }
  312. goto botched;
  313. }
  314. /*
  315. * else:
  316. * it looked like a calls,
  317. * but it wasn't to anywhere.
  318. */
  319. goto botched;
  320. default:
  321. botched:
  322. /*
  323. * something funny going on.
  324. */
  325. DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
  326. length = 1;
  327. continue;
  328. }
  329. }
  330. }
  331. }