[master] ee92182 Add VRT_MAJOR_VERSION and VRT_MINOR_VERSION as discussed on the Stockholm VDD.

Poul-Henning Kamp phk at FreeBSD.org
Thu Jun 19 11:52:49 CEST 2014


commit ee92182fe25177c392c3be2d1c3955096d10d2e6
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Thu Jun 19 09:51:19 2014 +0000

    Add VRT_MAJOR_VERSION and VRT_MINOR_VERSION as discussed on the Stockholm VDD.
    
    Renovate and simplify the compile-time binding between VMODs, VCC
    and varnishd.

diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c
index 70b8d95..a2dc7c0 100644
--- a/bin/varnishd/cache/cache_vrt_vmod.c
+++ b/bin/varnishd/cache/cache_vrt_vmod.c
@@ -39,7 +39,6 @@
 
 #include "vcli_priv.h"
 #include "vrt.h"
-#include "vmod_abi.h"
 
 /*--------------------------------------------------------------------
  * Modules stuff
@@ -64,10 +63,10 @@ static VTAILQ_HEAD(,vmod)	vmods = VTAILQ_HEAD_INITIALIZER(vmods);
 
 int
 VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
-    const char *path, struct cli *cli)
+    const char *path, const char *file_id, struct cli *cli)
 {
 	struct vmod *v;
-	void *x, *y, *z, *w;
+	const struct vmod_data *d;
 	char buf[256];
 	void *dlhdl;
 
@@ -90,50 +89,37 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
 
 		v->hdl = dlhdl;
 
-		bprintf(buf, "Vmod_%s_Name", nm);
-		x = dlsym(v->hdl, buf);
-		bprintf(buf, "Vmod_%s_Len", nm);
-		y = dlsym(v->hdl, buf);
-		bprintf(buf, "Vmod_%s_Func", nm);
-		z = dlsym(v->hdl, buf);
-		bprintf(buf, "Vmod_%s_ABI", nm);
-		w = dlsym(v->hdl, buf);
-		if (x == NULL || y == NULL || z == NULL || w == NULL) {
+		bprintf(buf, "Vmod_%s_Data", nm);
+		d = dlsym(v->hdl, buf);
+		if (d == NULL ||
+		    d->file_id == NULL ||
+		    strcmp(d->file_id, file_id)) {
 			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
-			VCLI_Out(cli, "VMOD symbols not found\n");
-			VCLI_Out(cli, "Check relative pathnames.\n");
+			VCLI_Out(cli,
+			    "This is no longer the same file seen by"
+			    " the VCL-compiler.\n");
 			(void)dlclose(v->hdl);
 			FREE_OBJ(v);
 			return (1);
 		}
-		AN(x);
-		AN(y);
-		AN(z);
-		AN(w);
-		if (strcmp(x, nm)) {
+		if (d->vrt_major != VRT_MAJOR_VERSION ||
+		    d->vrt_minor > VRT_MINOR_VERSION ||
+		    d->name == NULL ||
+		    strcmp(d->name, nm) ||
+		    d->func == NULL ||
+		    d->func_len <= 0 ||
+		    d->proto == NULL ||
+		    d->spec == NULL ||
+		    d->abi == NULL) {
 			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
-			VCLI_Out(cli, "File contain wrong VMOD (\"%s\")\n",
-			    (char *) x);
-			VCLI_Out(cli, "Check relative pathnames ?.\n");
+			VCLI_Out(cli, "VMOD data is mangled.\n");
 			(void)dlclose(v->hdl);
 			FREE_OBJ(v);
 			return (1);
 		}
 
-		if (strcmp(w, VMOD_ABI_Version)) {
-			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
-			VCLI_Out(cli, "VMOD ABI (%s)", (char*)w);
-			VCLI_Out(cli, " incompatible with varnish ABI (%s)\n",
-			    VMOD_ABI_Version);
-			(void)dlclose(v->hdl);
-			FREE_OBJ(v);
-			return (1);
-		}
-
-		// XXX: Check w for ABI version compatibility
-
-		v->funclen = *(const int *)y;
-		v->funcs = z;
+		v->funclen = d->func_len;
+		v->funcs = d->func;
 
 		REPLACE(v->nm, nm);
 		REPLACE(v->path, path);
diff --git a/bin/varnishd/flint.lnt b/bin/varnishd/flint.lnt
index 0c8c7d6..9ad0543 100644
--- a/bin/varnishd/flint.lnt
+++ b/bin/varnishd/flint.lnt
@@ -58,18 +58,8 @@
 
 // Stuff in VMODs which is used through dl*(3) functions
 -esym(754, Vmod_*_Func::*)
--esym(765, Vmod_*_Func)
--esym(552, Vmod_*_Func)
--esym(765, Vmod_*_Len)
--esym(714, Vmod_*_Len)
--esym(765, Vmod_*_Name)
--esym(714, Vmod_*_Name)
--esym(765, Vmod_*_Proto)
--esym(714, Vmod_*_Proto)
--esym(765, Vmod_*_Spec)
--esym(714, Vmod_*_Spec)
--esym(765, Vmod_*_ABI)
--esym(714, Vmod_*_ABI)
+-esym(714, Vmod_*_Data)
+-esym(765, Vmod_*_Data)
 
 
 //-sem (pthread_mutex_lock, thread_lock)
diff --git a/include/vrt.h b/include/vrt.h
index 5884b00..066d6c8 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -26,11 +26,26 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * Runtime support for compiled VCL programs.
+ * Runtime support for compiled VCL programs and VMODs.
  *
- * XXX: When this file is changed, lib/libvcc/generate.py *MUST* be rerun.
+ * NB: When this file is changed, lib/libvcc/generate.py *MUST* be rerun.
  */
 
