debuggers: import openocd-0.7.0
Initial check-in of openocd-0.7.0 as it can be downloaded from http://sourceforge.net/projects/openocd/files/openocd/0.7.0/ Any modifications will follow. Change-Id: I6949beaefd589e046395ea0cb80f4e1ab1654d55
This commit is contained in:
23
debuggers/openocd/src/server/Makefile.am
Normal file
23
debuggers/openocd/src/server/Makefile.am
Normal file
@ -0,0 +1,23 @@
|
||||
include $(top_srcdir)/common.mk
|
||||
|
||||
METASOURCES = AUTO
|
||||
noinst_LTLIBRARIES = libserver.la
|
||||
noinst_HEADERS = server.h telnet_server.h gdb_server.h
|
||||
libserver_la_SOURCES = server.c telnet_server.c gdb_server.c
|
||||
|
||||
libserver_la_SOURCES += server_stubs.c
|
||||
|
||||
libserver_la_CFLAGS =
|
||||
if IS_MINGW
|
||||
# FD_* macros are sloppy with their signs on MinGW32 platform
|
||||
libserver_la_CFLAGS += -Wno-sign-compare
|
||||
endif
|
||||
|
||||
# tcl server addons
|
||||
noinst_HEADERS += tcl_server.h
|
||||
libserver_la_SOURCES += tcl_server.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
startup.tcl
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
615
debuggers/openocd/src/server/Makefile.in
Normal file
615
debuggers/openocd/src/server/Makefile.in
Normal file
@ -0,0 +1,615 @@
|
||||
# Makefile.in generated by automake 1.13.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2012 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__make_dryrun = \
|
||||
{ \
|
||||
am__dry=no; \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
|
||||
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
|
||||
*) \
|
||||
for am__flg in $$MAKEFLAGS; do \
|
||||
case $$am__flg in \
|
||||
*=*|--*) ;; \
|
||||
*n*) am__dry=yes; break;; \
|
||||
esac; \
|
||||
done;; \
|
||||
esac; \
|
||||
test $$am__dry = yes; \
|
||||
}
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
DIST_COMMON = $(top_srcdir)/common.mk $(srcdir)/Makefile.in \
|
||||
$(srcdir)/Makefile.am $(top_srcdir)/depcomp $(noinst_HEADERS)
|
||||
@INTERNAL_JIMTCL_TRUE@am__append_1 = -I$(top_srcdir)/jimtcl \
|
||||
@INTERNAL_JIMTCL_TRUE@ -I$(top_builddir)/jimtcl
|
||||
|
||||
# FD_* macros are sloppy with their signs on MinGW32 platform
|
||||
@IS_MINGW_TRUE@am__append_2 = -Wno-sign-compare
|
||||
subdir = src/server
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/config_subdir.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libserver_la_LIBADD =
|
||||
am_libserver_la_OBJECTS = libserver_la-server.lo \
|
||||
libserver_la-telnet_server.lo libserver_la-gdb_server.lo \
|
||||
libserver_la-server_stubs.lo libserver_la-tcl_server.lo
|
||||
libserver_la_OBJECTS = $(am_libserver_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
libserver_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libserver_la_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(libserver_la_SOURCES)
|
||||
DIST_SOURCES = $(libserver_la_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CC_FOR_BUILD = @CC_FOR_BUILD@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
doxygen_as_html = @doxygen_as_html@
|
||||
doxygen_as_pdf = @doxygen_as_pdf@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
# common flags used in openocd build
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/src/helper -DPKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DPKGLIBDIR=\"$(pkglibdir)\" $(am__append_1)
|
||||
METASOURCES = AUTO
|
||||
noinst_LTLIBRARIES = libserver.la
|
||||
|
||||
# tcl server addons
|
||||
noinst_HEADERS = server.h telnet_server.h gdb_server.h tcl_server.h
|
||||
libserver_la_SOURCES = server.c telnet_server.c gdb_server.c \
|
||||
server_stubs.c tcl_server.c
|
||||
libserver_la_CFLAGS = $(am__append_2)
|
||||
EXTRA_DIST = \
|
||||
startup.tcl
|
||||
|
||||
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/server/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/server/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
$(top_srcdir)/common.mk:
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; \
|
||||
locs=`for p in $$list; do echo $$p; done | \
|
||||
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
|
||||
sort -u`; \
|
||||
test -z "$$locs" || { \
|
||||
echo rm -f $${locs}; \
|
||||
rm -f $${locs}; \
|
||||
}
|
||||
libserver.la: $(libserver_la_OBJECTS) $(libserver_la_DEPENDENCIES) $(EXTRA_libserver_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libserver_la_LINK) $(libserver_la_OBJECTS) $(libserver_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-gdb_server.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-server.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-server_stubs.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-tcl_server.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libserver_la-telnet_server.Plo@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
libserver_la-server.lo: server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-server.lo -MD -MP -MF $(DEPDIR)/libserver_la-server.Tpo -c -o libserver_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-server.Tpo $(DEPDIR)/libserver_la-server.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='libserver_la-server.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
|
||||
libserver_la-telnet_server.lo: telnet_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-telnet_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-telnet_server.Tpo -c -o libserver_la-telnet_server.lo `test -f 'telnet_server.c' || echo '$(srcdir)/'`telnet_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-telnet_server.Tpo $(DEPDIR)/libserver_la-telnet_server.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='telnet_server.c' object='libserver_la-telnet_server.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-telnet_server.lo `test -f 'telnet_server.c' || echo '$(srcdir)/'`telnet_server.c
|
||||
|
||||
libserver_la-gdb_server.lo: gdb_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-gdb_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-gdb_server.Tpo -c -o libserver_la-gdb_server.lo `test -f 'gdb_server.c' || echo '$(srcdir)/'`gdb_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-gdb_server.Tpo $(DEPDIR)/libserver_la-gdb_server.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gdb_server.c' object='libserver_la-gdb_server.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-gdb_server.lo `test -f 'gdb_server.c' || echo '$(srcdir)/'`gdb_server.c
|
||||
|
||||
libserver_la-server_stubs.lo: server_stubs.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-server_stubs.lo -MD -MP -MF $(DEPDIR)/libserver_la-server_stubs.Tpo -c -o libserver_la-server_stubs.lo `test -f 'server_stubs.c' || echo '$(srcdir)/'`server_stubs.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-server_stubs.Tpo $(DEPDIR)/libserver_la-server_stubs.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server_stubs.c' object='libserver_la-server_stubs.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-server_stubs.lo `test -f 'server_stubs.c' || echo '$(srcdir)/'`server_stubs.c
|
||||
|
||||
libserver_la-tcl_server.lo: tcl_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -MT libserver_la-tcl_server.lo -MD -MP -MF $(DEPDIR)/libserver_la-tcl_server.Tpo -c -o libserver_la-tcl_server.lo `test -f 'tcl_server.c' || echo '$(srcdir)/'`tcl_server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libserver_la-tcl_server.Tpo $(DEPDIR)/libserver_la-tcl_server.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcl_server.c' object='libserver_la-tcl_server.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libserver_la_CFLAGS) $(CFLAGS) -c -o libserver_la-tcl_server.lo `test -f 'tcl_server.c' || echo '$(srcdir)/'`tcl_server.c
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
|
||||
ctags-am distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
2436
debuggers/openocd/src/server/gdb_server.c
Normal file
2436
debuggers/openocd/src/server/gdb_server.c
Normal file
File diff suppressed because it is too large
Load Diff
53
debuggers/openocd/src/server/gdb_server.h
Normal file
53
debuggers/openocd/src/server/gdb_server.h
Normal file
@ -0,0 +1,53 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007-2009 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* Copyright (C) 2011 by Broadcom Corporation *
|
||||
* Evan Hunter - ehunter@broadcom.com *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GDB_SERVER_H
|
||||
#define GDB_SERVER_H
|
||||
|
||||
struct image;
|
||||
struct reg;
|
||||
#include <target/target.h>
|
||||
|
||||
#define GDB_BUFFER_SIZE 16384
|
||||
|
||||
int gdb_target_add_all(struct target *target);
|
||||
int gdb_register_commands(struct command_context *command_context);
|
||||
|
||||
int gdb_put_packet(struct connection *connection, char *buffer, int len);
|
||||
|
||||
static inline struct target *get_target_from_connection(struct connection *connection)
|
||||
{
|
||||
struct gdb_service *gdb_service = connection->service->priv;
|
||||
return gdb_service->target;
|
||||
}
|
||||
|
||||
#define ERROR_GDB_BUFFER_TOO_SMALL (-800)
|
||||
#define ERROR_GDB_TIMEOUT (-801)
|
||||
|
||||
#endif /* GDB_SERVER_H */
|
||||
655
debuggers/openocd/src/server/server.c
Normal file
655
debuggers/openocd/src/server/server.c
Normal file
@ -0,0 +1,655 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007-2010 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "server.h"
|
||||
#include <target/target.h>
|
||||
#include <target/target_request.h>
|
||||
#include "openocd.h"
|
||||
#include "tcl_server.h"
|
||||
#include "telnet_server.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
static struct service *services;
|
||||
|
||||
/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
|
||||
static int shutdown_openocd;
|
||||
|
||||
static int add_connection(struct service *service, struct command_context *cmd_ctx)
|
||||
{
|
||||
socklen_t address_size;
|
||||
struct connection *c, **p;
|
||||
int retval;
|
||||
int flag = 1;
|
||||
|
||||
c = malloc(sizeof(struct connection));
|
||||
c->fd = -1;
|
||||
c->fd_out = -1;
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->cmd_ctx = copy_command_context(cmd_ctx);
|
||||
c->service = service;
|
||||
c->input_pending = 0;
|
||||
c->priv = NULL;
|
||||
c->next = NULL;
|
||||
|
||||
if (service->type == CONNECTION_TCP) {
|
||||
address_size = sizeof(c->sin);
|
||||
|
||||
c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
|
||||
c->fd_out = c->fd;
|
||||
|
||||
/* This increases performance dramatically for e.g. GDB load which
|
||||
* does not have a sliding window protocol.
|
||||
*
|
||||
* Ignore errors from this fn as it probably just means less performance
|
||||
*/
|
||||
setsockopt(c->fd, /* socket affected */
|
||||
IPPROTO_TCP, /* set option at TCP level */
|
||||
TCP_NODELAY, /* name of option */
|
||||
(char *)&flag, /* the cast is historical cruft */
|
||||
sizeof(int)); /* length of option value */
|
||||
|
||||
LOG_INFO("accepting '%s' connection from %s", service->name, service->port);
|
||||
retval = service->new_connection(c);
|
||||
if (retval != ERROR_OK) {
|
||||
close_socket(c->fd);
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
command_done(c->cmd_ctx);
|
||||
free(c);
|
||||
return retval;
|
||||
}
|
||||
} else if (service->type == CONNECTION_STDINOUT) {
|
||||
c->fd = service->fd;
|
||||
c->fd_out = fileno(stdout);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* we are using stdin/out so ignore ctrl-c under windoze */
|
||||
SetConsoleCtrlHandler(NULL, TRUE);
|
||||
#endif
|
||||
|
||||
/* do not check for new connections again on stdin */
|
||||
service->fd = -1;
|
||||
|
||||
LOG_INFO("accepting '%s' connection from pipe", service->name);
|
||||
retval = service->new_connection(c);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
command_done(c->cmd_ctx);
|
||||
free(c);
|
||||
return retval;
|
||||
}
|
||||
} else if (service->type == CONNECTION_PIPE) {
|
||||
c->fd = service->fd;
|
||||
/* do not check for new connections again on stdin */
|
||||
service->fd = -1;
|
||||
|
||||
char *out_file = alloc_printf("%so", service->port);
|
||||
c->fd_out = open(out_file, O_WRONLY);
|
||||
free(out_file);
|
||||
if (c->fd_out == -1) {
|
||||
LOG_ERROR("could not open %s", service->port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
|
||||
retval = service->new_connection(c);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("attempted '%s' connection rejected", service->name);
|
||||
command_done(c->cmd_ctx);
|
||||
free(c);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &service->connections; *p; p = &(*p)->next)
|
||||
;
|
||||
*p = c;
|
||||
|
||||
service->max_connections--;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int remove_connection(struct service *service, struct connection *connection)
|
||||
{
|
||||
struct connection **p = &service->connections;
|
||||
struct connection *c;
|
||||
|
||||
/* find connection */
|
||||
while ((c = *p)) {
|
||||
if (c->fd == connection->fd) {
|
||||
service->connection_closed(c);
|
||||
if (service->type == CONNECTION_TCP)
|
||||
close_socket(c->fd);
|
||||
else if (service->type == CONNECTION_PIPE) {
|
||||
/* The service will listen to the pipe again */
|
||||
c->service->fd = c->fd;
|
||||
}
|
||||
|
||||
command_done(c->cmd_ctx);
|
||||
|
||||
/* delete connection */
|
||||
*p = c->next;
|
||||
free(c);
|
||||
|
||||
service->max_connections++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* redirect p to next list pointer */
|
||||
p = &(*p)->next;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* FIX! make service return error instead of invoking exit() */
|
||||
int add_service(char *name,
|
||||
const char *port,
|
||||
int max_connections,
|
||||
new_connection_handler_t new_connection_handler,
|
||||
input_handler_t input_handler,
|
||||
connection_closed_handler_t connection_closed_handler,
|
||||
void *priv)
|
||||
{
|
||||
struct service *c, **p;
|
||||
int so_reuseaddr_option = 1;
|
||||
|
||||
c = malloc(sizeof(struct service));
|
||||
|
||||
c->name = strdup(name);
|
||||
c->port = strdup(port);
|
||||
c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */
|
||||
c->fd = -1;
|
||||
c->connections = NULL;
|
||||
c->new_connection = new_connection_handler;
|
||||
c->input = input_handler;
|
||||
c->connection_closed = connection_closed_handler;
|
||||
c->priv = priv;
|
||||
c->next = NULL;
|
||||
long portnumber;
|
||||
if (strcmp(c->port, "pipe") == 0)
|
||||
c->type = CONNECTION_STDINOUT;
|
||||
else {
|
||||
char *end;
|
||||
portnumber = strtol(c->port, &end, 0);
|
||||
if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) {
|
||||
c->portnumber = portnumber;
|
||||
c->type = CONNECTION_TCP;
|
||||
} else
|
||||
c->type = CONNECTION_PIPE;
|
||||
}
|
||||
|
||||
if (c->type == CONNECTION_TCP) {
|
||||
c->max_connections = max_connections;
|
||||
|
||||
c->fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (c->fd == -1) {
|
||||
LOG_ERROR("error creating socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
setsockopt(c->fd,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
(void *)&so_reuseaddr_option,
|
||||
sizeof(int));
|
||||
|
||||
socket_nonblock(c->fd);
|
||||
|
||||
memset(&c->sin, 0, sizeof(c->sin));
|
||||
c->sin.sin_family = AF_INET;
|
||||
c->sin.sin_addr.s_addr = INADDR_ANY;
|
||||
c->sin.sin_port = htons(c->portnumber);
|
||||
|
||||
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
|
||||
LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
int segsize = 65536;
|
||||
setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int));
|
||||
#endif
|
||||
int window_size = 128 * 1024;
|
||||
|
||||
/* These setsockopt()s must happen before the listen() */
|
||||
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&window_size, sizeof(window_size));
|
||||
|
||||
if (listen(c->fd, 1) == -1) {
|
||||
LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
} else if (c->type == CONNECTION_STDINOUT) {
|
||||
c->fd = fileno(stdin);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* for win32 set stdin/stdout to binary mode */
|
||||
if (_setmode(_fileno(stdout), _O_BINARY) < 0)
|
||||
LOG_WARNING("cannot change stdout mode to binary");
|
||||
if (_setmode(_fileno(stdin), _O_BINARY) < 0)
|
||||
LOG_WARNING("cannot change stdin mode to binary");
|
||||
if (_setmode(_fileno(stderr), _O_BINARY) < 0)
|
||||
LOG_WARNING("cannot change stderr mode to binary");
|
||||
#else
|
||||
socket_nonblock(c->fd);
|
||||
#endif
|
||||
} else if (c->type == CONNECTION_PIPE) {
|
||||
#ifdef _WIN32
|
||||
/* we currenty do not support named pipes under win32
|
||||
* so exit openocd for now */
|
||||
LOG_ERROR("Named pipes currently not supported under this os");
|
||||
exit(1);
|
||||
#else
|
||||
/* Pipe we're reading from */
|
||||
c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
|
||||
if (c->fd == -1) {
|
||||
LOG_ERROR("could not open %s", c->port);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* add to the end of linked list */
|
||||
for (p = &services; *p; p = &(*p)->next)
|
||||
;
|
||||
*p = c;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int remove_services(void)
|
||||
{
|
||||
struct service *c = services;
|
||||
|
||||
/* loop service */
|
||||
while (c) {
|
||||
struct service *next = c->next;
|
||||
|
||||
if (c->name)
|
||||
free((void *)c->name);
|
||||
|
||||
if (c->type == CONNECTION_PIPE) {
|
||||
if (c->fd != -1)
|
||||
close(c->fd);
|
||||
}
|
||||
if (c->port)
|
||||
free((void *)c->port);
|
||||
|
||||
if (c->priv)
|
||||
free(c->priv);
|
||||
|
||||
/* delete service */
|
||||
free(c);
|
||||
|
||||
/* remember the last service for unlinking */
|
||||
c = next;
|
||||
}
|
||||
|
||||
services = NULL;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_loop(struct command_context *command_context)
|
||||
{
|
||||
struct service *service;
|
||||
|
||||
bool poll_ok = true;
|
||||
|
||||
/* used in select() */
|
||||
fd_set read_fds;
|
||||
int fd_max;
|
||||
|
||||
/* used in accept() */
|
||||
int retval;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
|
||||
#endif
|
||||
|
||||
while (!shutdown_openocd) {
|
||||
/* monitor sockets for activity */
|
||||
fd_max = 0;
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* add service and connection fds to read_fds */
|
||||
for (service = services; service; service = service->next) {
|
||||
if (service->fd != -1) {
|
||||
/* listen for new connections */
|
||||
FD_SET(service->fd, &read_fds);
|
||||
|
||||
if (service->fd > fd_max)
|
||||
fd_max = service->fd;
|
||||
}
|
||||
|
||||
if (service->connections) {
|
||||
struct connection *c;
|
||||
|
||||
for (c = service->connections; c; c = c->next) {
|
||||
/* check for activity on the connection */
|
||||
FD_SET(c->fd, &read_fds);
|
||||
if (c->fd > fd_max)
|
||||
fd_max = c->fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
if (poll_ok) {
|
||||
/* we're just polling this iteration, this is faster on embedded
|
||||
* hosts */
|
||||
tv.tv_usec = 0;
|
||||
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
|
||||
} else {
|
||||
/* Every 100ms */
|
||||
tv.tv_usec = 100000;
|
||||
/* Only while we're sleeping we'll let others run */
|
||||
openocd_sleep_prelude();
|
||||
kept_alive();
|
||||
retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
|
||||
openocd_sleep_postlude();
|
||||
}
|
||||
|
||||
if (retval == -1) {
|
||||
#ifdef _WIN32
|
||||
|
||||
errno = WSAGetLastError();
|
||||
|
||||
if (errno == WSAEINTR)
|
||||
FD_ZERO(&read_fds);
|
||||
else {
|
||||
LOG_ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
|
||||
if (errno == EINTR)
|
||||
FD_ZERO(&read_fds);
|
||||
else {
|
||||
LOG_ERROR("error during select: %s", strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (retval == 0) {
|
||||
/* We only execute these callbacks when there was nothing to do or we timed
|
||||
*out */
|
||||
target_call_timer_callbacks();
|
||||
process_jim_events(command_context);
|
||||
|
||||
FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case! */
|
||||
|
||||
/* We timed out/there was nothing to do, timeout rather than poll next time
|
||||
**/
|
||||
poll_ok = false;
|
||||
} else {
|
||||
/* There was something to do, next time we'll just poll */
|
||||
poll_ok = true;
|
||||
}
|
||||
|
||||
/* This is a simple back-off algorithm where we immediately
|
||||
* re-poll if we did something this time around.
|
||||
*
|
||||
* This greatly improves performance of DCC.
|
||||
*/
|
||||
poll_ok = poll_ok || target_got_message();
|
||||
|
||||
for (service = services; service; service = service->next) {
|
||||
/* handle new connections on listeners */
|
||||
if ((service->fd != -1)
|
||||
&& (FD_ISSET(service->fd, &read_fds))) {
|
||||
if (service->max_connections > 0)
|
||||
add_connection(service, command_context);
|
||||
else {
|
||||
if (service->type == CONNECTION_TCP) {
|
||||
struct sockaddr_in sin;
|
||||
socklen_t address_size = sizeof(sin);
|
||||
int tmp_fd;
|
||||
tmp_fd = accept(service->fd,
|
||||
(struct sockaddr *)&service->sin,
|
||||
&address_size);
|
||||
close_socket(tmp_fd);
|
||||
}
|
||||
LOG_INFO(
|
||||
"rejected '%s' connection, no more connections allowed",
|
||||
service->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle activity on connections */
|
||||
if (service->connections) {
|
||||
struct connection *c;
|
||||
|
||||
for (c = service->connections; c; ) {
|
||||
if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) {
|
||||
retval = service->input(c);
|
||||
if (retval != ERROR_OK) {
|
||||
struct connection *next = c->next;
|
||||
if (service->type == CONNECTION_PIPE ||
|
||||
service->type == CONNECTION_STDINOUT) {
|
||||
/* if connection uses a pipe then
|
||||
* shutdown openocd on error */
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
remove_connection(service, c);
|
||||
LOG_INFO("dropped '%s' connection",
|
||||
service->name);
|
||||
c = next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT)
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sig_handler(int sig)
|
||||
{
|
||||
shutdown_openocd = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int server_preinit(void)
|
||||
{
|
||||
/* this currently only calls WSAStartup on native win32 systems
|
||||
* before any socket operations are performed.
|
||||
* This is an issue if you call init in your config script */
|
||||
|
||||
#ifdef _WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
|
||||
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
|
||||
LOG_ERROR("Failed to Open Winsock");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* register ctrl-c handler */
|
||||
SetConsoleCtrlHandler(ControlHandler, TRUE);
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGBREAK, sig_handler);
|
||||
signal(SIGABRT, sig_handler);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int server_init(struct command_context *cmd_ctx)
|
||||
{
|
||||
int ret = tcl_init();
|
||||
if (ERROR_OK != ret)
|
||||
return ret;
|
||||
|
||||
return telnet_init("Open On-Chip Debugger");
|
||||
}
|
||||
|
||||
int server_quit(void)
|
||||
{
|
||||
remove_services();
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
SetConsoleCtrlHandler(ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int connection_write(struct connection *connection, const void *data, int len)
|
||||
{
|
||||
if (len == 0) {
|
||||
/* successful no-op. Sockets and pipes behave differently here... */
|
||||
return 0;
|
||||
}
|
||||
if (connection->service->type == CONNECTION_TCP)
|
||||
return write_socket(connection->fd_out, data, len);
|
||||
else
|
||||
return write(connection->fd_out, data, len);
|
||||
}
|
||||
|
||||
int connection_read(struct connection *connection, void *data, int len)
|
||||
{
|
||||
if (connection->service->type == CONNECTION_TCP)
|
||||
return read_socket(connection->fd, data, len);
|
||||
else
|
||||
return read(connection->fd, data, len);
|
||||
}
|
||||
|
||||
/* tell the server we want to shut down */
|
||||
COMMAND_HANDLER(handle_shutdown_command)
|
||||
{
|
||||
LOG_USER("shutdown command invoked");
|
||||
|
||||
shutdown_openocd = 1;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration server_command_handlers[] = {
|
||||
{
|
||||
.name = "shutdown",
|
||||
.handler = &handle_shutdown_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "",
|
||||
.help = "shut the server down",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
int server_register_commands(struct command_context *cmd_ctx)
|
||||
{
|
||||
int retval = telnet_register_commands(cmd_ctx);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
retval = tcl_register_commands(cmd_ctx);
|
||||
if (ERROR_OK != retval)
|
||||
return retval;
|
||||
|
||||
return register_commands(cmd_ctx, NULL, server_command_handlers);
|
||||
}
|
||||
|
||||
SERVER_PORT_COMMAND()
|
||||
{
|
||||
switch (CMD_ARGC) {
|
||||
case 0:
|
||||
command_print(CMD_CTX, "%d", *out);
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
uint16_t port;
|
||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
|
||||
*out = port;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
SERVER_PIPE_COMMAND()
|
||||
{
|
||||
switch (CMD_ARGC) {
|
||||
case 0:
|
||||
command_print(CMD_CTX, "%s", *out);
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
if (CMD_CTX->mode == COMMAND_EXEC) {
|
||||
LOG_WARNING("unable to change server port after init");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
const char *t = strdup(CMD_ARGV[0]);
|
||||
free((void *)*out);
|
||||
*out = t;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
116
debuggers/openocd/src/server/server.h
Normal file
116
debuggers/openocd/src/server/server.h
Normal file
@ -0,0 +1,116 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include <helper/log.h>
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
enum connection_type {
|
||||
CONNECTION_TCP,
|
||||
CONNECTION_PIPE,
|
||||
CONNECTION_STDINOUT
|
||||
};
|
||||
|
||||
struct connection {
|
||||
int fd;
|
||||
int fd_out; /* When using pipes we're writing to a different fd */
|
||||
struct sockaddr_in sin;
|
||||
struct command_context *cmd_ctx;
|
||||
struct service *service;
|
||||
int input_pending;
|
||||
void *priv;
|
||||
struct connection *next;
|
||||
};
|
||||
|
||||
typedef int (*new_connection_handler_t)(struct connection *connection);
|
||||
typedef int (*input_handler_t)(struct connection *connection);
|
||||
typedef int (*connection_closed_handler_t)(struct connection *connection);
|
||||
|
||||
struct service {
|
||||
const char *name;
|
||||
enum connection_type type;
|
||||
const char *port;
|
||||
unsigned short portnumber;
|
||||
int fd;
|
||||
struct sockaddr_in sin;
|
||||
int max_connections;
|
||||
struct connection *connections;
|
||||
new_connection_handler_t new_connection;
|
||||
input_handler_t input;
|
||||
connection_closed_handler_t connection_closed;
|
||||
void *priv;
|
||||
struct service *next;
|
||||
};
|
||||
|
||||
int add_service(char *name, const char *port,
|
||||
int max_connections, new_connection_handler_t new_connection_handler,
|
||||
input_handler_t in_handler, connection_closed_handler_t close_handler,
|
||||
void *priv);
|
||||
|
||||
int server_preinit(void);
|
||||
int server_init(struct command_context *cmd_ctx);
|
||||
int server_quit(void);
|
||||
|
||||
int server_loop(struct command_context *command_context);
|
||||
|
||||
int server_register_commands(struct command_context *context);
|
||||
|
||||
int connection_write(struct connection *connection, const void *data, int len);
|
||||
int connection_read(struct connection *connection, void *data, int len);
|
||||
|
||||
/**
|
||||
* Used by server_loop(), defined in server_stubs.c
|
||||
*/
|
||||
void openocd_sleep_prelude(void);
|
||||
/**
|
||||
* Used by server_loop(), defined in server_stubs.c
|
||||
*/
|
||||
void openocd_sleep_postlude(void);
|
||||
|
||||
/**
|
||||
* Defines an extended command handler function declaration to enable
|
||||
* access to (and manipulation of) the server port number.
|
||||
* Call server_port like a normal COMMAND_HANDLER with an extra @a out parameter
|
||||
* to receive the specified port number.
|
||||
*/
|
||||
#define SERVER_PIPE_COMMAND() \
|
||||
COMMAND_HELPER(server_pipe_command, const char **out)
|
||||
SERVER_PIPE_COMMAND();
|
||||
|
||||
#define SERVER_PORT_COMMAND() \
|
||||
COMMAND_HELPER(server_port_command, unsigned short *out)
|
||||
|
||||
SERVER_PORT_COMMAND();
|
||||
|
||||
#define ERROR_SERVER_REMOTE_CLOSED (-400)
|
||||
#define ERROR_CONNECTION_REJECTED (-401)
|
||||
|
||||
#endif /* SERVER_H */
|
||||
32
debuggers/openocd/src/server/server_stubs.c
Normal file
32
debuggers/openocd/src/server/server_stubs.c
Normal file
@ -0,0 +1,32 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "server.h"
|
||||
|
||||
void openocd_sleep_prelude(void)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
void openocd_sleep_postlude(void)
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
10
debuggers/openocd/src/server/startup.tcl
Normal file
10
debuggers/openocd/src/server/startup.tcl
Normal file
@ -0,0 +1,10 @@
|
||||
# Defines basic Tcl procs for OpenOCD server modules
|
||||
|
||||
# Handle GDB 'R' packet. Can be overridden by configuration script,
|
||||
# but it's not something one would expect target scripts to do
|
||||
# normally
|
||||
proc ocd_gdb_restart {target_id} {
|
||||
# Fix!!! we're resetting all targets here! Really we should reset only
|
||||
# one target
|
||||
reset halt
|
||||
}
|
||||
192
debuggers/openocd/src/server/tcl_server.c
Normal file
192
debuggers/openocd/src/server/tcl_server.c
Normal file
@ -0,0 +1,192 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2010 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tcl_server.h"
|
||||
|
||||
#define TCL_SERVER_VERSION "TCL Server 0.1"
|
||||
#define TCL_MAX_LINE (4096)
|
||||
|
||||
struct tcl_connection {
|
||||
int tc_linedrop;
|
||||
int tc_lineoffset;
|
||||
char tc_line[TCL_MAX_LINE];
|
||||
int tc_outerror;/* flag an output error */
|
||||
};
|
||||
|
||||
static const char *tcl_port;
|
||||
|
||||
/* handlers */
|
||||
static int tcl_new_connection(struct connection *connection);
|
||||
static int tcl_input(struct connection *connection);
|
||||
static int tcl_output(struct connection *connection, const void *buf, ssize_t len);
|
||||
static int tcl_closed(struct connection *connection);
|
||||
|
||||
/* write data out to a socket.
|
||||
*
|
||||
* this is a blocking write, so the return value must equal the length, if
|
||||
* that is not the case then flag the connection with an output error.
|
||||
*/
|
||||
int tcl_output(struct connection *connection, const void *data, ssize_t len)
|
||||
{
|
||||
ssize_t wlen;
|
||||
struct tcl_connection *tclc;
|
||||
|
||||
tclc = connection->priv;
|
||||
if (tclc->tc_outerror)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
wlen = connection_write(connection, data, len);
|
||||
|
||||
if (wlen == len)
|
||||
return ERROR_OK;
|
||||
|
||||
LOG_ERROR("error during write: %d != %d", (int)wlen, (int)len);
|
||||
tclc->tc_outerror = 1;
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
/* connections */
|
||||
static int tcl_new_connection(struct connection *connection)
|
||||
{
|
||||
struct tcl_connection *tclc;
|
||||
|
||||
tclc = malloc(sizeof(struct tcl_connection));
|
||||
if (tclc == NULL)
|
||||
return ERROR_CONNECTION_REJECTED;
|
||||
|
||||
memset(tclc, 0, sizeof(struct tcl_connection));
|
||||
connection->priv = tclc;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int tcl_input(struct connection *connection)
|
||||
{
|
||||
Jim_Interp *interp = (Jim_Interp *)connection->cmd_ctx->interp;
|
||||
int retval;
|
||||
int i;
|
||||
ssize_t rlen;
|
||||
const char *result;
|
||||
int reslen;
|
||||
struct tcl_connection *tclc;
|
||||
unsigned char in[256];
|
||||
|
||||
rlen = connection_read(connection, &in, sizeof(in));
|
||||
if (rlen <= 0) {
|
||||
if (rlen < 0)
|
||||
LOG_ERROR("error during read: %s", strerror(errno));
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
tclc = connection->priv;
|
||||
if (tclc == NULL)
|
||||
return ERROR_CONNECTION_REJECTED;
|
||||
|
||||
/* push as much data into the line as possible */
|
||||
for (i = 0; i < rlen; i++) {
|
||||
/* buffer the data */
|
||||
tclc->tc_line[tclc->tc_lineoffset] = in[i];
|
||||
if (tclc->tc_lineoffset < TCL_MAX_LINE)
|
||||
tclc->tc_lineoffset++;
|
||||
else
|
||||
tclc->tc_linedrop = 1;
|
||||
|
||||
/* ctrl-z is end of command. When testing from telnet, just
|
||||
* press ctrl-z a couple of times first to put telnet into the
|
||||
* mode where it will send 0x1a in response to pressing ctrl-z
|
||||
*/
|
||||
if (in[i] != '\x1a')
|
||||
continue;
|
||||
|
||||
/* process the line */
|
||||
if (tclc->tc_linedrop) {
|
||||
#define ESTR "line too long\n"
|
||||
retval = tcl_output(connection, ESTR, sizeof(ESTR));
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
#undef ESTR
|
||||
} else {
|
||||
tclc->tc_line[tclc->tc_lineoffset-1] = '\0';
|
||||
LOG_DEBUG("Executing script:\n %s", tclc->tc_line);
|
||||
retval = Jim_Eval_Named(interp, tclc->tc_line, "remote:connection", 1);
|
||||
result = Jim_GetString(Jim_GetResult(interp), &reslen);
|
||||
LOG_DEBUG("Result: %d\n %s", retval, result);
|
||||
retval = tcl_output(connection, result, reslen);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
/* Always output ctrl-d as end of line to allow multiline results */
|
||||
tcl_output(connection, "\x1a", 1);
|
||||
}
|
||||
|
||||
tclc->tc_lineoffset = 0;
|
||||
tclc->tc_linedrop = 0;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int tcl_closed(struct connection *connection)
|
||||
{
|
||||
/* cleanup connection context */
|
||||
if (connection->priv) {
|
||||
free(connection->priv);
|
||||
connection->priv = NULL;
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int tcl_init(void)
|
||||
{
|
||||
if (strcmp(tcl_port, "disabled") == 0) {
|
||||
LOG_INFO("tcl server disabled");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
return add_service("tcl", tcl_port, 1,
|
||||
&tcl_new_connection, &tcl_input,
|
||||
&tcl_closed, NULL);
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_tcl_port_command)
|
||||
{
|
||||
return CALL_COMMAND_HANDLER(server_pipe_command, &tcl_port);
|
||||
}
|
||||
|
||||
static const struct command_registration tcl_command_handlers[] = {
|
||||
{
|
||||
.name = "tcl_port",
|
||||
.handler = handle_tcl_port_command,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.help = "Specify port on which to listen "
|
||||
"for incoming Tcl syntax. "
|
||||
"Read help on 'gdb_port'.",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
int tcl_register_commands(struct command_context *cmd_ctx)
|
||||
{
|
||||
tcl_port = strdup("6666");
|
||||
return register_commands(cmd_ctx, NULL, tcl_command_handlers);
|
||||
}
|
||||
28
debuggers/openocd/src/server/tcl_server.h
Normal file
28
debuggers/openocd/src/server/tcl_server.h
Normal file
@ -0,0 +1,28 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _TCL_SERVER_H_
|
||||
#define _TCL_SERVER_H_
|
||||
|
||||
#include <server/server.h>
|
||||
|
||||
int tcl_init(void);
|
||||
int tcl_register_commands(struct command_context *cmd_ctx);
|
||||
|
||||
#endif /* _TCL_SERVER_H_ */
|
||||
652
debuggers/openocd/src/server/telnet_server.c
Normal file
652
debuggers/openocd/src/server/telnet_server.c
Normal file
@ -0,0 +1,652 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007-2010 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "telnet_server.h"
|
||||
#include <target/target_request.h>
|
||||
#include <helper/configuration.h>
|
||||
|
||||
static const char *telnet_port;
|
||||
|
||||
static char *negotiate =
|
||||
"\xFF\xFB\x03" /* IAC WILL Suppress Go Ahead */
|
||||
"\xFF\xFB\x01" /* IAC WILL Echo */
|
||||
"\xFF\xFD\x03" /* IAC DO Suppress Go Ahead */
|
||||
"\xFF\xFE\x01"; /* IAC DON'T Echo */
|
||||
|
||||
#define CTRL(c) (c - '@')
|
||||
#define TELNET_HISTORY ".openocd_history"
|
||||
|
||||
/* The only way we can detect that the socket is closed is the first time
|
||||
* we write to it, we will fail. Subsequent write operations will
|
||||
* succeed. Shudder!
|
||||
*/
|
||||
static int telnet_write(struct connection *connection, const void *data,
|
||||
int len)
|
||||
{
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
if (t_con->closed)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
if (connection_write(connection, data, len) == len)
|
||||
return ERROR_OK;
|
||||
t_con->closed = 1;
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
static int telnet_prompt(struct connection *connection)
|
||||
{
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
|
||||
return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));
|
||||
}
|
||||
|
||||
static int telnet_outputline(struct connection *connection, const char *line)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* process lines in buffer */
|
||||
while (*line) {
|
||||
char *line_end = strchr(line, '\n');
|
||||
|
||||
if (line_end)
|
||||
len = line_end-line;
|
||||
else
|
||||
len = strlen(line);
|
||||
|
||||
telnet_write(connection, line, len);
|
||||
if (line_end) {
|
||||
telnet_write(connection, "\r\n", 2);
|
||||
line += len + 1;
|
||||
} else
|
||||
line += len;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int telnet_output(struct command_context *cmd_ctx, const char *line)
|
||||
{
|
||||
struct connection *connection = cmd_ctx->output_handler_priv;
|
||||
|
||||
return telnet_outputline(connection, line);
|
||||
}
|
||||
|
||||
static void telnet_log_callback(void *priv, const char *file, unsigned line,
|
||||
const char *function, const char *string)
|
||||
{
|
||||
struct connection *connection = priv;
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
int i;
|
||||
|
||||
/* if there is no prompt, simply output the message */
|
||||
if (t_con->line_cursor < 0) {
|
||||
telnet_outputline(connection, string);
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the command line */
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, " ", i > 16 ? 16 : i);
|
||||
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
|
||||
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
|
||||
|
||||
/* output the message */
|
||||
telnet_outputline(connection, string);
|
||||
|
||||
/* put the command line to its previous state */
|
||||
telnet_prompt(connection);
|
||||
telnet_write(connection, t_con->line, t_con->line_size);
|
||||
for (i = t_con->line_size; i > t_con->line_cursor; i--)
|
||||
telnet_write(connection, "\b", 1);
|
||||
}
|
||||
|
||||
static void telnet_load_history(struct telnet_connection *t_con)
|
||||
{
|
||||
FILE *histfp;
|
||||
char buffer[TELNET_BUFFER_SIZE];
|
||||
int i = 0;
|
||||
|
||||
char *history = get_home_dir(TELNET_HISTORY);
|
||||
|
||||
if (history == NULL) {
|
||||
LOG_INFO("unable to get user home directory, telnet history will be disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
histfp = fopen(history, "rb");
|
||||
|
||||
if (histfp) {
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), histfp) != NULL) {
|
||||
|
||||
char *p = strchr(buffer, '\n');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
if (buffer[0] && i < TELNET_LINE_HISTORY_SIZE)
|
||||
t_con->history[i++] = strdup(buffer);
|
||||
}
|
||||
|
||||
t_con->next_history = i;
|
||||
t_con->next_history %= TELNET_LINE_HISTORY_SIZE;
|
||||
/* try to set to last entry - 1, that way we skip over any exit/shutdown cmds */
|
||||
t_con->current_history = t_con->next_history > 0 ? i - 1 : 0;
|
||||
fclose(histfp);
|
||||
}
|
||||
|
||||
free(history);
|
||||
}
|
||||
|
||||
static void telnet_save_history(struct telnet_connection *t_con)
|
||||
{
|
||||
FILE *histfp;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
char *history = get_home_dir(TELNET_HISTORY);
|
||||
|
||||
if (history == NULL) {
|
||||
LOG_INFO("unable to get user home directory, telnet history will be disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
histfp = fopen(history, "wb");
|
||||
|
||||
if (histfp) {
|
||||
|
||||
num = TELNET_LINE_HISTORY_SIZE;
|
||||
i = t_con->current_history + 1;
|
||||
i %= TELNET_LINE_HISTORY_SIZE;
|
||||
|
||||
while (t_con->history[i] == NULL && num > 0) {
|
||||
i++;
|
||||
i %= TELNET_LINE_HISTORY_SIZE;
|
||||
num--;
|
||||
}
|
||||
|
||||
if (num > 0) {
|
||||
for (; num > 0; num--) {
|
||||
fprintf(histfp, "%s\n", t_con->history[i]);
|
||||
i++;
|
||||
i %= TELNET_LINE_HISTORY_SIZE;
|
||||
}
|
||||
}
|
||||
fclose(histfp);
|
||||
}
|
||||
|
||||
free(history);
|
||||
}
|
||||
|
||||
static int telnet_new_connection(struct connection *connection)
|
||||
{
|
||||
struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection));
|
||||
struct telnet_service *telnet_service = connection->service->priv;
|
||||
int i;
|
||||
|
||||
connection->priv = telnet_connection;
|
||||
|
||||
/* initialize telnet connection information */
|
||||
telnet_connection->closed = 0;
|
||||
telnet_connection->line_size = 0;
|
||||
telnet_connection->line_cursor = 0;
|
||||
telnet_connection->option_size = 0;
|
||||
telnet_connection->prompt = strdup("> ");
|
||||
telnet_connection->state = TELNET_STATE_DATA;
|
||||
|
||||
/* output goes through telnet connection */
|
||||
command_set_output_handler(connection->cmd_ctx, telnet_output, connection);
|
||||
|
||||
/* negotiate telnet options */
|
||||
telnet_write(connection, negotiate, strlen(negotiate));
|
||||
|
||||
/* print connection banner */
|
||||
if (telnet_service->banner) {
|
||||
telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner));
|
||||
telnet_write(connection, "\r\n", 2);
|
||||
}
|
||||
|
||||
/* the prompt is always placed at the line beginning */
|
||||
telnet_write(connection, "\r", 1);
|
||||
telnet_prompt(connection);
|
||||
|
||||
/* initialize history */
|
||||
for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
|
||||
telnet_connection->history[i] = NULL;
|
||||
telnet_connection->next_history = 0;
|
||||
telnet_connection->current_history = 0;
|
||||
telnet_load_history(telnet_connection);
|
||||
|
||||
log_add_callback(telnet_log_callback, connection);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static void telnet_clear_line(struct connection *connection,
|
||||
struct telnet_connection *t_con)
|
||||
{
|
||||
/* move to end of line */
|
||||
if (t_con->line_cursor < t_con->line_size)
|
||||
telnet_write(connection,
|
||||
t_con->line + t_con->line_cursor,
|
||||
t_con->line_size - t_con->line_cursor);
|
||||
|
||||
/* backspace, overwrite with space, backspace */
|
||||
while (t_con->line_size > 0) {
|
||||
telnet_write(connection, "\b \b", 3);
|
||||
t_con->line_size--;
|
||||
}
|
||||
t_con->line_cursor = 0;
|
||||
}
|
||||
|
||||
static int telnet_input(struct connection *connection)
|
||||
{
|
||||
int bytes_read;
|
||||
unsigned char buffer[TELNET_BUFFER_SIZE];
|
||||
unsigned char *buf_p;
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
struct command_context *command_context = connection->cmd_ctx;
|
||||
|
||||
bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE);
|
||||
|
||||
if (bytes_read == 0)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
else if (bytes_read == -1) {
|
||||
LOG_ERROR("error during read: %s", strerror(errno));
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
|
||||
buf_p = buffer;
|
||||
while (bytes_read) {
|
||||
switch (t_con->state) {
|
||||
case TELNET_STATE_DATA:
|
||||
if (*buf_p == 0xff)
|
||||
t_con->state = TELNET_STATE_IAC;
|
||||
else {
|
||||
if (isprint(*buf_p)) { /* printable character */
|
||||
/* watch buffer size leaving one spare character for
|
||||
* string null termination */
|
||||
if (t_con->line_size == TELNET_LINE_MAX_SIZE-1) {
|
||||
/* output audible bell if buffer is full
|
||||
* "\a" does not work, at least on windows */
|
||||
telnet_write(connection, "\x07", 1);
|
||||
} else if (t_con->line_cursor == t_con->line_size) {
|
||||
telnet_write(connection, buf_p, 1);
|
||||
t_con->line[t_con->line_size++] = *buf_p;
|
||||
t_con->line_cursor++;
|
||||
} else {
|
||||
int i;
|
||||
memmove(t_con->line + t_con->line_cursor + 1,
|
||||
t_con->line + t_con->line_cursor,
|
||||
t_con->line_size - t_con->line_cursor);
|
||||
t_con->line[t_con->line_cursor] = *buf_p;
|
||||
t_con->line_size++;
|
||||
telnet_write(connection,
|
||||
t_con->line + t_con->line_cursor,
|
||||
t_con->line_size - t_con->line_cursor);
|
||||
t_con->line_cursor++;
|
||||
for (i = t_con->line_cursor; i < t_con->line_size; i++)
|
||||
telnet_write(connection, "\b", 1);
|
||||
}
|
||||
} else { /* non-printable */
|
||||
if (*buf_p == 0x1b) { /* escape */
|
||||
t_con->state = TELNET_STATE_ESCAPE;
|
||||
t_con->last_escape = '\x00';
|
||||
} else if ((*buf_p == 0xd) || (*buf_p == 0xa)) { /* CR/LF */
|
||||
int retval;
|
||||
|
||||
/* skip over combinations with CR/LF and NUL characters */
|
||||
if ((bytes_read > 1) && ((*(buf_p + 1) == 0xa) ||
|
||||
(*(buf_p + 1) == 0xd))) {
|
||||
buf_p++;
|
||||
bytes_read--;
|
||||
}
|
||||
if ((bytes_read > 1) && (*(buf_p + 1) == 0)) {
|
||||
buf_p++;
|
||||
bytes_read--;
|
||||
}
|
||||
t_con->line[t_con->line_size] = 0;
|
||||
|
||||
telnet_write(connection, "\r\n\x00", 3);
|
||||
|
||||
if (strcmp(t_con->line, "history") == 0) {
|
||||
int i;
|
||||
for (i = 1; i < TELNET_LINE_HISTORY_SIZE; i++) {
|
||||
/* the t_con->next_history line contains empty string
|
||||
* (unless NULL), thus it is not printed */
|
||||
char *history_line = t_con->history[(t_con->
|
||||
next_history + i) %
|
||||
TELNET_LINE_HISTORY_SIZE];
|
||||
if (history_line) {
|
||||
telnet_write(connection, history_line,
|
||||
strlen(history_line));
|
||||
telnet_write(connection, "\r\n\x00", 3);
|
||||
}
|
||||
}
|
||||
t_con->line_size = 0;
|
||||
t_con->line_cursor = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* save only non-blank not repeating lines in the history */
|
||||
char *prev_line = t_con->history[(t_con->current_history > 0) ?
|
||||
t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1];
|
||||
if (*t_con->line && (prev_line == NULL ||
|
||||
strcmp(t_con->line, prev_line))) {
|
||||
/* if the history slot is already taken, free it */
|
||||
if (t_con->history[t_con->next_history])
|
||||
free(t_con->history[t_con->next_history]);
|
||||
|
||||
/* add line to history */
|
||||
t_con->history[t_con->next_history] = strdup(t_con->line);
|
||||
|
||||
/* wrap history at TELNET_LINE_HISTORY_SIZE */
|
||||
t_con->next_history = (t_con->next_history + 1) %
|
||||
TELNET_LINE_HISTORY_SIZE;
|
||||
|
||||
/* current history line starts at the new entry */
|
||||
t_con->current_history =
|
||||
t_con->next_history;
|
||||
|
||||
if (t_con->history[t_con->current_history])
|
||||
free(t_con->history[t_con->current_history]);
|
||||
t_con->history[t_con->current_history] = strdup("");
|
||||
}
|
||||
|
||||
t_con->line_size = 0;
|
||||
|
||||
/* to suppress prompt in log callback during command execution */
|
||||
t_con->line_cursor = -1;
|
||||
|
||||
if (strcmp(t_con->line, "shutdown") == 0)
|
||||
telnet_save_history(t_con);
|
||||
|
||||
retval = command_run_line(command_context, t_con->line);
|
||||
|
||||
t_con->line_cursor = 0;
|
||||
|
||||
if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
/* the prompt is always * placed at the line beginning */
|
||||
telnet_write(connection, "\r", 1);
|
||||
|
||||
retval = telnet_prompt(connection);
|
||||
if (retval == ERROR_SERVER_REMOTE_CLOSED)
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
|
||||
} else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) { /* delete character */
|
||||
if (t_con->line_cursor > 0) {
|
||||
if (t_con->line_cursor != t_con->line_size) {
|
||||
int i;
|
||||
telnet_write(connection, "\b", 1);
|
||||
t_con->line_cursor--;
|
||||
t_con->line_size--;
|
||||
memmove(t_con->line + t_con->line_cursor,
|
||||
t_con->line + t_con->line_cursor + 1,
|
||||
t_con->line_size -
|
||||
t_con->line_cursor);
|
||||
|
||||
telnet_write(connection,
|
||||
t_con->line + t_con->line_cursor,
|
||||
t_con->line_size -
|
||||
t_con->line_cursor);
|
||||
telnet_write(connection, " \b", 2);
|
||||
for (i = t_con->line_cursor; i < t_con->line_size; i++)
|
||||
telnet_write(connection, "\b", 1);
|
||||
} else {
|
||||
t_con->line_size--;
|
||||
t_con->line_cursor--;
|
||||
/* back space: move the 'printer' head one char
|
||||
* back, overwrite with space, move back again */
|
||||
telnet_write(connection, "\b \b", 3);
|
||||
}
|
||||
}
|
||||
} else if (*buf_p == 0x15) /* clear line */
|
||||
telnet_clear_line(connection, t_con);
|
||||
else if (*buf_p == CTRL('B')) { /* cursor left */
|
||||
if (t_con->line_cursor > 0) {
|
||||
telnet_write(connection, "\b", 1);
|
||||
t_con->line_cursor--;
|
||||
}
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == CTRL('F')) { /* cursor right */
|
||||
if (t_con->line_cursor < t_con->line_size)
|
||||
telnet_write(connection, t_con->line + t_con->line_cursor++, 1);
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else
|
||||
LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TELNET_STATE_IAC:
|
||||
switch (*buf_p) {
|
||||
case 0xfe:
|
||||
t_con->state = TELNET_STATE_DONT;
|
||||
break;
|
||||
case 0xfd:
|
||||
t_con->state = TELNET_STATE_DO;
|
||||
break;
|
||||
case 0xfc:
|
||||
t_con->state = TELNET_STATE_WONT;
|
||||
break;
|
||||
case 0xfb:
|
||||
t_con->state = TELNET_STATE_WILL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TELNET_STATE_SB:
|
||||
break;
|
||||
case TELNET_STATE_SE:
|
||||
break;
|
||||
case TELNET_STATE_WILL:
|
||||
case TELNET_STATE_WONT:
|
||||
case TELNET_STATE_DO:
|
||||
case TELNET_STATE_DONT:
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
break;
|
||||
case TELNET_STATE_ESCAPE:
|
||||
if (t_con->last_escape == '[') {
|
||||
if (*buf_p == 'D') { /* cursor left */
|
||||
if (t_con->line_cursor > 0) {
|
||||
telnet_write(connection, "\b", 1);
|
||||
t_con->line_cursor--;
|
||||
}
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == 'C') { /* cursor right */
|
||||
if (t_con->line_cursor < t_con->line_size)
|
||||
telnet_write(connection,
|
||||
t_con->line + t_con->line_cursor++, 1);
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == 'A') { /* cursor up */
|
||||
int last_history = (t_con->current_history > 0) ?
|
||||
t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1;
|
||||
if (t_con->history[last_history]) {
|
||||
telnet_clear_line(connection, t_con);
|
||||
t_con->line_size = strlen(t_con->history[last_history]);
|
||||
t_con->line_cursor = t_con->line_size;
|
||||
memcpy(t_con->line, t_con->history[last_history], t_con->line_size);
|
||||
telnet_write(connection, t_con->line, t_con->line_size);
|
||||
t_con->current_history = last_history;
|
||||
}
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == 'B') { /* cursor down */
|
||||
int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;
|
||||
if (t_con->history[next_history]) {
|
||||
telnet_clear_line(connection, t_con);
|
||||
t_con->line_size = strlen(t_con->history[next_history]);
|
||||
t_con->line_cursor = t_con->line_size;
|
||||
memcpy(t_con->line, t_con->history[next_history], t_con->line_size);
|
||||
telnet_write(connection, t_con->line, t_con->line_size);
|
||||
t_con->current_history = next_history;
|
||||
}
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (*buf_p == '3')
|
||||
t_con->last_escape = *buf_p;
|
||||
else
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (t_con->last_escape == '3') {
|
||||
/* Remove character */
|
||||
if (*buf_p == '~') {
|
||||
if (t_con->line_cursor < t_con->line_size) {
|
||||
int i;
|
||||
t_con->line_size--;
|
||||
/* remove char from line buffer */
|
||||
memmove(t_con->line + t_con->line_cursor,
|
||||
t_con->line + t_con->line_cursor + 1,
|
||||
t_con->line_size - t_con->line_cursor);
|
||||
|
||||
/* print remainder of buffer */
|
||||
telnet_write(connection, t_con->line + t_con->line_cursor,
|
||||
t_con->line_size - t_con->line_cursor);
|
||||
/* overwrite last char with whitespace */
|
||||
telnet_write(connection, " \b", 2);
|
||||
|
||||
/* move back to cursor position*/
|
||||
for (i = t_con->line_cursor; i < t_con->line_size; i++)
|
||||
telnet_write(connection, "\b", 1);
|
||||
}
|
||||
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else if (t_con->last_escape == '\x00') {
|
||||
if (*buf_p == '[')
|
||||
t_con->last_escape = *buf_p;
|
||||
else
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
} else {
|
||||
LOG_ERROR("BUG: unexpected value in t_con->last_escape");
|
||||
t_con->state = TELNET_STATE_DATA;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("unknown telnet state");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
bytes_read--;
|
||||
buf_p++;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int telnet_connection_closed(struct connection *connection)
|
||||
{
|
||||
struct telnet_connection *t_con = connection->priv;
|
||||
int i;
|
||||
|
||||
log_remove_callback(telnet_log_callback, connection);
|
||||
|
||||
if (t_con->prompt) {
|
||||
free(t_con->prompt);
|
||||
t_con->prompt = NULL;
|
||||
}
|
||||
|
||||
/* save telnet history */
|
||||
telnet_save_history(t_con);
|
||||
|
||||
for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) {
|
||||
if (t_con->history[i]) {
|
||||
free(t_con->history[i]);
|
||||
t_con->history[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* if this connection registered a debug-message receiver delete it */
|
||||
delete_debug_msg_receiver(connection->cmd_ctx, NULL);
|
||||
|
||||
if (connection->priv) {
|
||||
free(connection->priv);
|
||||
connection->priv = NULL;
|
||||
} else
|
||||
LOG_ERROR("BUG: connection->priv == NULL");
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
int telnet_init(char *banner)
|
||||
{
|
||||
if (strcmp(telnet_port, "disabled") == 0) {
|
||||
LOG_INFO("telnet server disabled");
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
struct telnet_service *telnet_service = malloc(sizeof(struct telnet_service));
|
||||
|
||||
telnet_service->banner = banner;
|
||||
|
||||
return add_service("telnet",
|
||||
telnet_port,
|
||||
1,
|
||||
telnet_new_connection,
|
||||
telnet_input,
|
||||
telnet_connection_closed,
|
||||
telnet_service);
|
||||
}
|
||||
|
||||
/* daemon configuration command telnet_port */
|
||||
COMMAND_HANDLER(handle_telnet_port_command)
|
||||
{
|
||||
return CALL_COMMAND_HANDLER(server_pipe_command, &telnet_port);
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_exit_command)
|
||||
{
|
||||
return ERROR_COMMAND_CLOSE_CONNECTION;
|
||||
}
|
||||
|
||||
static const struct command_registration telnet_command_handlers[] = {
|
||||
{
|
||||
.name = "exit",
|
||||
.handler = handle_exit_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.usage = "",
|
||||
.help = "exit telnet session",
|
||||
},
|
||||
{
|
||||
.name = "telnet_port",
|
||||
.handler = handle_telnet_port_command,
|
||||
.mode = COMMAND_ANY,
|
||||
.help = "Specify port on which to listen "
|
||||
"for incoming telnet connections. "
|
||||
"Read help on 'gdb_port'.",
|
||||
.usage = "[port_num]",
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
int telnet_register_commands(struct command_context *cmd_ctx)
|
||||
{
|
||||
telnet_port = strdup("4444");
|
||||
return register_commands(cmd_ctx, NULL, telnet_command_handlers);
|
||||
}
|
||||
72
debuggers/openocd/src/server/telnet_server.h
Normal file
72
debuggers/openocd/src/server/telnet_server.h
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Dominic Rath *
|
||||
* Dominic.Rath@gmx.de *
|
||||
* *
|
||||
* Copyright (C) 2007,2008 Øyvind Harboe *
|
||||
* oyvind.harboe@zylin.com *
|
||||
* *
|
||||
* Copyright (C) 2008 by Spencer Oliver *
|
||||
* spen@spen-soft.co.uk *
|
||||
* *
|
||||
* 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 2 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TELNET_SERVER_H
|
||||
#define TELNET_SERVER_H
|
||||
|
||||
#include <server/server.h>
|
||||
|
||||
#define TELNET_BUFFER_SIZE (1024)
|
||||
|
||||
#define TELNET_OPTION_MAX_SIZE (128)
|
||||
#define TELNET_LINE_HISTORY_SIZE (128)
|
||||
#define TELNET_LINE_MAX_SIZE (256)
|
||||
|
||||
enum telnet_states {
|
||||
TELNET_STATE_DATA,
|
||||
TELNET_STATE_IAC,
|
||||
TELNET_STATE_SB,
|
||||
TELNET_STATE_SE,
|
||||
TELNET_STATE_WILL,
|
||||
TELNET_STATE_WONT,
|
||||
TELNET_STATE_DO,
|
||||
TELNET_STATE_DONT,
|
||||
TELNET_STATE_ESCAPE,
|
||||
};
|
||||
|
||||
struct telnet_connection {
|
||||
char *prompt;
|
||||
enum telnet_states state;
|
||||
char line[TELNET_LINE_MAX_SIZE];
|
||||
int line_size;
|
||||
int line_cursor;
|
||||
char option[TELNET_OPTION_MAX_SIZE];
|
||||
int option_size;
|
||||
char last_escape;
|
||||
char *history[TELNET_LINE_HISTORY_SIZE];
|
||||
int next_history;
|
||||
int current_history;
|
||||
int closed;
|
||||
};
|
||||
|
||||
struct telnet_service {
|
||||
char *banner;
|
||||
};
|
||||
|
||||
int telnet_init(char *banner);
|
||||
int telnet_register_commands(struct command_context *command_context);
|
||||
|
||||
#endif /* TELNET_SERVER_H */
|
||||
Reference in New Issue
Block a user