public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb: LoongArch: Implement loongarch_scan_prologue()
@ 2022-04-20 11:23 Tiezhu Yang
  0 siblings, 0 replies; only message in thread
From: Tiezhu Yang @ 2022-04-20 11:23 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6e0d24c448d09a27f56799102f06223ceaf6ff4d

commit 6e0d24c448d09a27f56799102f06223ceaf6ff4d
Author: Tiezhu Yang <yangtiezhu@loongson.cn>
Date:   Wed Apr 20 17:48:53 2022 +0800

    gdb: LoongArch: Implement loongarch_scan_prologue()
    
    If can't determine prologue from the symbol table, need to examine
    instructions. Implement loongarch_scan_prologue() to analyze the
    function prologue from START_PC to LIMIT_PC, return the address of
    the first instruction past the prologue.
    
    Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>

Diff:
---
 gdb/loongarch-tdep.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 131 insertions(+), 1 deletion(-)

diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index 88a838210c0..e30ef8084da 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -22,11 +22,131 @@
 #include "dwarf2/frame.h"
 #include "elf-bfd.h"
 #include "frame-unwind.h"
+#include "gdbcore.h"
 #include "loongarch-tdep.h"
+#include "target.h"
 #include "target-descriptions.h"
 #include "trad-frame.h"
 #include "user-regs.h"
 
+/* Fetch the instruction at PC.  */
+
+static insn_t
+loongarch_fetch_instruction (CORE_ADDR pc)
+{
+  size_t insn_len = loongarch_insn_length (0);
+  gdb_byte buf[insn_len];
+  int err;
+
+  err = target_read_memory (pc, buf, insn_len);
+  if (err)
+    memory_error (TARGET_XFER_E_IO, pc);
+
+  return extract_unsigned_integer (buf, insn_len, BFD_ENDIAN_LITTLE);
+}
+
+/* Return TRUE if INSN is a branch instruction, otherwise return FALSE.  */
+
+static bool
+loongarch_insn_is_branch (insn_t insn)
+{
+  if ((insn & 0xfc000000) == 0x4c000000       /* jirl	rd, rj, offs16  */
+      || (insn & 0xfc000000) == 0x50000000    /* b	offs26  */
+      || (insn & 0xfc000000) == 0x54000000    /* bl	offs26  */
+      || (insn & 0xfc000000) == 0x58000000    /* beq	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x5c000000    /* bne	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x60000000    /* blt	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x64000000    /* bge	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x68000000    /* bltu	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x6c000000    /* bgeu	rj, rd, offs16  */
+      || (insn & 0xfc000000) == 0x40000000    /* beqz	rj, offs21  */
+      || (insn & 0xfc000000) == 0x44000000)   /* bnez	rj, offs21  */
+    return true;
+  return false;
+}
+
+/* Analyze the function prologue from START_PC to LIMIT_PC.
+   Return the address of the first instruction past the prologue.  */
+
+static CORE_ADDR
+loongarch_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
+			 CORE_ADDR limit_pc, struct frame_info *this_frame,
+			 struct trad_frame_cache *this_cache)
+{
+  CORE_ADDR cur_pc = start_pc, prologue_end = 0;
+  loongarch_gdbarch_tdep *tdep = (loongarch_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+  auto regs = tdep->regs;
+  int32_t sp = regs.r + 3;
+  int32_t fp = regs.r + 22;
+  int32_t reg_value[32] = {0};
+  int32_t reg_used[32] = {1, 0};
+
+  while (cur_pc < limit_pc)
+    {
+      insn_t insn = loongarch_fetch_instruction (cur_pc);
+      size_t insn_len = loongarch_insn_length (insn);
+      int32_t rd = loongarch_decode_imm ("0:5", insn, 0);
+      int32_t rj = loongarch_decode_imm ("5:5", insn, 0);
+      int32_t rk = loongarch_decode_imm ("10:5", insn, 0);
+      int32_t si12 = loongarch_decode_imm ("10:12", insn, 1);
+      int32_t si20 = loongarch_decode_imm ("5:20", insn, 1);
+
+      if ((insn & 0xffc00000) == 0x02c00000	/* addi.d sp,sp,si12  */
+	  && rd == sp && rj == sp && si12 < 0)
+	{
+	  prologue_end = cur_pc + insn_len;
+	}
+      else if ((insn & 0xffc00000) == 0x02c00000 /* addi.d fp,sp,si12  */
+	       && rd == fp && rj == sp && si12 > 0)
+	{
+	  prologue_end = cur_pc + insn_len;
+	}
+      else if ((insn & 0xffc00000) == 0x29c00000 /* st.d rd,sp,si12  */
+	       && rj == sp)
+	{
+	  prologue_end = cur_pc + insn_len;
+	}
+      else if ((insn & 0xff000000) == 0x27000000 /* stptr.d rd,sp,si14  */
+	       && rj == sp)
+	{
+	  prologue_end = cur_pc + insn_len;
+	}
+      else if ((insn & 0xfe000000) == 0x14000000) /* lu12i.w rd,si20  */
+	{
+	  reg_value[rd] = si20 << 12;
+	  reg_used[rd] = 1;
+	}
+      else if ((insn & 0xffc00000) == 0x03800000) /* ori rd,rj,si12  */
+	{
+	  if (reg_used[rj])
+	  {
+	    reg_value[rd] = reg_value[rj] | (si12 & 0xfff);
+	    reg_used[rd] = 1;
+	  }
+	}
+      else if ((insn & 0xffff8000) == 0x00108000 /* add.d sp,sp,rk  */
+	       && rd == sp && rj == sp)
+	{
+	  if (reg_used[rk] == 1 && reg_value[rk] < 0)
+	    {
+	      prologue_end = cur_pc + insn_len;
+	      break;
+	    }
+	}
+      else if (loongarch_insn_is_branch (insn))
+	{
+	  break;
+	}
+
+      cur_pc += insn_len;
+    }
+
+  if (prologue_end == 0)
+    prologue_end = cur_pc;
+
+  return prologue_end;
+}
+
 /* Implement the loongarch_skip_prologue gdbarch method.  */
 
 static CORE_ADDR
@@ -45,7 +165,17 @@ loongarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 	return std::max (pc, post_prologue_pc);
     }
 
-  return 0;
+  /* Can't determine prologue from the symbol table, need to examine
+     instructions.  */
+
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  CORE_ADDR limit_pc = skip_prologue_using_sal (gdbarch, pc);
+  if (limit_pc == 0)
+    limit_pc = pc + 100;	/* Arbitrary large number.  */
+
+  return loongarch_scan_prologue (gdbarch, pc, limit_pc, nullptr, nullptr);
 }
 
 /* Adjust the address downward (direction of stack growth) so that it


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-04-20 11:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-20 11:23 [binutils-gdb] gdb: LoongArch: Implement loongarch_scan_prologue() Tiezhu Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).