+/***********************************************************************
+ * Major and minor VRT API versions.
+ *
+ * Whenever something is added, increment MINOR version
+ * Whenever something is deleted or changed in a way which is not
+ * binary/load-time compatible, increment MAJOR version
+ */
+
+#define VRT_MAJOR_VERSION	1U
+
+#define VRT_MINOR_VERSION	1U
+
+
+/***********************************************************************/
+
 struct req;
 struct busyobj;
 struct vsl_log;
@@ -89,6 +104,22 @@ struct vrt_ctx {
 
 /***********************************************************************/
 
+struct vmod_data {
+	/* The version/id fields must be first, they protect the rest */
+	unsigned			vrt_major;
+	unsigned			vrt_minor;
+	const char			*file_id;
+
+	const char			*name;
+	const void			*func;
+	int				func_len;
+	const char			*proto;
+	const char			* const *spec;
+	const char			*abi;
+};
+
+/***********************************************************************/
+
 enum gethdr_e { HDR_REQ, HDR_RESP, HDR_OBJ, HDR_BEREQ, HDR_BERESP };
 
 struct gethdr_s {
@@ -230,7 +261,7 @@ int VRT_VSA_GetPtr(const struct suckaddr *sua, const unsigned char ** dst);
 
 /* VMOD/Modules related */
 int VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
-    const char *path, struct cli *cli);
+    const char *path, const char *file_id, struct cli *cli);
 void VRT_Vmod_Fini(void **hdl);
 
 struct vmod_priv;
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index 1723007..4f139de 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -35,6 +35,7 @@
 #include "vcc_compile.h"
 
 #include "vmod_abi.h"
+#include "vrt.h"
 
 void
 vcc_ParseImport(struct vcc *tl)
@@ -44,14 +45,12 @@ vcc_ParseImport(struct vcc *tl)
 	char buf[256];
 	struct token *mod, *t1;
 	struct inifin *ifp;
-	const char *modname;
-	const char *proto;
-	const char *abi;
-	const char **spec;
+	const char * const *spec;
 	struct symbol *sym;
 	const struct symbol *osym;
 	const char *p;
 	// int *modlen;
+	const struct vmod_data *vmd;
 
 	t1 = tl->t;
 	SkipToken(tl, ID);		/* "import" */
@@ -62,7 +61,7 @@ vcc_ParseImport(struct vcc *tl)
 
 	osym = VCC_FindSymbol(tl, mod, SYM_NONE);
 	if (osym != NULL && osym->kind != SYM_VMOD) {
-		VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n",
+		VSB_printf(tl->sb, "Module %.*s conflicts with other symbol.\n",
 		    PF(mod));
 		vcc_ErrWhere2(tl, t1, tl->t);
 		return;
@@ -104,77 +103,88 @@ vcc_ParseImport(struct vcc *tl)
 		bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod));
 	}
 
