diff --git a/Makefile b/Makefile
index 48d88e7..4376907 100644
--- a/Makefile
+++ b/Makefile
@@ -277,7 +277,7 @@ gui: force $(CMD_TARGETS) $(kshark-dir)/build/Makefile
 	@echo "gui build complete"
 	@echo "  kernelshark located at $(kshark-dir)/bin"
 
-trace-cmd: force $(LIBTRACEEVENT_STATIC) $(LIBTRACECMD_STATIC)
+trace-cmd: force plugins_builtin $(LIBTRACEEVENT_STATIC) $(LIBTRACECMD_STATIC)
 	$(Q)$(MAKE) -C $(src)/tracecmd $(obj)/tracecmd/$@
 
 $(LIBTRACEEVENT_SHARED): force $(obj)/lib/traceevent/plugins/traceevent_plugin_dir
@@ -308,6 +308,14 @@ $(obj)/lib/traceevent/plugins/traceevent_plugin_dir: force
 $(obj)/lib/traceevent/plugins/trace_python_dir: force
 	$(Q)$(MAKE) -C $(src)/lib/traceevent/plugins $@
 
+ifneq (,$(is_static_build))
+export USE_BUILTIN_PLUGINS=1
+override CFLAGS += -DUSE_BUILTIN_PLUGINS
+plugins_builtin: plugins
+endif
+
+PHONY += plugins_builtin
+
 show_gui_make:
 	@echo "Note: to build the gui, type \"make gui\""
 	@echo "      to build man pages, type \"make doc\""
diff --git a/include/traceevent/event-parse.h b/include/traceevent/event-parse.h
index a77af4c..58277d3 100644
--- a/include/traceevent/event-parse.h
+++ b/include/traceevent/event-parse.h
@@ -65,6 +65,11 @@ struct tep_plugin_option {
 	int				set;
 };
 
+struct tep_plugin_builtin {
+	char *name;
+	int (*init)(struct tep_handle *tep);
+};
+
 /*
  * Plugin hooks that can be called:
  *
@@ -116,6 +121,26 @@ struct tep_plugin_option {
 #define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS)
 #define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS)
 
+#ifdef USE_BUILTIN_PLUGINS
+extern const struct tep_plugin_builtin __start_builtin_plugins[];
+extern const struct tep_plugin_builtin __stop_builtin_plugins[];
+
+#define TEP_PLUGIN(plugin)						\
+	int plugin##_init(struct tep_handle *pevent);			\
+	static struct tep_plugin_builtin __builtin_plugin_##plugin	\
+	__attribute__((unused))						\
+	__attribute__((__section__("builtin_plugins"))) = {		\
+		.name = "builtin:"#plugin,				\
+		.init = plugin##_init,					\
+	};								\
+	int plugin##_init(struct tep_handle *tep)
+#define TEP_PLUGIN_EXIT(plugin) \
+	void plugin##_exit(struct tep_handle *tep)
+#else
+#define TEP_PLUGIN(x) int TEP_PLUGIN_LOADER(struct tep_handle *tep)
+#define TEP_PLUGIN_EXIT(x) void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
+#endif
+
 enum tep_format_flags {
 	TEP_FIELD_IS_ARRAY	= 1,
 	TEP_FIELD_IS_POINTER	= 2,
diff --git a/lib/traceevent/event-plugin.c b/lib/traceevent/event-plugin.c
index 6ea4ac0..6cd6aa7 100644
--- a/lib/traceevent/event-plugin.c
+++ b/lib/traceevent/event-plugin.c
@@ -590,12 +590,44 @@ void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix,
 	free(path);
 }
 
+#ifdef USE_BUILTIN_PLUGINS
+static void tep_load_builtin_plugins(struct tep_handle *tep,
+				     struct tep_plugin_list **list)
+{
+	const struct tep_plugin_builtin *plugin;
+	struct tep_plugin_list *l;
+	int ret;
+
+	for (plugin = __start_builtin_plugins; plugin < __stop_builtin_plugins;
+	     plugin++) {
+		ret = plugin->init(tep);
+		pr_stat("built-in plugin \"%s\" registration: %s\n",
+			plugin->name, ret ? "Fail" : "Success");
+		if (ret)
+			continue;
+
+		l = malloc(sizeof(*l));
+		if (l) {
+			l->next = *list;
+			l->handle = NULL;
+			l->name = plugin->name;
+			*list = l;
+		}
+	}
+}
+#else
+void tep_load_builtin_plugins(struct tep_handle *tep,
+			      struct tep_plugin_list **list)
+{}
+#endif
+
 struct tep_plugin_list*
 tep_load_plugins(struct tep_handle *tep)
 {
 	struct tep_plugin_list *list = NULL;
 
 	tep_load_plugins_hook(tep, ".so", load_plugin, &list);
+	tep_load_builtin_plugins(tep, &list);
 	return list;
 }
 
@@ -608,11 +640,15 @@ tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep)
 	while (plugin_list) {
 		list = plugin_list;
 		plugin_list = list->next;
-		func = dlsym(list->handle, TEP_PLUGIN_UNLOADER_NAME);
-		if (func)
-			func(tep);
-		dlclose(list->handle);
-		free(list->name);
+
+		/* !handle == builtin plugin */
+		if (list->handle) {
+			func = dlsym(list->handle, TEP_PLUGIN_UNLOADER_NAME);
+			if (func)
+				func(tep);
+			dlclose(list->handle);
+			free(list->name);
+		}
 		free(list);
 	}
 }
