From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7873) id 3C0EC3858C53; Wed, 20 Apr 2022 11:23:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C0EC3858C53 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tiezhu Yang To: gdb-cvs@sourceware.org Subject: [binutils-gdb] gdb: LoongArch: Implement loongarch_scan_prologue() X-Act-Checkin: binutils-gdb X-Git-Author: Tiezhu Yang X-Git-Refname: refs/heads/master X-Git-Oldrev: 5355776935f1a69d897c4770209b6a3978f07ce1 X-Git-Newrev: 6e0d24c448d09a27f56799102f06223ceaf6ff4d Message-Id: <20220420112319.3C0EC3858C53@sourceware.org> Date: Wed, 20 Apr 2022 11:23:19 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Apr 2022 11:23:19 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D6e0d24c448d0= 9a27f56799102f06223ceaf6ff4d commit 6e0d24c448d09a27f56799102f06223ceaf6ff4d Author: Tiezhu Yang Date: Wed Apr 20 17:48:53 2022 +0800 gdb: LoongArch: Implement loongarch_scan_prologue() =20 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. =20 Signed-off-by: Tiezhu Yang 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" =20 +/* Fetch the instruction at PC. */ + +static insn_t +loongarch_fetch_instruction (CORE_ADDR pc) +{ + size_t insn_len =3D loongarch_insn_length (0); + gdb_byte buf[insn_len]; + int err; + + err =3D 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) =3D=3D 0x4c000000 /* jirl rd, rj, offs16 = */ + || (insn & 0xfc000000) =3D=3D 0x50000000 /* b offs26 */ + || (insn & 0xfc000000) =3D=3D 0x54000000 /* bl offs26 */ + || (insn & 0xfc000000) =3D=3D 0x58000000 /* beq rj, rd, offs16 */ + || (insn & 0xfc000000) =3D=3D 0x5c000000 /* bne rj, rd, offs16 */ + || (insn & 0xfc000000) =3D=3D 0x60000000 /* blt rj, rd, offs16 */ + || (insn & 0xfc000000) =3D=3D 0x64000000 /* bge rj, rd, offs16 */ + || (insn & 0xfc000000) =3D=3D 0x68000000 /* bltu rj, rd, offs16 = */ + || (insn & 0xfc000000) =3D=3D 0x6c000000 /* bgeu rj, rd, offs16 = */ + || (insn & 0xfc000000) =3D=3D 0x40000000 /* beqz rj, offs21 */ + || (insn & 0xfc000000) =3D=3D 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 =3D start_pc, prologue_end =3D 0; + loongarch_gdbarch_tdep *tdep =3D (loongarch_gdbarch_tdep *) gdbarch_tdep= (gdbarch); + auto regs =3D tdep->regs; + int32_t sp =3D regs.r + 3; + int32_t fp =3D regs.r + 22; + int32_t reg_value[32] =3D {0}; + int32_t reg_used[32] =3D {1, 0}; + + while (cur_pc < limit_pc) + { + insn_t insn =3D loongarch_fetch_instruction (cur_pc); + size_t insn_len =3D loongarch_insn_length (insn); + int32_t rd =3D loongarch_decode_imm ("0:5", insn, 0); + int32_t rj =3D loongarch_decode_imm ("5:5", insn, 0); + int32_t rk =3D loongarch_decode_imm ("10:5", insn, 0); + int32_t si12 =3D loongarch_decode_imm ("10:12", insn, 1); + int32_t si20 =3D loongarch_decode_imm ("5:20", insn, 1); + + if ((insn & 0xffc00000) =3D=3D 0x02c00000 /* addi.d sp,sp,si12 */ + && rd =3D=3D sp && rj =3D=3D sp && si12 < 0) + { + prologue_end =3D cur_pc + insn_len; + } + else if ((insn & 0xffc00000) =3D=3D 0x02c00000 /* addi.d fp,sp,si12 = */ + && rd =3D=3D fp && rj =3D=3D sp && si12 > 0) + { + prologue_end =3D cur_pc + insn_len; + } + else if ((insn & 0xffc00000) =3D=3D 0x29c00000 /* st.d rd,sp,si12 */ + && rj =3D=3D sp) + { + prologue_end =3D cur_pc + insn_len; + } + else if ((insn & 0xff000000) =3D=3D 0x27000000 /* stptr.d rd,sp,si14= */ + && rj =3D=3D sp) + { + prologue_end =3D cur_pc + insn_len; + } + else if ((insn & 0xfe000000) =3D=3D 0x14000000) /* lu12i.w rd,si20 = */ + { + reg_value[rd] =3D si20 << 12; + reg_used[rd] =3D 1; + } + else if ((insn & 0xffc00000) =3D=3D 0x03800000) /* ori rd,rj,si12 */ + { + if (reg_used[rj]) + { + reg_value[rd] =3D reg_value[rj] | (si12 & 0xfff); + reg_used[rd] =3D 1; + } + } + else if ((insn & 0xffff8000) =3D=3D 0x00108000 /* add.d sp,sp,rk */ + && rd =3D=3D sp && rj =3D=3D sp) + { + if (reg_used[rk] =3D=3D 1 && reg_value[rk] < 0) + { + prologue_end =3D cur_pc + insn_len; + break; + } + } + else if (loongarch_insn_is_branch (insn)) + { + break; + } + + cur_pc +=3D insn_len; + } + + if (prologue_end =3D=3D 0) + prologue_end =3D cur_pc; + + return prologue_end; +} + /* Implement the loongarch_skip_prologue gdbarch method. */ =20 static CORE_ADDR @@ -45,7 +165,17 @@ loongarch_skip_prologue (struct gdbarch *gdbarch, CORE_= ADDR pc) return std::max (pc, post_prologue_pc); } =20 - 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 =3D skip_prologue_using_sal (gdbarch, pc); + if (limit_pc =3D=3D 0) + limit_pc =3D pc + 100; /* Arbitrary large number. */ + + return loongarch_scan_prologue (gdbarch, pc, limit_pc, nullptr, nullptr); } =20 /* Adjust the address downward (direction of stack growth) so that it