gdb/testsuite: add simesp board

This commit is contained in:
Alexey Lapshin
2021-11-30 19:42:48 +03:00
parent c32361e9c2
commit 01f46c867e
10 changed files with 581 additions and 0 deletions

View File

@ -0,0 +1,138 @@
set simesp_spawn_id ""
set simesp_last_load_file ""
if { [info exists ::env(ESP_BIN_GEN_PATH)] } {
set esp_bin_gen_path $::env(ESP_BIN_GEN_PATH)
} else {
set esp_bin_gen_path "$::env(PWD)/esp_bin_generator"
}
if { [info exists ::env(SIMESP_PATH)] } {
set simesp_path $::env(SIMESP_PATH)
} else {
set simesp_path "qemu-system-xtensa"
}
if { [info exists ::env(SIMESP_CPU)] } {
set simesp_cpu $::env(SIMESP_CPU)
} else {
set simesp_cpu "esp32"
}
set_board_info compiler "xtensa-${simesp_cpu}-elf-gcc"
set_board_info c++compiler "xtensa-${simesp_cpu}-elf-g++"
set_board_info cflags "-mlongcalls"
set_board_info ldflags "--specs=sim.elf.specs --specs=sys.qemu.specs -Wl,-z,noexecstack"
set_board_info use_gdb_stub 1
set_board_info gdb_protocol "remote"
set_board_info gdb,do_reload_on_run 1
set_board_info noargs 1
set_board_info gdb,noinferiorio 1
set_board_info gdb,nofileio 1
set_board_info gdb,no_long_long 1
set_board_info gdb,noresults 1
set_board_info gdb,nosignals 1
set_board_info gdb,skip_huge_test 1
set_board_info gdb,start_symbol 0x40000400
proc init_simulator { file } {
global simesp_last_load_file
global simesp_spawn_id
global simesp_cpu
global simesp_path
global timeout
if { $file == "" } {
set file $simesp_last_load_file
} else {
set simesp_last_load_file $file
}
gdb_file_cmd $file
# Close any previous simesp instance.
if { $simesp_spawn_id != "" } {
verbose -log "simesp: closing previous spawn id $simesp_spawn_id"
if [catch { close -i $simesp_spawn_id } != 0] {
warning "simesp: failed to close connection to previous simesp instance"
}
wait -i $simesp_spawn_id
set simesp_spawn_id ""
}
set cmd "spawn -noecho ${simesp_path} -nographic -monitor null -cpu ${simesp_cpu} -M ${simesp_cpu} -m 4M -S -s -kernel ${file} -d trace:gdbstub_op_start -semihosting"
verbose -log "Spawning simesp (timeout $timeout): $cmd"
for {set i 0} {$i < 10} {incr i} {
# Run simesp.
verbose -log "try to execute simesp: $i"
eval $cmd
set simesp_spawn_id $spawn_id
expect {
-i $simesp_spawn_id -re "::1234" {}
timeout {
verbose -log "simesp: timeout, closing simesp spawn id"
close -i $simesp_spawn_id
verbose -log "simesp: timeout, waiting for simesp process exit"
wait -i $simesp_spawn_id
set simesp_spawn_id ""
verbose -log "unable to start simesp: timeout"
continue
}
eof {
verbose -log "simesp: eof, waiting for simesp process exit"
wait -i $simesp_spawn_id
set simesp_spawn_id ""
verbose -log "unable to start simesp: eof"
continue
}
}
verbose -log "simesp: executed ok"
break
}
verbose -log "simesp: simesp spawned with spawn id $simesp_spawn_id, pid [exp_pid $simesp_spawn_id]"
return 0
}
proc connect_to_simesp {} {
global simesp_spawn_id
global gdb_prompt
verbose -log "simesp: connecting to remote ..."
# Connect to simesp.
send_gdb "target remote :1234\n"
gdb_expect {
-re ".*Remote debugging using :1234.*\[\r\n\]+$gdb_prompt $" {}
-re "Kill the program being debugged? (y or n)" {
send_gdb "y\n"
connect_to_simesp
}
timeout {
verbose -log "simesp: unable to connect to simesp, closing simesp spawn id"
close -i $simesp_spawn_id
verbose -log "simesp: unable to connect to simesp, waiting for simesp process exit"
wait -i $simesp_spawn_id
set simesp_spawn_id ""
error "unable to connect to simesp stub"
}
}
verbose -log "simesp: connected"
}
proc gdb_load { file } {
return [ init_simulator $file ]
}
proc gdb_run_cmd { {inferior_args {}} } {
init_simulator $inferior_args
connect_to_simesp
send_gdb "continue\n"
gdb_expect 60 {
-re "Continu\[^\r\n\]*\[\r\n\]" {}
default {}
}
return 0
}

View File