diff --git a/lib/traceevent/plugins/Makefile b/lib/traceevent/plugins/Makefile
index 4050019..1bc6298 100644
--- a/lib/traceevent/plugins/Makefile
+++ b/lib/traceevent/plugins/Makefile
@@ -25,7 +25,11 @@ PLUGINS += $(bdir)/plugin_python_loader.so
 endif
 DEPS := $(PLUGIN_OBJS:$(bdir)/%.o=$(bdir)/.%.d)
 
+ifndef USE_BUILTIN_PLUGINS
 all: $(PLUGINS)
+else
+all: $(PLUGIN_OBJS)
+endif
 
 $(bdir):
 	@mkdir -p $(bdir)
diff --git a/lib/traceevent/plugins/plugin_blk.c b/lib/traceevent/plugins/plugin_blk.c
index ea3a9cf..df9dd80 100644
--- a/lib/traceevent/plugins/plugin_blk.c
+++ b/lib/traceevent/plugins/plugin_blk.c
@@ -363,9 +363,9 @@ static int blktrace_handler(struct trace_seq *s, struct tep_record *record,
 	return 0;
 }
 
-int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
+TEP_PLUGIN(blk)
 {
-	tep_register_event_handler(pevent, -1, "ftrace", "blktrace",
+	tep_register_event_handler(tep, -1, "ftrace", "blktrace",
 				   blktrace_handler, NULL);
 	return 0;
 }
diff --git a/lib/traceevent/plugins/plugin_sched_switch.c b/lib/traceevent/plugins/plugin_sched_switch.c
index 566f166..7b645fb 100644
--- a/lib/traceevent/plugins/plugin_sched_switch.c
+++ b/lib/traceevent/plugins/plugin_sched_switch.c
@@ -118,7 +118,7 @@ static int sched_switch_handler(struct trace_seq *s, struct tep_record *record,
 	return 0;
 }
 
-int TEP_PLUGIN_LOADER(struct tep_handle *tep)
+TEP_PLUGIN(sched_switch)
 {
 	tep_register_event_handler(tep, -1, "sched", "sched_switch",
 				   sched_switch_handler, NULL);
@@ -132,7 +132,7 @@ int TEP_PLUGIN_LOADER(struct tep_handle *tep)
 	return 0;
 }
 
-void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
+TEP_PLUGIN_EXIT(sched_switch)
 {
 	tep_unregister_event_handler(tep, -1, "sched", "sched_switch",
 				     sched_switch_handler, NULL);
diff --git a/scripts/utils.mk b/scripts/utils.mk
index d1d5135..d03315b 100644
--- a/scripts/utils.mk
+++ b/scripts/utils.mk
@@ -79,6 +79,16 @@ do_python_plugin_build =			\
 	($(print_plugin_build)			\
 	$(CC) $< -shared $(LDFLAGS) $(PYTHON_LDFLAGS) -o $@)
 
+builtin_plugins = \
+	$(foreach plugin,$(wildcard $(src)/lib/traceevent/plugins/*.o),$(is_builtin_plugin))
+
+is_builtin_plugin = \
+	$(shell $(CROSS_COMPILE)objdump -h -j builtin_plugins $(plugin) \
+		>/dev/null 2>&1 && echo $(plugin))
+
+is_static_build = \
+	$(findstring -static,$(LDFLAGS))
+
 define make_version.h
 	(echo '/* This file is automatically generated. Do not modify. */';		\
 	echo \#define VERSION_CODE $(shell						\
diff --git a/tracecmd/Makefile b/tracecmd/Makefile
index 29a623b..7fa3974 100644
--- a/tracecmd/Makefile
+++ b/tracecmd/Makefile
@@ -62,7 +62,7 @@ $(all_objs): | $(bdir)
 $(bdir)/trace-cmd: $(ALL_OBJS)
 	$(Q)$(do_app_build)
 
-$(bdir)/trace-cmd: $(LIBTRACECMD_STATIC) $(LIBTRACEEVENT_STATIC)
+$(bdir)/trace-cmd: $(LIBTRACECMD_STATIC) $(LIBTRACEEVENT_STATIC) $(builtin_plugins)
 
 $(bdir)/%.o: %.c
 	$(Q)$(call do_compile)
