mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
gdbstub, postmortem: clean up
- Move GDB stub hooks into a separate file, provide header for it - Use syscall instruction raise user mode exception - Remove unused code in postmortem.c fixup fixup
This commit is contained in:
parent
0643d6e7ab
commit
170911a689
@ -33,6 +33,7 @@ extern "C" {
|
|||||||
#include "cont.h"
|
#include "cont.h"
|
||||||
}
|
}
|
||||||
#include <core_version.h>
|
#include <core_version.h>
|
||||||
|
#include "gdb_hooks.h"
|
||||||
|
|
||||||
#define LOOP_TASK_PRIORITY 1
|
#define LOOP_TASK_PRIORITY 1
|
||||||
#define LOOP_QUEUE_SIZE 1
|
#define LOOP_QUEUE_SIZE 1
|
||||||
@ -137,12 +138,6 @@ static void do_global_ctors(void) {
|
|||||||
(*--p)();
|
(*--p)();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __gdb_init() {}
|
|
||||||
extern "C" void gdb_init(void) __attribute__ ((weak, alias("__gdb_init")));
|
|
||||||
|
|
||||||
extern "C" void __gdb_do_break(){}
|
|
||||||
extern "C" void gdb_do_break(void) __attribute__ ((weak, alias("__gdb_do_break")));
|
|
||||||
|
|
||||||
void init_done() {
|
void init_done() {
|
||||||
system_set_os_print(1);
|
system_set_os_print(1);
|
||||||
gdb_init();
|
gdb_init();
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
#include "esp8266_peri.h"
|
#include "esp8266_peri.h"
|
||||||
#include "cont.h"
|
#include "cont.h"
|
||||||
#include "pgmspace.h"
|
#include "pgmspace.h"
|
||||||
|
#include "gdb_hooks.h"
|
||||||
|
|
||||||
extern void __real_system_restart_local();
|
extern void __real_system_restart_local();
|
||||||
extern void gdb_do_break();
|
|
||||||
|
|
||||||
extern cont_t g_cont;
|
extern cont_t g_cont;
|
||||||
|
|
||||||
@ -38,16 +38,14 @@ extern cont_t g_cont;
|
|||||||
static const char* s_panic_file = 0;
|
static const char* s_panic_file = 0;
|
||||||
static int s_panic_line = 0;
|
static int s_panic_line = 0;
|
||||||
static const char* s_panic_func = 0;
|
static const char* s_panic_func = 0;
|
||||||
|
|
||||||
static bool s_abort_called = false;
|
static bool s_abort_called = false;
|
||||||
|
|
||||||
void uart_write_char_d(char c);
|
void abort() __attribute__((noreturn));
|
||||||
|
static void uart_write_char_d(char c);
|
||||||
static void uart0_write_char_d(char c);
|
static void uart0_write_char_d(char c);
|
||||||
static void uart1_write_char_d(char c);
|
static void uart1_write_char_d(char c);
|
||||||
static void print_stack(uint32_t start, uint32_t end);
|
static void print_stack(uint32_t start, uint32_t end);
|
||||||
//static void print_pcs(uint32_t start, uint32_t end);
|
static void raise_exception() __attribute__((noreturn));
|
||||||
|
|
||||||
bool __attribute((weak)) crash_for_gdb = 0;
|
|
||||||
|
|
||||||
extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
|
extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
|
||||||
(void) rst_info;
|
(void) rst_info;
|
||||||
@ -66,9 +64,17 @@ static void ets_puts_P(const char *romString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void __wrap_system_restart_local() {
|
void __wrap_system_restart_local() {
|
||||||
if (crash_for_gdb) *((int*)0) = 0;
|
|
||||||
register uint32_t sp asm("a1");
|
register uint32_t sp asm("a1");
|
||||||
|
|
||||||
|
if (gdb_present()) {
|
||||||
|
/* When GDBStub is present, exceptions are handled by GDBStub,
|
||||||
|
but Soft WDT will still call this function.
|
||||||
|
Trigger an exception to break into GDB.
|
||||||
|
TODO: check why gdb_do_break() or asm("break.n 0") do not
|
||||||
|
break into GDB here. */
|
||||||
|
raise_exception();
|
||||||
|
}
|
||||||
|
|
||||||
struct rst_info rst_info = {0};
|
struct rst_info rst_info = {0};
|
||||||
system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
|
system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
|
||||||
if (rst_info.reason != REASON_SOFT_WDT_RST &&
|
if (rst_info.reason != REASON_SOFT_WDT_RST &&
|
||||||
@ -129,7 +135,6 @@ void __wrap_system_restart_local() {
|
|||||||
|
|
||||||
ets_printf("sp: %08x end: %08x offset: %04x\n", sp, stack_end, offset);
|
ets_printf("sp: %08x end: %08x offset: %04x\n", sp, stack_end, offset);
|
||||||
|
|
||||||
// print_pcs(sp + offset, stack_end);
|
|
||||||
print_stack(sp + offset, stack_end);
|
print_stack(sp + offset, stack_end);
|
||||||
|
|
||||||
custom_crash_callback( &rst_info, sp + offset, stack_end );
|
custom_crash_callback( &rst_info, sp + offset, stack_end );
|
||||||
@ -153,24 +158,7 @@ static void print_stack(uint32_t start, uint32_t end) {
|
|||||||
ets_puts_P(PSTR("<<<stack<<<\n"));
|
ets_puts_P(PSTR("<<<stack<<<\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void uart_write_char_d(char c) {
|
||||||
static void print_pcs(uint32_t start, uint32_t end) {
|
|
||||||
uint32_t n = 0;
|
|
||||||
ets_printf("\n>>>pc>>>\n");
|
|
||||||
for (uint32_t pos = start; pos < end; pos += 16, ++n) {
|
|
||||||
uint32_t* sf = (uint32_t*) pos;
|
|
||||||
|
|
||||||
uint32_t pc_ret = sf[3];
|
|
||||||
uint32_t sp_ret = sf[2];
|
|
||||||
if (pc_ret < 0x40000000 || pc_ret > 0x40f00000 || sp_ret != pos + 16)
|
|
||||||
continue;
|
|
||||||
ets_printf("%08x\n", pc_ret);
|
|
||||||
}
|
|
||||||
ets_printf("<<<pc<<<\n");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void uart_write_char_d(char c) {
|
|
||||||
uart0_write_char_d(c);
|
uart0_write_char_d(c);
|
||||||
uart1_write_char_d(c);
|
uart1_write_char_d(c);
|
||||||
}
|
}
|
||||||
@ -192,14 +180,15 @@ static void uart1_write_char_d(char c) {
|
|||||||
}
|
}
|
||||||
USF(1) = c;
|
USF(1) = c;
|
||||||
}
|
}
|
||||||
void abort() __attribute__((noreturn));
|
|
||||||
|
|
||||||
void abort(){
|
static void raise_exception() {
|
||||||
// cause exception
|
__asm__ __volatile__ ("syscall");
|
||||||
|
while (1); // never reached, needed to satisfy "noreturn" attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
void abort() {
|
||||||
s_abort_called = true;
|
s_abort_called = true;
|
||||||
do {
|
raise_exception();
|
||||||
*((int*)0) = 0;
|
|
||||||
} while(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __assert_func(const char *file, int line, const char *func, const char *what) {
|
void __assert_func(const char *file, int line, const char *func, const char *what) {
|
||||||
@ -207,14 +196,14 @@ void __assert_func(const char *file, int line, const char *func, const char *wha
|
|||||||
s_panic_file = file;
|
s_panic_file = file;
|
||||||
s_panic_line = line;
|
s_panic_line = line;
|
||||||
s_panic_func = func;
|
s_panic_func = func;
|
||||||
gdb_do_break();
|
gdb_do_break(); /* if GDB is not present, this is a no-op */
|
||||||
}
|
}
|
||||||
|
|
||||||
void __panic_func(const char* file, int line, const char* func) {
|
void __panic_func(const char* file, int line, const char* func) {
|
||||||
s_panic_file = file;
|
s_panic_file = file;
|
||||||
s_panic_line = line;
|
s_panic_line = line;
|
||||||
s_panic_func = func;
|
s_panic_func = func;
|
||||||
gdb_do_break();
|
gdb_do_break(); /* if GDB is not present, this is a no-op */
|
||||||
abort();
|
raise_exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
cores/esp8266/gdb_hooks.c
Normal file
36
cores/esp8266/gdb_hooks.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
gdb_hooks.c - Default (no-op) hooks for GDB Stub library
|
||||||
|
Copyright (c) 2018 Ivan Grokhotkov. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ets_sys.h"
|
||||||
|
#include "gdb_hooks.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* gdb_init and gdb_do_break do not return anything, but since the return
|
||||||
|
value is in register, it doesn't hurt to return a bool, so that the
|
||||||
|
same stub can be used for gdb_present. */
|
||||||
|
|
||||||
|
bool ICACHE_RAM_ATTR __gdb_no_op()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void gdb_init(void) __attribute__ ((weak, alias("__gdb_no_op")));
|
||||||
|
extern void gdb_do_break(void) __attribute__ ((weak, alias("__gdb_no_op")));
|
||||||
|
extern bool gdb_present(void) __attribute__ ((weak, alias("__gdb_no_op")));
|
||||||
|
|
57
cores/esp8266/gdb_hooks.h
Normal file
57
cores/esp8266/gdb_hooks.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
gdb_hooks.h - Hooks for GDB Stub library
|
||||||
|
Copyright (c) 2018 Ivan Grokhotkov. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize GDB stub, if present
|
||||||
|
*
|
||||||
|
* By default, this function is a no-op. When GDBStub library is linked,
|
||||||
|
* this function is overriden and does necessary initialization of that library.
|
||||||
|
* Called early at startup.
|
||||||
|
*/
|
||||||
|
void gdb_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Break into GDB, if present
|
||||||
|
*
|
||||||
|
* By default, this function is a no-op. When GDBStub library is linked,
|
||||||
|
* this function is overriden and triggers entry into the debugger, which
|
||||||
|
* looks like a breakpoint hit.
|
||||||
|
*/
|
||||||
|
void gdb_do_break(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if GDB stub is present.
|
||||||
|
*
|
||||||
|
* By default, this function returns false. When GDBStub library is linked,
|
||||||
|
* this function is overriden and returns true. Can be used to check whether
|
||||||
|
* GDB is used.
|
||||||
|
*
|
||||||
|
* @return true if GDB stub is present
|
||||||
|
*/
|
||||||
|
bool gdb_present(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -3,6 +3,4 @@
|
|||||||
|
|
||||||
// this header is intentionally left blank
|
// this header is intentionally left blank
|
||||||
|
|
||||||
bool crash_for_gdb = 1;
|
|
||||||
|
|
||||||
#endif //GDBSTUB_H
|
#endif //GDBSTUB_H
|
||||||
|
@ -792,5 +792,11 @@ void ATTR_GDBFN gdbstub_do_break_wrapper() {
|
|||||||
gdbstub_do_break();
|
gdbstub_do_break();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void gdb_do_break() __attribute__((weak, alias("gdbstub_do_break_wrapper")));
|
bool ATTR_GDBINIT gdb_present()
|
||||||
extern void gdb_init() __attribute__((weak, alias("gdbstub_init")));
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void gdb_do_break() __attribute__((alias("gdbstub_do_break_wrapper")));
|
||||||
|
extern void gdb_init() __attribute__((alias("gdbstub_init")));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user