From a0985e881914eb4893a85640a66b91360266f51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Sat, 31 May 2014 00:13:41 +0200 Subject: [PATCH 1/2] x86: add proper terminal for qemu-i386 This includes GNU readline features and debugging. Build with `make BOARD=qemu-i386 all-debug`. Run with `make BOARD=qemu-i386 term`. Debug with `make BOARD=qemu-i386 debug`. The default debugger is `gdb`. Also supported are `debug-tui` (GDB Text User Interface), `debug-kdbg`, and `debug-ddd`. Set a breakpoint in e.g. "startup" or "main", and hit/write "continue". The debugger can only run with a quite new toolchain (e.g. Debian testing). Ubuntu 13.10. for example will likely report a crash in GDB when switching from 16bit code to 32bit code. --- boards/qemu-i386/Makefile.include | 24 +++++- boards/qemu-i386/dist/term.py | 124 ++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100755 boards/qemu-i386/dist/term.py diff --git a/boards/qemu-i386/Makefile.include b/boards/qemu-i386/Makefile.include index 85db0b12a2..b8f48a7338 100644 --- a/boards/qemu-i386/Makefile.include +++ b/boards/qemu-i386/Makefile.include @@ -3,5 +3,27 @@ include $(RIOTBOARD)/x86-multiboot-common/Makefile.include CFLAGS += -march=i686 -mtune=i686 CFLAGS += -I$(RIOTBOARD)/qemu-i386/include -TERMPROG = qemu-system-i386 -m 512m -serial stdio -nographic -monitor /dev/null -kernel $(BINDIR)/$(APPLICATION).hex +TERMPROG = exec $(RIOTBOARD)/qemu-i386/dist/term.py "qemu-system-i386 -m 512m" $(BINDIRBASE) $(HEXFILE) + FLASHER = true + +DEBUGGER = $(TERMPROG) + +all: + +all-debug: export CFLAGS += -ggdb3 -O0 +all-debug: all + +debug-kdbg: DEBUGGER_FLAGS="kdbg -r :1234 -- $(ELFFILE)" +debug-kdbg: debug + +debug-ddd: DEBUGGER_FLAGS="ddd --eval-command='target remote :1234' $(ELFFILE)" +debug-ddd: debug + +debug-tui: DEBUGGER_FLAGS="x-terminal-emulator -e gdb -ex 'target remote :1234' -tui --args $(ELFFILE)" +debug-tui: debug + +debug-gdb: debug +DEBUGGER_FLAGS = "x-terminal-emulator -e gdb -ex 'target remote :1234' --args $(ELFFILE)" + +debug: diff --git a/boards/qemu-i386/dist/term.py b/boards/qemu-i386/dist/term.py new file mode 100755 index 0000000000..b5c3404bd1 --- /dev/null +++ b/boards/qemu-i386/dist/term.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Copyright (C) 2014 René Kijewski +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import readline +import socket +import signal +import subprocess +import sys +import threading + +from datetime import datetime +from distutils.util import split_quoted +from time import time + + +def get_timestamp(): + return datetime.fromtimestamp(time()).strftime('%Y-%m-%d %H:%M:%S.%f') + +def popen(args, **kw): + null = open(os.devnull, 'wb', 0) + return subprocess.Popen(args, stdin=null, stdout=null, stderr=null, **kw) + +def main(QEMU, BINDIRBASE, HEXFILE, DEBUGGER=None): + def run_shell(): + nonlocal result + while 1: + try: + line = input() + if line == 'quit': + result = 0 + raise EOFError() + except EOFError: + qemu.kill() + return + client_file.write((line + '\r\n').encode('UTF-8')) + + def read_terminal(): + for line in client_file: + print('{}: {}'.format(get_timestamp(), line.decode('UTF-8', 'replace').rstrip("\r\n"))) + + if isinstance(QEMU, str): + QEMU = split_quoted(QEMU) + if DEBUGGER and isinstance(DEBUGGER, str): + DEBUGGER = split_quoted(DEBUGGER) + + histfile = os.path.join(BINDIRBASE, '.qemu-term.hist') + try: + readline.read_history_file(histfile) + except IOError: + pass + + result = 1 + try: + sock = socket.socket() + sock.settimeout(5) + sock.bind(('', 0)) + sock.listen(1) + host, port = sock.getsockname() + + args = QEMU + [ + '-serial', 'tcp:{}:{}'.format(host, port), + '-nographic', + '-monitor', '/dev/null', + '-kernel', HEXFILE, + ] + if DEBUGGER: + args += ['-s', '-S'] + + try: + qemu = popen(args) + + if DEBUGGER: + ignore_sig_int = lambda: signal.signal(signal.SIGINT, signal.SIG_IGN) + popen(DEBUGGER, preexec_fn=ignore_sig_int) + + client_sock, _ = sock.accept() + client_file = client_sock.makefile('rwb', 1) + sock.close() + + threading.Thread(target=run_shell, daemon=True).start() + threading.Thread(target=read_terminal, daemon=True).start() + + try: + result = qemu.wait() and result + except KeyboardInterrupt: + print('Interrupted ...') + result = 0 + finally: + try: + qemu.kill() + except: + pass + finally: + try: + readline.write_history_file(histfile) + except: + pass + + try: + client_sock.close() + except: + pass + return result + + +if __name__ == '__main__': + print("Type 'exit' to exit.") + sys.exit(main(*sys.argv[1:])) From 6a75a14ce51255ec81349d5d8b112246e39e96cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Sat, 7 Jun 2014 03:13:55 +0200 Subject: [PATCH 2/2] x86: garbage collect section if not debugging --- boards/qemu-i386/Makefile.include | 5 +---- boards/x86-multiboot-common/Makefile.include | 16 +++++++++++----- boards/x86-multiboot-common/linker.ld | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/boards/qemu-i386/Makefile.include b/boards/qemu-i386/Makefile.include index b8f48a7338..1413f9b392 100644 --- a/boards/qemu-i386/Makefile.include +++ b/boards/qemu-i386/Makefile.include @@ -11,9 +11,6 @@ DEBUGGER = $(TERMPROG) all: -all-debug: export CFLAGS += -ggdb3 -O0 -all-debug: all - debug-kdbg: DEBUGGER_FLAGS="kdbg -r :1234 -- $(ELFFILE)" debug-kdbg: debug @@ -26,4 +23,4 @@ debug-tui: debug debug-gdb: debug DEBUGGER_FLAGS = "x-terminal-emulator -e gdb -ex 'target remote :1234' --args $(ELFFILE)" -debug: +debug: diff --git a/boards/x86-multiboot-common/Makefile.include b/boards/x86-multiboot-common/Makefile.include index 87937b1c4d..f868a6bb95 100644 --- a/boards/x86-multiboot-common/Makefile.include +++ b/boards/x86-multiboot-common/Makefile.include @@ -55,12 +55,18 @@ export OFLAGS = -O binary LINKFLAGS += -m32 -nostdlib -nostdinc -nostartfiles -nodefaultlibs \ --prefix=$(NEWLIB_BASE) \ -Wl,-rpath,$(NEWLIB_BASE)/lib \ - -T $(RIOTBASE)/boards/x86-multiboot-common/linker.ld + -T$(RIOTBASE)/boards/x86-multiboot-common/linker.ld UNDEF += $(BINDIR)x86-multiboot-common_base/startup.o -#CFLAGS += -ffunction-sections -fdata-sections -#LINKFLAGS += -Wl,--gc-sections -#CFLAGS += -Wall -Wextra -Werror -pedantic -pedantic-errors \ - BASELIBS += $(NEWLIB_BASE)/lib/libc.a \ $(NEWLIB_BASE)/lib/libm.a + +all: + +all-debug: export CFLAGS += -ggdb3 -O0 +all-debug: all + +ifeq (, $(filter all-debug, $(MAKECMDGOALS))) + CFLAGS += -Os -ffunction-sections -fdata-sections + LINKFLAGS += -Wl,--gc-sections +endif diff --git a/boards/x86-multiboot-common/linker.ld b/boards/x86-multiboot-common/linker.ld index 2a9f0a2a85..e6e1fb08b9 100644 --- a/boards/x86-multiboot-common/linker.ld +++ b/boards/x86-multiboot-common/linker.ld @@ -34,7 +34,7 @@ SECTIONS Next we'll put the .text section. */ ._multiboot_header : { - *(._multiboot_header) + KEEP(*(._multiboot_header)) } .note.gnu.build-id :