@ -0,0 +1,5 @@
*.bin
*.elf
src/*.o
*.a
*.o

View File

@ -0,0 +1,49 @@
XTENSA_TARGET ?= esp32
PREFIX := xtensa-$(XTENSA_TARGET)-elf-
CC := $(PREFIX)gcc
AR := $(PREFIX)ar
SOURCE_DIR ?= ./src
CFLAGS := -mlongcalls \
-Wall \
-Wno-unused \
-O2 -g3 \
-Wall -Wno-main \
-mtext-section-literals
LDFLAGS := -mlongcalls \
--specs=nano.specs \
--specs=nosys.specs \
-g \
-lc \
-Tesp32.rom.api.ld \
-Tesp32.rom.libgcc.ld \
-Tesp32.ld \
-Telf32xtensa.ld \
-Wl,--undefine=include_syscalls \
-Wl,--undefine=entry \
-Wl,--entry=entry
COMPILE_C = $(CC) -c $(CFLAGS) -o $@
LINK = $(CC) $(LDFLAGS) -o
APP = app
LIBESP = lib$(XTENSA_TARGET).a
all: $(LIBESP)
%.o: %.c
$(COMPILE_C) $<
$(LIBESP): $(patsubst %.c,%.o,$(wildcard $(SOURCE_DIR)/*.c))
$(AR) rcs $@ $^
$(APP): $(LIBESP) main.o
$(LINK) $(APP).elf $^ $(LIBESP)
esptool.py --chip esp32 elf2image -o $(APP).bin $(APP).elf
esptool.py --chip=esp32 merge_bin --fill-flash-size 4MB -o $(APP)4m.bin 0x1000 $(APP).bin
clean:
rm -f *.a *.o *.bin *.elf $(SOURCE_DIR)/*.o

View File

@ -0,0 +1,200 @@
/* Default linker script, for normal executables */
/* Copyright (C) 2014-2018 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
ENTRY(_start)
SEARCH_DIR("=/builds/idf/crosstool-NG/builds/xtensa-esp32-elf/xtensa-esp32-elf/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.init : { *(.rela.init) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rela.fini : { *(.rela.fini) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rela.ctors : { *(.rela.ctors) }
.rela.dtors : { *(.rela.dtors) }
.rela.got : { *(.rela.got) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rela.plt : { *(.rela.plt) }
/* .plt* sections are embedded in .text */
.text :
{
*(.got.plt* .plt*)
KEEP (*(.init.literal))
KEEP (*(SORT_NONE(.init)))
*(.literal .text .stub .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
KEEP (*(.fini.literal))
KEEP (*(SORT_NONE(.fini)))
} =0
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.got.loc : { *(.got.loc) }
.xt_except_table : ONLY_IF_RO { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.xt_except_table : ONLY_IF_RW { KEEP (*(.xt_except_table .xt_except_table.* .gnu.linkonce.e.*)) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.got : { *(.got) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.xt_except_desc :
{
*(.xt_except_desc .xt_except_desc.* .gnu.linkonce.h.*)
*(.xt_except_desc_end)
}
.lit4 :
{
PROVIDE (_lit4_start = .);
*(.lit4 .lit4.* .gnu.linkonce.lit4.*)
PROVIDE (_lit4_end = .);
}
_edata = .; PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
.xt.lit 0 : { KEEP (*(.xt.lit .xt.lit.* .gnu.linkonce.p.*)) }
.xt.insn 0 : { KEEP (*(.xt.insn .gnu.linkonce.x.*)) }
.xt.prop 0 : { KEEP (*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

View File

@ -0,0 +1,5 @@
MEMORY
{
iram0_0_seg (x) : org = 0x40080000, len = 0x20000
dram0_0_seg (rw) : org = 0x3FFB0000, len = 0x2c200
}

View File

@ -0,0 +1,2 @@
PROVIDE ( ets_write_char_uart = 0x40007cf8 );
PROVIDE ( ets_delay_us = 0x40008534 );

View File

@ -0,0 +1,94 @@
/* Unlike other ROM functions which are exported using PROVIDE, which declares
weak symbols, these libgcc functions are exported using assignment,
which declares strong symbols. This is done so that ROM functions are always
used instead of the ones provided by libgcc.a.
*/
__absvdi2 = 0x4006387c;
__absvsi2 = 0x40063868;
__adddf3 = 0x40002590;
__addsf3 = 0x400020e8;
__addvdi3 = 0x40002cbc;
__addvsi3 = 0x40002c98;
__ashldi3 = 0x4000c818;
__ashrdi3 = 0x4000c830;
__bswapdi2 = 0x40064b08;
__bswapsi2 = 0x40064ae0;
__clrsbdi2 = 0x40064b7c;
__clrsbsi2 = 0x40064b64;
__clzdi2 = 0x4000ca50;
__clzsi2 = 0x4000c7e8;
__cmpdi2 = 0x40063820;
__ctzdi2 = 0x4000ca64;
__ctzsi2 = 0x4000c7f0;
__divdc3 = 0x400645a4;
__divdf3 = 0x40002954;
__divdi3 = 0x4000ca84;
__divsi3 = 0x4000c7b8;
__eqdf2 = 0x400636a8;
__eqsf2 = 0x40063374;
__extendsfdf2 = 0x40002c34;
__ffsdi2 = 0x4000ca2c;
__ffssi2 = 0x4000c804;
__fixdfdi = 0x40002ac4;
__fixdfsi = 0x40002a78;
__fixsfdi = 0x4000244c;
__fixsfsi = 0x4000240c;
__fixunsdfsi = 0x40002b30;
__fixunssfdi = 0x40002504;
__fixunssfsi = 0x400024ac;
__floatdidf = 0x4000c988;
__floatdisf = 0x4000c8c0;
__floatsidf = 0x4000c944;
__floatsisf = 0x4000c870;
__floatundidf = 0x4000c978;
__floatundisf = 0x4000c8b0;
__floatunsidf = 0x4000c938;
__floatunsisf = 0x4000c864;
__gcc_bcmp = 0x40064a70;
__gedf2 = 0x40063768;
__gesf2 = 0x4006340c;
__gtdf2 = 0x400636dc;
__gtsf2 = 0x400633a0;
__ledf2 = 0x40063704;
__lesf2 = 0x400633c0;
__lshrdi3 = 0x4000c84c;
__ltdf2 = 0x40063790;
__ltsf2 = 0x4006342c;
__moddi3 = 0x4000cd4c;
__modsi3 = 0x4000c7c0;
__muldc3 = 0x40063c90;
__muldf3 = 0x4006358c;
__muldi3 = 0x4000c9fc;
__mulsf3 = 0x400632c8;
__mulsi3 = 0x4000c7b0;
__mulvdi3 = 0x40002d78;
__mulvsi3 = 0x40002d60;
__nedf2 = 0x400636a8;
__negdf2 = 0x400634a0;
__negdi2 = 0x4000ca14;
__negsf2 = 0x400020c0;
__negvdi2 = 0x40002e98;
__negvsi2 = 0x40002e78;
__nesf2 = 0x40063374;
__nsau_data = 0x3ff96544;
__paritysi2 = 0x40002f3c;
__popcount_tab = 0x3ff96544;
__popcountdi2 = 0x40002ef8;
__popcountsi2 = 0x40002ed0;
__powidf2 = 0x400638e4;
__subdf3 = 0x400026e4;
__subsf3 = 0x400021d0;
__subvdi3 = 0x40002d20;
__subvsi3 = 0x40002cf8;
__truncdfsf2 = 0x40002b90;
__ucmpdi2 = 0x40063840;
__udiv_w_sdiv = 0x40064bec;
__udivdi3 = 0x4000cff8;
__udivmoddi4 = 0x40064bf4;
__udivsi3 = 0x4000c7c8;
__umoddi3 = 0x4000d280;
__umodsi3 = 0x4000c7d0;
__umulsidi3 = 0x4000c7d8;
__unorddf2 = 0x400637f4;
__unordsf2 = 0x40063478;

View File

@ -0,0 +1,9 @@
#include <stdio.h>
int main() {
while(1)
{
printf("TEST\n");
}
return 0;
}

View File

@ -0,0 +1,35 @@
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
extern char _end;
extern char __bss_start;
//extern int main(int argc, const char** argv);
extern void syscalls_init(void);
extern void ets_delay_us(uint32_t us);
void entry()
{
/* give us a bit of time to connect with miniterm after esptool.py load_ram is done */
ets_delay_us(4000000);
/* try to re-initialize everything */
memset(&__bss_start, 0, &_end - &__bss_start);
syscalls_init();
main();
exit(0);
}
void usleep(uint32_t us)
{
ets_delay_us(us);
}
void sleep(uint32_t s)
{
ets_delay_us(s*1000000);
}

View File

@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/reent.h>
// #include "uart_reg.h"
// #define UART_NUM 0
void ets_write_char_uart(char c);
ssize_t _write_r(void* reent, int fildes, const void *buf, size_t nbyte)
{
const uint8_t* cbuf = (const uint8_t*) buf;
for (size_t i = 0; i < nbyte; ++i) {
ets_write_char_uart(cbuf[i]);
if (cbuf[i] == '\r') {
ets_write_char_uart('\n');
}
}
return nbyte;
}
int signal(int sig, void (*func)(void))
{
return 0;
}
static struct _reent s_reent;
struct _reent* __getreent(void) {
return _GLOBAL_REENT;
}
void syscalls_init(void)
{
_GLOBAL_REENT = &s_reent;
_REENT_INIT_PTR(&s_reent);
}
/* this is a hook used to force linking this file */
void include_syscalls(void)
{
}