Ethereal-dev: [Ethereal-dev] Building plugins with mingw works
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Scott Renfro <scott@xxxxxxxxxx>
Date: Thu, 18 Apr 2002 09:03:07 -0700
Summary: You can indeed use mingw (gcc for win32) to build a plugin that works with the win32 Ethereal binary from www.ethereal.com (which is compiled with MS Visual C++). Although I was building a proprietary dissector that can't be released, I wanted to document the required tricks so others can do this without MS Dev Studio and without building the entire Ethereal win32 binary. There are bits of this that would be worth committing (e.g., the config.h.mingw, config.mingw, plugins/plugin.def.mingw, and patch to plugin_api.h). The others (plugins/Makefile.mingw and plugins/FOO/Makefile.mingw, changes to plugin_api.c) are more questionable. It may be worth adding this to doc/README.plugins. Some of this may lay the groundwork for building Ethereal from scratch using mingw. What You Need - The win32 binary release of Ethereal (0.9.2 in this case) - The corresponding source code tarball (0.9.2 also; note that using a different source tarball will likely result in problems). - The gtk development tarball (gtk+-dev-20001226.zip) from www.ethereal.com/distribution/win32/development. This includes both the glib and gtk header files you need. For convenience, I extracted the tarball in the same parent directory as the ethereal source. We assume you extract these into c:/ethereal-win32-libs/. - The mingw and make distributions from http://mingw.sf.net - A few UNIX-sh tools. Install UnxUtils from http://unxutils.sf.net Preparing to build - First, get a plugin working under Unix, if at all possible. Otherwise, follow the directions in doc/README.plugins. We assume this is in place as a starting point. - Ethereal source modifications. Several modifications to the existing code base are required to appease mingw. - Add global function pointers to plugins/plugin_api.c. Copy the field list contained in the typedef struct plugin_address_table_t (but not the surrounding structure definition) from plugins/plugin_table.h and paste them at the end of plugins/plugin_api.c. This creates a set of global variables that mirror those contained within that structure. I'm not providing a diff for this since it changes from release to release and is a 10 second operation to copy and paste. Here's why: the plugin needs to call methods in the parent executable. While this works fine on some OSes (e.g., UNIX), it doesn't work on Win32. In such cases, plugins/plugin_api.{c,h} and plugins/plugin_table.h provide a table of pointers that is passed to the plugin and used to initialize a set of global function pointers in the plugin. This trick allows the same source to be used with and without function pointers depending on whether or not the address table is required. Unfortunately, gcc doesn't see the global pointers (actually, it's not clear to me how Dev Studio does see them or where they exist, but that's another discussion, perhaps). Copying the fields out of the struct and pasting them into plugin_api.c, which is linked with the plugin, creates the global variables inside the dll that are initialized in the plugin_init() call. - Disable the gcc __attribute__(x) extensions for the function pointers. Although there's surely a more surgical, elegant, and proper way to accomplish this, here's one that works: in plugins/plugin_api.h, just before the includes, within the #ifdef PLUGINS_NEED_ADDRESS_TABLE, add the following lines (the attached patchfile will also do this): #if defined(WIN32) && defined(__GNUC__) #define __attribute__(x) #endif This will cause the later includes within this compilation unit to erase the gcc __attribute__ extensions. Here's why: apparently gcc doesn't support the use of this extension with function pointers. The code in plugins/plugin_api.h translates several Ethereal functions into function pointer declarations, so we need to disable the extension for those functions. - Add the build framework. The following files need to be added, which will allow your plugin to build. The attached patch will create generic copies of these. - config.h.mingw. Copy this file over config.h, epan/config.h, wiretap/config.h. It contains the proper #defines to control inclusion/exclusion of various header files. (Note that the VERSION string is hard coded in this file; I didn't do the same @VERSION@ sed trick that config.h.nmake used since I didn't have a global Makefile.mingw. You'll have to update the version string before use.) - config.mingw. This file contains the make variables, including compiler name, locations of libraries, header files, etc. - plugins/Makefile.mingw. This builds plugin_api.o and then builds the specified plugins by calling their makefiles. Replace FOO in PROTO=FOO with the name of your plugin's directory. You could retrofit this with the SUBDIR approach more common in other Makefiles. - plugins/plugin.def.mingw. This file specifies which symbols should be exported and the order in which they should be exported. It's completely boilerplate and can be shared by all plugins, so no modifications should be required. - plugins/FOO/Makefile.mingw. This builds your plugin from packet-proto.c. Replace FOO in PROTO=FOO PROTO with the name of your protocol. This assumes that your source files and dll name are based on your short protocol name -- which is the case for nearly all Ethereal development. - Modifying your plugin source code. If you followed doc/README.plugins closely, then nothing special needs to be done. You do want to be sure you wrap your includes in appropriate guards (e.g., for <netinet/in.h> guard with HAVE_NETINET_IN_H). Building the plugin The hard work is all finished. Here's how to build it: cd plugins make -f Makefile.mingw copy FOO/FOO.dll c:\program files\ethereal\plugins\VERSION\ Start Ethereal and it should all ``just work.'' Caveat: these are my sketchy notes and reflect one (successful) attempt with one version of Ethereal. This is intended for experienced developers and may or may not work for you or your plugins. If it doesn't, I probably don't have time to help you debug the problem. Best of luck, --Scott -- Scott Renfro <scott@xxxxxxxxxx>
diff -ruN ethereal-0.9.2.orig\config.h.mingw ethereal-0.9.2\config.h.mingw --- ethereal-0.9.2.orig\config.h.mingw Wed Dec 31 16:00:00 1969 +++ ethereal-0.9.2\config.h.mingw Wed Apr 17 11:14:19 2002 @@ -0,0 +1,114 @@ +/* config.h. Generated automatically by configure. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +/* #undef YYTEXT_POINTER */ + +#define HAVE_PLUGINS 1 +#define PLUGINS_NEED_ADDRESS_TABLE 1 + +/* #undef HAVE_SA_LEN */ + +/* #undef NEED_SNPRINTF_H */ + +/* #undef NEED_STRERROR_H */ + +#define NEED_MKSTEMP 1 + +#define HAVE_LIBPCAP 1 + +/* Define if you have the gethostbyname2 function. */ +/* #undef HAVE_GETHOSTBYNAME2 */ + +/* Define if you have the getprotobynumber function. */ +/* #undef HAVE_GETPROTOBYNUMBER */ + +/* Define if you have the <arpa/inet.h> header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the <iconv.h> header file. */ +/* #undef HAVE_ICONV_H */ + +/* Define if you have the <netdb.h> header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define if you have the <netinet/in.h> header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the <snmp/snmp.h> header file. */ +/* #undef HAVE_SNMP_SNMP_H */ + +/* Define if you have the <snmp/version.h> header file. */ +/* #undef HAVE_SNMP_VERSION_H */ + +/* Define if you have the <stdarg.h> header file. */ +#define HAVE_STDARG_H 1 + +/* Define if you have the <stddef.h> header file. */ +#define HAVE_STDDEF_H + +/* Define if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define if you have the <sys/socket.h> header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the <sys/wait.h> header file. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define if you have the <ucd-snmp/snmp.h> header file. */ +/* #undef HAVE_UCD_SNMP_SNMP_H */ + +/* Define if you have the <ucd-snmp/version.h> header file. */ +/* #undef HAVE_UCD_SNMP_VERSION_H */ + +/* Define if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the z library (-lz). */ +/*#define HAVE_LIBZ 1*/ + +#ifndef WIN32 +#define WIN32 1 +#endif + +#define HAVE_WINDOWS_H 1 +#define HAVE_WINSOCK_H 1 +#define HAVE_DIRECT_H 1 +#define HAVE_IO_H 1 +#define NEED_INET_ATON_H 1 +#define NEED_INET_V6DEFS_H 1 +#define NEED_STRPTIME_H 1 +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +/* Name of package */ +#define PACKAGE "ethereal" + +/* Version number of package */ +#define VERSION "0.9.2" + +/* Plugin installation directory */ +#define PLUGIN_DIR NULL diff -ruN ethereal-0.9.2.orig\config.mingw ethereal-0.9.2\config.mingw --- ethereal-0.9.2.orig\config.mingw Wed Dec 31 16:00:00 1969 +++ ethereal-0.9.2\config.mingw Wed Apr 17 11:36:23 2002 @@ -0,0 +1,32 @@ +# $Id: $ + +CC=gcc +MAKE=make + +VERSION=0.9.2 +RC_VERSION=0.9.2 +WTAP_VERSION=0.0 + +GTK_VERSION=1.3 +GLIB_VERSION=1.3 + +GLIB_DIR=C:/ethereal-win32-libs/glib +GTK_DIR=C:/ethereal-win32-libs/gtk+ +ZLIB_DIR=C:/ethereal-win32-libs/zlib-1.1.3 +PCAP_DIR=C:/ethereal-win32-libs/WPdpack + +LOCAL_CFLAGS= +LOCAL_LDFLAGS= + +PERL=perl +POD2MAN=pod2man +POD2HTML=pod2html +PYTHON="C:/python22/python.exe" +LEX=flex +YACC=bison + +# Set YACC_OPTS if cygnus bison can't find template file. +#YACC_OPTS=-S t:/w32-ix86/cygnus/cygwin-b20/share/bison.simple + +# To build the installer +MAKENSIS="C:/program files/nsis/makensis.exe" diff -ruN ethereal-0.9.2.orig\plugins\Makefile.mingw ethereal-0.9.2\plugins\Makefile.mingw --- ethereal-0.9.2.orig\plugins\Makefile.mingw Wed Dec 31 16:00:00 1969 +++ ethereal-0.9.2\plugins\Makefile.mingw Wed Apr 17 11:52:09 2002 @@ -0,0 +1,30 @@ +# +# $Id: Makefile.nmake,v 1.13 2002/02/27 09:42:44 guy Exp $ +# + +include ../config.mingw + +PROTO=FOO + +CC=gcc + +CFLAGS=-DHAVE_CONFIG_H -I.. -I.. -I../wiretap -I. \ + -I$(GLIB_DIR) -I$(GTK_DIR) -I$(GLIB_DIR)/gmodule \ + -I$(GTK_DIR)/gdk -I$(GTK_DIR)/gdk/win32 \ + -I$(PCAP_DIR)/include -D_U_="" $(LOCAL_CFLAGS) + +OBJECTS=plugin_api.o + +all: plugin_api.o $(PROTO)-dir + +$(PROTO)-dir: + cd $(PROTO); \ + $(MAKE) -f Makefile.mingw; \ + cd .. + +clean: + rm -f $(OBJECTS); \ + cd $(PROTO); \ + $(MAKE) -f Makefile.mingw clean; \ + cd .. + diff -ruN ethereal-0.9.2.orig\plugins\plugin.def.mingw ethereal-0.9.2\plugins\plugin.def.mingw --- ethereal-0.9.2.orig\plugins\plugin.def.mingw Wed Dec 31 16:00:00 1969 +++ ethereal-0.9.2\plugins\plugin.def.mingw Wed Apr 17 10:35:08 2002 @@ -0,0 +1,4 @@ +EXPORTS + plugin_init @ 0 ; + plugin_reg_handoff @ 1 ; + version @ 2 DATA ; diff -ruN ethereal-0.9.2.orig\plugins\plugin_api.h ethereal-0.9.2\plugins\plugin_api.h --- ethereal-0.9.2.orig\plugins\plugin_api.h Sat Feb 23 11:12:30 2002 +++ ethereal-0.9.2\plugins\plugin_api.h Wed Apr 17 11:46:14 2002 @@ -202,6 +202,12 @@ #define dissect_tpkt_encap (*p_dissect_tpkt_encap) /* TPKT entries End */ + +/* disable gcc attributes when using mingw and plugin address table macros */ +#if defined(WIN32) && defined(__GNUC__) +#define __attribute__(x) +#endif + #endif #include <epan/packet.h> diff -ruN ethereal-0.9.2.orig\plugins\FOO\Makefile.mingw ethereal-0.9.2\plugins\FOO\Makefile.mingw --- ethereal-0.9.2.orig\plugins\FOO\Makefile.mingw Wed Dec 31 16:00:00 1969 +++ ethereal-0.9.2\plugins\FOO\Makefile.mingw Wed Apr 17 12:37:40 2002 @@ -0,0 +1,26 @@ +# +# $Id: Makefile.nmake,v 1.8 2002/02/27 09:42:47 guy Exp $ +# + +include ../../config.mingw + +PROTO=FOO + +############### no need to modify below this line ######### + +CFLAGS=-DHAVE_CONFIG_H -I.. -I../.. -I../../wiretap -I. \ + -I$(GLIB_DIR) -I$(GTK_DIR) -I$(GLIB_DIR)/gmodule \ + -I$(GTK_DIR)\gdk -I$(GTK_DIR)\gdk\win32 \ + -I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS) + +OBJECTS=packet-$(PROTO).o ../plugin_api.o + +$(PROTO).dll: $(OBJECTS) + dllwrap --def ../plugin.def.mingw -dllname=$(PROTO).dll --driver-name=gcc $(OBJECTS) + +packet-$(PROTO).o: packet-$(PROTO).c + gcc $(CFLAGS) -c packet-$(PROTO).c + +clean: + rm -f $(OBJECTS) $(PROTO).dll +
- Prev by Date: Re: [Ethereal-dev] referencing specific tcp protocol data
- Next by Date: Re: [Ethereal-dev] referencing specific tcp protocol data
- Previous by thread: Re: [Ethereal-dev] weird colorization desegmentation interaction
- Next by thread: [Ethereal-dev] Ethereal 0.93 fatal error
- Index(es):