-	ifp = New_IniFin(tl);
-
-	VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
-	VSB_printf(ifp->ini, "\t    &Vmod_%.*s_Func,\n", PF(mod));
-	VSB_printf(ifp->ini, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
-	VSB_printf(ifp->ini, "\t    \"%.*s\",\n", PF(mod));
-	VSB_printf(ifp->ini, "\t    ");
-	EncString(ifp->ini, fn, NULL, 0);
-	VSB_printf(ifp->ini, ",\n\t    ");
-	VSB_printf(ifp->ini, "cli))\n");
-	VSB_printf(ifp->ini, "\t\treturn(1);");
-
-	/* XXX: zero the function pointer structure ?*/
-	VSB_printf(ifp->fin, "\tVRT_priv_fini(&vmod_priv_%.*s);", PF(mod));
-	VSB_printf(ifp->fin, "\n\tVRT_Vmod_Fini(&VGC_vmod_%.*s);", PF(mod));
-
-	ifp = NULL;
-
 	SkipToken(tl, ';');
 
 	hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
 	if (hdl == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, dlerror());
+		VSB_printf(tl->sb, "Could not load VMOD %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\tdlerror:: %s\n", dlerror());
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
 
-	bprintf(buf, "Vmod_%.*s_Name", PF(mod));
-	modname = dlsym(hdl, buf);
-	if (modname == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Name not found");
+	bprintf(buf, "Vmod_%.*s_Data", PF(mod));
+	vmd = dlsym(hdl, buf);
+	if (vmd == NULL) {
+		VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\t(no Vmod_Data symbol)\n");
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
-	if (!vcc_IdIs(mod, modname)) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
-		    PF(mod), fn);
-		VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname);
+	if (vmd->vrt_major != VRT_MAJOR_VERSION ||
+	    vmd->vrt_minor > VRT_MINOR_VERSION) {
+		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\tVMOD version %u.%u\n",
+		    vmd->vrt_major, vmd->vrt_minor);
+		VSB_printf(tl->sb, "\tvarnishd version %u.%u\n",
+		    VRT_MAJOR_VERSION, VRT_MINOR_VERSION);
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
-
-	bprintf(buf, "Vmod_%.*s_ABI", PF(mod));
-	abi = dlsym(hdl, buf);
-	if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
-		    PF(mod), fn);
-		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
-			   VMOD_ABI_Version, abi);
+	if (vmd->name == NULL ||
+	    vmd->func == NULL ||
+	    vmd->func_len <= 0 ||
+	    vmd->proto == NULL ||
+	    vmd->abi == NULL) {
+		VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\tInconsistent metadata\n");
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
 
-	bprintf(buf, "Vmod_%.*s_Proto", PF(mod));
-	proto = dlsym(hdl, buf);
-	if (proto == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Proto not found");
+	if (!vcc_IdIs(mod, vmd->name)) {
+		VSB_printf(tl->sb, "Wrong VMOD file %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\tContains vmod \"%s\"\n", vmd->name);
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
-	bprintf(buf, "Vmod_%.*s_Spec", PF(mod));
-	spec = dlsym(hdl, buf);
-	if (spec == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Spec not found");
+
+	if (strcmp(vmd->abi, VMOD_ABI_Version) != 0) {
+		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
+		VSB_printf(tl->sb, "\tFile name: %s\n", fn);
+		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
+			   VMOD_ABI_Version, vmd->abi);
 		vcc_ErrWhere(tl, mod);
 		return;
 	}
+
+	ifp = New_IniFin(tl);
+
+	VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
+	VSB_printf(ifp->ini, "\t    &Vmod_%.*s_Func,\n", PF(mod));
+	VSB_printf(ifp->ini, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
+	VSB_printf(ifp->ini, "\t    \"%.*s\",\n", PF(mod));
+	VSB_printf(ifp->ini, "\t    ");
+	EncString(ifp->ini, fn, NULL, 0);
+	VSB_printf(ifp->ini, ",\n");
+	AN(vmd);
+	AN(vmd->file_id);
+	VSB_printf(ifp->ini, "\t    \"%s\",\n", vmd->file_id);
+	VSB_printf(ifp->ini, "\t    cli))\n");
+	VSB_printf(ifp->ini, "\t\treturn(1);");
+
+	/* XXX: zero the function pointer structure ?*/
+	VSB_printf(ifp->fin, "\tVRT_priv_fini(&vmod_priv_%.*s);", PF(mod));
+	VSB_printf(ifp->fin, "\n\tVRT_Vmod_Fini(&VGC_vmod_%.*s);", PF(mod));
+
+	ifp = NULL;
+
+	spec = vmd->spec;
 	for (; *spec != NULL; spec++) {
 		p = *spec;
 		if (!strcmp(p, "OBJ")) {
@@ -208,6 +218,6 @@ vcc_ParseImport(struct vcc *tl)
 	Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod));
 	Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod));
 	Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
-	Fh(tl, 0, "\n%s\n", proto);
+	Fh(tl, 0, "\n%s\n", vmd->proto);
 	Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod));
 }
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 315b46b..21c6c6d 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -40,6 +40,7 @@ import sys
 import re
 import optparse
 import unittest
