Parcourir la source

Merge branch 'gdb/bt_on_invalid_pc_v4.0' into 'release/v4.0'

gdb: Modify PC in case of invalid PC (v4.0)

See merge request espressif/esp-idf!8980
Ivan Grokhotkov il y a 5 ans
Parent
commit
a4d7f15625

+ 1 - 0
components/esp32/ld/esp32.project.ld.in

@@ -142,6 +142,7 @@ SECTIONS
     . = 0x3C0;
     KEEP(*(.DoubleExceptionVector.text));
     . = 0x400;
+    _invalid_pc_placeholder = ABSOLUTE(.);
     *(.*Vector.literal)
 
     *(.UserEnter.literal);

+ 18 - 0
components/esp32/panic.c

@@ -188,6 +188,8 @@ static const char *edesc[] = {
 
 #define NUM_EDESCS (sizeof(edesc) / sizeof(char *))
 
+extern int _invalid_pc_placeholder;
+
 static void commonErrorHandler(XtExcFrame *frame);
 static inline void disableAllWdts();
 static void illegal_instruction_helper(XtExcFrame *frame);
@@ -309,6 +311,14 @@ void panicHandler(XtExcFrame *frame)
 
     if (esp_cpu_in_ocd_debug_mode()) {
         disableAllWdts();
+        if (!(esp_ptr_executable((void *)((frame->pc & 0x3fffffffU) | 0x40000000U)) && (frame->pc & 0xC0000000U))) {
+            /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
+             * Incase the PC is invalid, GDB will fail to translate addresses to function names
+             * Hence replacing the PC to a placeholder address in case of invalid PC
+             */
+            frame->pc = (uint32_t)&_invalid_pc_placeholder;
+        }
+
         if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
             frame->exccause == PANIC_RSN_INTWDT_CPU1) {
             TIMERG1.int_clr_timers.wdt = 1;
@@ -354,6 +364,14 @@ void xt_unhandled_exception(XtExcFrame *frame)
                                       APPTRACE_ONPANIC_HOST_FLUSH_TMO);
 #endif
 #endif
+            if (!(esp_ptr_executable((void *)((frame->pc & 0x3fffffffU) | 0x40000000U)) && (frame->pc & 0xC0000000U))) {
+                /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
+                 * Incase the PC is invalid, GDB will fail to translate addresses to function names
+                 * Hence replacing the PC to a placeholder address in case of invalid PC
+                 */
+                frame->pc = (uint32_t)&_invalid_pc_placeholder;
+            }
+
             //Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
             //will kick in exactly at the context the error happened.
             setFirstBreakpoint(frame->pc);

+ 16 - 2
components/esp_gdbstub/xtensa/gdbstub_xtensa.c

@@ -23,6 +23,8 @@
 #warning "gdbstub_xtensa: revisit the implementation for Call0 ABI"
 #endif
 
+extern int _invalid_pc_placeholder;
+
 static void init_regfile(esp_gdbstub_gdb_regfile_t *dst)
 {
     memset(dst, 0, sizeof(*dst));
@@ -46,7 +48,15 @@ void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_
 {
     init_regfile(dst);
     const uint32_t *a_regs = (const uint32_t *) &frame->a0;
-    dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U;
+    if (!(esp_ptr_executable((void *)((frame->pc & 0x3fffffffU) | 0x40000000U)) && (frame->pc & 0xC0000000U))) {
+        /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
+         * Incase the PC is invalid, GDB will fail to translate addresses to function names
+         * Hence replacing the PC to a placeholder address in case of invalid PC
+         */
+        dst->pc = (uint32_t)&_invalid_pc_placeholder;
+    } else {
+        dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U;
+    }
 
     for (int i = 0; i < 16; i++) {
         dst->a[i] = a_regs[i];
@@ -72,7 +82,11 @@ static void solicited_frame_to_regfile(const XtSolFrame *frame, esp_gdbstub_gdb_
 {
     init_regfile(dst);
     const uint32_t *a_regs = (const uint32_t *) &frame->a0;
-    dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U;
+    if (!(esp_ptr_executable((void *)((frame->pc & 0x3fffffffU) | 0x40000000U)) && (frame->pc & 0xC0000000U))) {
+        dst->pc = (uint32_t)&_invalid_pc_placeholder;
+    } else {
+        dst->pc = (frame->pc & 0x3fffffffU) | 0x40000000U;
+    }
 
     /* only 4 registers saved in the solicited frame */
     for (int i = 0; i < 4; i++) {