patch-gdb_microblaze-tdep_c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. --- gdb-7.8.2.orig/gdb/microblaze-tdep.c 2015-01-15 11:58:12.000000000 +0100
  2. +++ gdb-7.8.2/gdb/microblaze-tdep.c 2016-09-21 10:34:30.029222319 +0200
  3. @@ -1,6 +1,6 @@
  4. /* Target-dependent code for Xilinx MicroBlaze.
  5. - Copyright (C) 2009-2014 Free Software Foundation, Inc.
  6. + Copyright (C) 2009-2013 Free Software Foundation, Inc.
  7. This file is part of GDB.
  8. @@ -29,13 +29,13 @@
  9. #include "inferior.h"
  10. #include "regcache.h"
  11. #include "target.h"
  12. +#include "frame.h"
  13. #include "frame-base.h"
  14. #include "frame-unwind.h"
  15. #include "dwarf2-frame.h"
  16. #include "osabi.h"
  17. #include "gdb_assert.h"
  18. -#include <string.h>
  19. #include "target-descriptions.h"
  20. #include "opcodes/microblaze-opcm.h"
  21. #include "opcodes/microblaze-dis.h"
  22. @@ -73,7 +73,8 @@ static const char *microblaze_register_n
  23. "rpc", "rmsr", "rear", "resr", "rfsr", "rbtr",
  24. "rpvr0", "rpvr1", "rpvr2", "rpvr3", "rpvr4", "rpvr5", "rpvr6",
  25. "rpvr7", "rpvr8", "rpvr9", "rpvr10", "rpvr11",
  26. - "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi"
  27. + "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi",
  28. + "rslr", "rshr"
  29. };
  30. #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names)
  31. @@ -145,6 +146,14 @@ microblaze_push_dummy_code (struct gdbar
  32. return sp;
  33. }
  34. +static CORE_ADDR
  35. +microblaze_store_arguments (struct regcache *regcache, int nargs,
  36. + struct value **args, CORE_ADDR sp,
  37. + int struct_return, CORE_ADDR struct_addr)
  38. +{
  39. + error (_("store_arguments not implemented"));
  40. + return sp;
  41. +}
  42. static CORE_ADDR
  43. microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
  44. @@ -156,14 +165,52 @@ microblaze_push_dummy_call (struct gdbar
  45. return sp;
  46. }
  47. +static int
  48. +microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
  49. + struct bp_target_info *bp_tgt)
  50. +{
  51. + CORE_ADDR addr = bp_tgt->placed_address;
  52. + const unsigned char *bp;
  53. + int val;
  54. + int bplen;
  55. + gdb_byte old_contents[BREAKPOINT_MAX];
  56. + struct cleanup *cleanup;
  57. +
  58. + /* Determine appropriate breakpoint contents and size for this address. */
  59. + bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
  60. + if (bp == NULL)
  61. + error (_("Software breakpoints not implemented for this target."));
  62. +
  63. + /* Make sure we see the memory breakpoints. */
  64. + cleanup = make_show_memory_breakpoints_cleanup (1);
  65. + val = target_read_memory (addr, old_contents, bplen);
  66. +
  67. + /* If our breakpoint is no longer at the address, this means that the
  68. + program modified the code on us, so it is wrong to put back the
  69. + old value. */
  70. + if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
  71. + {
  72. + val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen);
  73. + microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr);
  74. + }
  75. +
  76. + do_cleanups (cleanup);
  77. + return val;
  78. +}
  79. +
  80. static const gdb_byte *
  81. microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc,
  82. int *len)
  83. {
  84. + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  85. static gdb_byte break_insn[] = MICROBLAZE_BREAKPOINT;
  86. + static gdb_byte break_insn_le[] = MICROBLAZE_BREAKPOINT_LE;
  87. *len = sizeof (break_insn);
  88. - return break_insn;
  89. + if (byte_order == BFD_ENDIAN_BIG)
  90. + return break_insn;
  91. + else
  92. + return break_insn_le;
  93. }
  94. /* Allocate and initialize a frame cache. */
  95. @@ -178,6 +225,7 @@ microblaze_alloc_frame_cache (void)
  96. /* Base address. */
  97. cache->base = 0;
  98. cache->pc = 0;
  99. + cache->saved_sp = 0;
  100. /* Frameless until proven otherwise. */
  101. cache->frameless_p = 1;
  102. @@ -234,6 +282,8 @@ microblaze_analyze_prologue (struct gdba
  103. int flags = 0;
  104. int save_hidden_pointer_found = 0;
  105. int non_stack_instruction_found = 0;
  106. + int n_insns;
  107. + unsigned int *insn_block;
  108. /* Find the start of this function. */
  109. find_pc_partial_function (pc, &name, &func_addr, &func_end);
  110. @@ -273,11 +323,18 @@ microblaze_analyze_prologue (struct gdba
  111. name, paddress (gdbarch, func_addr),
  112. paddress (gdbarch, stop));
  113. +/* Do a block read to minimize the transaction with the Debug Agent */
  114. + n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE);
  115. + insn_block = calloc(n_insns, sizeof(unsigned long));
  116. +
  117. + target_read_memory (func_addr, (void*) insn_block, n_insns * INST_WORD_SIZE );
  118. +
  119. for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE)
  120. {
  121. insn = microblaze_fetch_instruction (addr);
  122. + //insn = insn_block[(addr - func_addr) / INST_WORD_SIZE];
  123. op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
  124. - microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn);
  125. + microblaze_debug ("%s %08lx op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm);
  126. /* This code is very sensitive to what functions are present in the
  127. prologue. It assumes that the (addi, addik, swi, sw) can be the
  128. @@ -291,6 +348,7 @@ microblaze_analyze_prologue (struct gdba
  129. cache->frameless_p = 0; /* Frame found. */
  130. save_hidden_pointer_found = 0;
  131. non_stack_instruction_found = 0;
  132. + cache->register_offsets[rd] = -imm;
  133. continue;
  134. }
  135. else if (IS_SPILL_SP(op, rd, ra))
  136. @@ -401,8 +459,8 @@ microblaze_analyze_prologue (struct gdba
  137. part of the prologue. */
  138. if (save_hidden_pointer_found)
  139. prologue_end_addr -= INST_WORD_SIZE;
  140. -
  141. - return prologue_end_addr;
  142. + free(insn_block);
  143. + return prologue_end_addr;
  144. }
  145. static CORE_ADDR
  146. @@ -452,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch
  147. return start_pc;
  148. }
  149. +enum { REG_UNAVAIL = (CORE_ADDR) -1 };
  150. /* Normal frames. */
  151. static struct microblaze_frame_cache *
  152. @@ -459,7 +518,7 @@ microblaze_frame_cache (struct frame_inf
  153. {
  154. struct microblaze_frame_cache *cache;
  155. struct gdbarch *gdbarch = get_frame_arch (next_frame);
  156. - CORE_ADDR func;
  157. + CORE_ADDR current_pc;
  158. int rn;
  159. if (*this_cache)
  160. @@ -473,9 +532,18 @@ microblaze_frame_cache (struct frame_inf
  161. for (rn = 0; rn < gdbarch_num_regs (gdbarch); rn++)
  162. cache->register_offsets[rn] = -1;
  163. - func = get_frame_func (next_frame);
  164. + cache->pc = get_frame_func (next_frame);
  165. + current_pc = get_frame_pc (next_frame);
  166. - cache->pc = get_frame_address_in_block (next_frame);
  167. + if (cache->pc)
  168. + microblaze_analyze_prologue (gdbarch, cache->pc, current_pc,
  169. + cache);
  170. +
  171. + cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch));
  172. + cache->saved_sp = cache->base + cache->framesize;
  173. +
  174. + cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM] = cache->base;
  175. + cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp;
  176. return cache;
  177. }
  178. @@ -501,6 +569,14 @@ microblaze_frame_prev_register (struct f
  179. struct microblaze_frame_cache *cache =
  180. microblaze_frame_cache (this_frame, this_cache);
  181. + if ((regnum == MICROBLAZE_SP_REGNUM &&
  182. + cache->register_offsets[MICROBLAZE_SP_REGNUM])
  183. + || (regnum == MICROBLAZE_FP_REGNUM &&
  184. + cache->register_offsets[MICROBLAZE_SP_REGNUM]))
  185. +
  186. + return frame_unwind_got_constant (this_frame, regnum,
  187. + cache->register_offsets[MICROBLAZE_SP_REGNUM]);
  188. +
  189. if (cache->frameless_p)
  190. {
  191. if (regnum == MICROBLAZE_PC_REGNUM)
  192. @@ -508,11 +584,18 @@ microblaze_frame_prev_register (struct f
  193. if (regnum == MICROBLAZE_SP_REGNUM)
  194. regnum = 1;
  195. return trad_frame_get_prev_register (this_frame,
  196. - cache->saved_regs, regnum);
  197. + cache->saved_regs, regnum);
  198. }
  199. - else
  200. - return trad_frame_get_prev_register (this_frame, cache->saved_regs,
  201. - regnum);
  202. +
  203. + if (regnum == MICROBLAZE_PC_REGNUM)
  204. + {
  205. + regnum = 15;
  206. + return frame_unwind_got_memory (this_frame, regnum,
  207. + cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]);
  208. + }
  209. +
  210. + return trad_frame_get_prev_register (this_frame, cache->saved_regs,
  211. + regnum);
  212. }
  213. @@ -536,6 +619,12 @@ microblaze_frame_base_address (struct fr
  214. return cache->base;
  215. }
  216. +static const struct frame_unwind *
  217. +microblaze_frame_sniffer (struct frame_info *next_frame)
  218. +{
  219. + return &microblaze_frame_unwind;
  220. +}
  221. +
  222. static const struct frame_base microblaze_frame_base =
  223. {
  224. &microblaze_frame_unwind,
  225. @@ -628,6 +717,109 @@ microblaze_stabs_argument_has_addr (stru
  226. return (TYPE_LENGTH (type) == 16);
  227. }
  228. +int
  229. +microblaze_software_single_step (struct frame_info *frame)
  230. +{
  231. + struct gdbarch *arch = get_frame_arch (frame);
  232. + struct address_space *aspace = get_frame_address_space (frame);
  233. + struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
  234. + static char le_breakp[] = MICROBLAZE_BREAKPOINT_LE;
  235. + static char be_breakp[] = MICROBLAZE_BREAKPOINT;
  236. + enum bfd_endian byte_order = gdbarch_byte_order (arch);
  237. + char *breakp = byte_order == BFD_ENDIAN_BIG ? be_breakp : le_breakp;
  238. + int ret = 0;
  239. +
  240. + /* Save the address and the values of the next_pc and the target */
  241. + static struct sstep_breaks
  242. + {
  243. + CORE_ADDR address;
  244. + bfd_boolean valid;
  245. + /* Shadow contents. */
  246. + char data[INST_WORD_SIZE];
  247. + } stepbreaks[2];
  248. + int ii;
  249. +
  250. + if (1)
  251. + {
  252. + CORE_ADDR pc;
  253. + long insn;
  254. + enum microblaze_instr minstr;
  255. + bfd_boolean isunsignednum;
  256. + enum microblaze_instr_type insn_type;
  257. + short delay_slots;
  258. + int imm;
  259. + bfd_boolean immfound = FALSE;
  260. +
  261. + /* Set a breakpoint at the next instruction */
  262. + /* If the current instruction is an imm, set it at the inst after */
  263. + /* If the instruction has a delay slot, skip the delay slot */
  264. + pc = get_frame_pc (frame);
  265. + insn = microblaze_fetch_instruction (pc);
  266. + minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
  267. + if (insn_type == immediate_inst)
  268. + {
  269. + int rd, ra, rb;
  270. + immfound = TRUE;
  271. + minstr = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
  272. + pc = pc + INST_WORD_SIZE;
  273. + insn = microblaze_fetch_instruction (pc);
  274. + minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
  275. + }
  276. + stepbreaks[0].address = pc + (delay_slots * INST_WORD_SIZE) + INST_WORD_SIZE;
  277. + if (insn_type != return_inst) {
  278. + stepbreaks[0].valid = TRUE;
  279. + } else {
  280. + stepbreaks[0].valid = FALSE;
  281. + }
  282. +
  283. + microblaze_debug ("single-step insn_type=%x insn=%x\n", insn_type, insn);
  284. + /* Now check for branch or return instructions */
  285. + if (insn_type == branch_inst || insn_type == return_inst) {
  286. + int limm;
  287. + int lrd, lra, lrb;
  288. + int ra, rb;
  289. + bfd_boolean targetvalid;
  290. + bfd_boolean unconditionalbranch;
  291. + microblaze_decode_insn(insn, &lrd, &lra, &lrb, &limm);
  292. + if (lra >= 0 && lra < MICROBLAZE_NUM_REGS)
  293. + ra = get_frame_register_unsigned (frame, lra);
  294. + else
  295. + ra = 0;
  296. + if (lrb >= 0 && lrb < MICROBLAZE_NUM_REGS)
  297. + rb = get_frame_register_unsigned (frame, lrb);
  298. + else
  299. + rb = 0;
  300. +
  301. + stepbreaks[1].address = microblaze_get_target_address (insn, immfound, imm, pc, ra, rb, &targetvalid, &unconditionalbranch);
  302. + microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address);
  303. +
  304. + if (unconditionalbranch)
  305. + stepbreaks[0].valid = FALSE; /* This is a unconditional branch: will not come to the next address */
  306. + if (targetvalid && (stepbreaks[0].valid == FALSE ||
  307. + (stepbreaks[0].address != stepbreaks[1].address))
  308. + && (stepbreaks[1].address != pc)) {
  309. + stepbreaks[1].valid = TRUE;
  310. + } else {
  311. + stepbreaks[1].valid = FALSE;
  312. + }
  313. + } else {
  314. + stepbreaks[1].valid = FALSE;
  315. + }
  316. +
  317. + /* Insert the breakpoints */
  318. + for (ii = 0; ii < 2; ++ii)
  319. + {
  320. +
  321. + /* ignore invalid breakpoint. */
  322. + if (stepbreaks[ii].valid) {
  323. + insert_single_step_breakpoint (arch, aspace, stepbreaks[ii].address);
  324. + ret = 1;
  325. + }
  326. + }
  327. + }
  328. + return ret;
  329. +}
  330. +
  331. static void
  332. microblaze_write_pc (struct regcache *regcache, CORE_ADDR pc)
  333. {
  334. @@ -664,6 +856,70 @@ microblaze_dwarf2_reg_to_regnum (struct
  335. return dwarf2_to_reg_map[reg];
  336. }
  337. +
  338. +void
  339. +microblaze_supply_gregset (const struct microblaze_gregset *gregset,
  340. + struct regcache *regcache,
  341. + int regnum, const void *gregs)
  342. +{
  343. + unsigned int *regs = gregs;
  344. + if (regnum >= 0)
  345. + regcache_raw_supply (regcache, regnum, regs + regnum);
  346. +
  347. + if (regnum == -1) {
  348. + int i;
  349. +
  350. + for (i = 0; i < 50; i++) {
  351. + regcache_raw_supply (regcache, i, regs + i);
  352. + }
  353. + }
  354. +}
  355. +
  356. +
  357. +void
  358. +microblaze_collect_gregset (const struct microblaze_gregset *gregset,
  359. + const struct regcache *regcache,
  360. + int regnum, void *gregs)
  361. +{
  362. + /* FIXME. */
  363. +}
  364. +
  365. +void
  366. +microblaze_supply_fpregset (struct regcache *regcache,
  367. + int regnum, const void *fpregs)
  368. +{
  369. + /* FIXME. */
  370. +}
  371. +
  372. +void
  373. +microblaze_collect_fpregset (const struct regcache *regcache,
  374. + int regnum, void *fpregs)
  375. +{
  376. + /* FIXME. */
  377. +}
  378. +
  379. +
  380. +/* Return the appropriate register set for the core section identified
  381. + by SECT_NAME and SECT_SIZE. */
  382. +
  383. +const struct regset *
  384. +microblaze_regset_from_core_section (struct gdbarch *gdbarch,
  385. + const char *sect_name, size_t sect_size)
  386. +{
  387. + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  388. +
  389. + microblaze_debug ("microblaze_regset_from_core_section, sect_name = %s\n", sect_name);
  390. +
  391. + if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
  392. + return tdep->gregset;
  393. +
  394. + if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
  395. + return tdep->fpregset;
  396. +
  397. + microblaze_debug ("microblaze_regset_from_core_section returning null :-( \n");
  398. + return NULL;
  399. +}
  400. +
  401. static struct gdbarch *
  402. microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
  403. {
  404. @@ -679,6 +935,11 @@ microblaze_gdbarch_init (struct gdbarch_
  405. tdep = XNEW (struct gdbarch_tdep);
  406. gdbarch = gdbarch_alloc (&info, tdep);
  407. + tdep->gregset = NULL;
  408. + tdep->sizeof_gregset = 0;
  409. + tdep->fpregset = NULL;
  410. + tdep->sizeof_fpregset = 0;
  411. +
  412. set_gdbarch_long_double_bit (gdbarch, 128);
  413. set_gdbarch_num_regs (gdbarch, MICROBLAZE_NUM_REGS);
  414. @@ -706,7 +967,10 @@ microblaze_gdbarch_init (struct gdbarch_
  415. /* Stack grows downward. */
  416. set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
  417. + set_gdbarch_memory_remove_breakpoint (gdbarch, microblaze_linux_memory_remove_breakpoint);
  418. +
  419. set_gdbarch_breakpoint_from_pc (gdbarch, microblaze_breakpoint_from_pc);
  420. + set_gdbarch_software_single_step (gdbarch, microblaze_software_single_step);
  421. set_gdbarch_frame_args_skip (gdbarch, 8);
  422. @@ -725,6 +989,13 @@ microblaze_gdbarch_init (struct gdbarch_
  423. dwarf2_append_unwinders (gdbarch);
  424. frame_unwind_append_unwinder (gdbarch, &microblaze_frame_unwind);
  425. frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
  426. + //frame_base_append_sniffer (gdbarch, microblaze_frame_sniffer);
  427. +
  428. + /* If we have register sets, enable the generic core file support. */
  429. + if (tdep->gregset) {
  430. + set_gdbarch_regset_from_core_section (gdbarch,
  431. + microblaze_regset_from_core_section);
  432. + }
  433. return gdbarch;
  434. }