+import random
 from os import unlink
 from os.path import dirname, realpath, exists
 from pprint import pprint, pformat
@@ -196,29 +197,17 @@ class Vmod(object):
 				fo.write(j + "\n")
 
 	def c_vmod(self, fo):
-		fo.write('extern const char Vmod_' + self.nam + '_Name[];\n')
-		fo.write('const char Vmod_' + self.nam + '_Name[] =')
-		fo.write(' \"' + self.nam + '";\n')
-		fo.write("\n")
 
 		cs = self.c_struct()
 		fo.write(cs + ';\n')
 
-		vfn = 'Vmod_' + self.nam + '_Func'
+		vfn = 'Vmod_%s_Func' % self.nam
 
-		fo.write("extern const struct " + vfn + " " + vfn + ';\n')
-		fo.write("const struct " + vfn + " " + vfn + ' =')
+		fo.write("\nstatic const struct %s Vmod_Func =" % vfn)
 		fo.write(self.c_initializer())
 		fo.write("\n")
 
-		fo.write("\n")
-		fo.write("extern const int Vmod_" + self.nam + '_Len;\n')
-		fo.write("const int Vmod_" + self.nam + '_Len =')
-		fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n")
-		fo.write("\n")
-
-		fo.write("extern const char Vmod_" + self.nam + "_Proto[];\n")
-		fo.write("const char Vmod_" + self.nam + "_Proto[] =\n")
+		fo.write("\nstatic const char Vmod_Proto[] =\n")
 		for t in self.c_typedefs_():
 			for i in lwrap(t, w=64):
 				fo.write('\t"' + i + '\\n"\n')
@@ -230,12 +219,28 @@ class Vmod(object):
 		fo.write(self.c_strspec())
 
 		fo.write("\n")
-		fo.write('extern const char Vmod_' + self.nam + '_ABI[];\n')
-		fo.write('const char Vmod_' + self.nam + '_ABI[] =')
-		fo.write(' VMOD_ABI_Version;\n')
-		#fo.write("\n")
-		#fo.write('const void * const Vmod_' + self.nam + '_Id =')
-		#fo.write(' &Vmod_' + self.nam + '_Id;\n')
+
+		nm = "Vmod_" + self.nam + "_Data"
+		fo.write("extern const struct vmod_data " + nm + ";\n\n")
+		fo.write("const struct vmod_data " + nm + " = {\n")
+		fo.write("\t.vrt_major = VRT_MAJOR_VERSION,\n");
+		fo.write("\t.vrt_minor = VRT_MINOR_VERSION,\n");
+		fo.write("\t.name = \"%s\",\n" % self.nam)
+		fo.write("\t.func = &Vmod_Func,\n")
+		fo.write("\t.func_len = sizeof(Vmod_Func),\n")
+		fo.write("\t.proto = Vmod_Proto,\n")
+		fo.write("\t.spec = Vmod_Spec,\n")
+		fo.write("\t.abi = VMOD_ABI_Version,\n")
+
+		# NB: Sort of hackish:
+		# Fill file_id with random stuff, so we can tell if
+		# VCC and VRT_Vmod_Init() dlopens the same file
+		#
+		fo.write("\t.file_id = \"")
+		for i in range(32):
+			fo.write("%c" % random.randint(0x23,0x5b))
+		fo.write("\",\n")
+		fo.write("};\n")
 
 	def c_initializer(self):
 		s = '{\n'
@@ -269,8 +274,7 @@ class Vmod(object):
 		return s
 
 	def c_strspec(self):
-		s = "const char * const Vmod_" + self.nam + "_Spec[]"
-		s = "extern " + s + ";\n" + s + " = {\n"
+		s = "static const char * const Vmod_Spec[] = {\n"
 
 		for o in self.objs:
 			s += o.c_strspec(self.nam) + ",\n\n"



More information about the varnish-commit mailing list