Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raise an exception when assert fails #4482

Merged
merged 2 commits into from
Mar 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern "C" {
#include "cont.h"
}
#include <core_version.h>
#include "gdb_hooks.h"

#define LOOP_TASK_PRIORITY 1
#define LOOP_QUEUE_SIZE 1
Expand Down Expand Up @@ -137,12 +138,6 @@ static void do_global_ctors(void) {
(*--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() {
system_set_os_print(1);
gdb_init();
Expand Down
60 changes: 25 additions & 35 deletions cores/esp8266/core_esp8266_postmortem.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,24 @@
#include "esp8266_peri.h"
#include "cont.h"
#include "pgmspace.h"
#include "gdb_hooks.h"

extern void __real_system_restart_local();
extern void gdb_do_break();

extern cont_t g_cont;

// These will be pointers to PROGMEM const strings
static const char* s_panic_file = 0;
static int s_panic_line = 0;
static const char* s_panic_func = 0;

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 uart1_write_char_d(char c);
static void print_stack(uint32_t start, uint32_t end);
//static void print_pcs(uint32_t start, uint32_t end);

bool __attribute((weak)) crash_for_gdb = 0;
static void raise_exception() __attribute__((noreturn));

extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
(void) rst_info;
Expand All @@ -66,9 +64,17 @@ static void ets_puts_P(const char *romString) {
}

void __wrap_system_restart_local() {
if (crash_for_gdb) *((int*)0) = 0;
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};
system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
if (rst_info.reason != REASON_SOFT_WDT_RST &&
Expand Down Expand Up @@ -129,7 +135,6 @@ void __wrap_system_restart_local() {

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);

custom_crash_callback( &rst_info, sp + offset, stack_end );
Expand All @@ -153,24 +158,7 @@ static void print_stack(uint32_t start, uint32_t end) {
ets_puts_P(PSTR("<<<stack<<<\n"));
}

/*
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) {
static void uart_write_char_d(char c) {
uart0_write_char_d(c);
uart1_write_char_d(c);
}
Expand All @@ -192,29 +180,31 @@ static void uart1_write_char_d(char c) {
}
USF(1) = c;
}
void abort() __attribute__((noreturn));

void abort(){
// cause exception
static void raise_exception() {
__asm__ __volatile__ ("syscall");
while (1); // never reached, needed to satisfy "noreturn" attribute
}

void abort() {
s_abort_called = true;
do {
*((int*)0) = 0;
} while(true);
raise_exception();
}

void __assert_func(const char *file, int line, const char *func, const char *what) {
(void) what;
s_panic_file = file;
s_panic_line = line;
s_panic_func = func;
gdb_do_break();
gdb_do_break(); /* if GDB is not present, this is a no-op */
raise_exception();
}

void __panic_func(const char* file, int line, const char* func) {
s_panic_file = file;
s_panic_line = line;
s_panic_func = func;
gdb_do_break();
abort();
gdb_do_break(); /* if GDB is not present, this is a no-op */
raise_exception();
}

36 changes: 36 additions & 0 deletions cores/esp8266/gdb_hooks.c
Original file line number Diff line number Diff line change
@@ -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 changes: 57 additions & 0 deletions cores/esp8266/gdb_hooks.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 0 additions & 2 deletions libraries/GDBStub/src/GDBStub.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@

// this header is intentionally left blank

bool crash_for_gdb = 1;

#endif //GDBSTUB_H
10 changes: 8 additions & 2 deletions libraries/GDBStub/src/internal/gdbstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,5 +792,11 @@ void ATTR_GDBFN gdbstub_do_break_wrapper() {
gdbstub_do_break();
}

extern void gdb_do_break() __attribute__((weak, alias("gdbstub_do_break_wrapper")));
extern void gdb_init() __attribute__((weak, alias("gdbstub_init")));
bool ATTR_GDBINIT gdb_present()
{
return true;
}

extern void gdb_do_break() __attribute__((alias("gdbstub_do_break_wrapper")));
extern void gdb_init() __attribute__((alias("gdbstub_init")));