diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 8450657..64580e9 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1826,6 +1826,114 @@ void kpatch_create_dynamic_rela_sections(struct kpatch_elf *kelf,
 	sec->sh.sh_size = sec->data->d_size;
 }
 
+/*
+ * This function basically reimplements the functionality of the Linux
+ * recordmcount script, so that patched functions can be recognized by ftrace.
+ *
+ * TODO: Eventually we can modify recordmount so that it recognizes our bundled
+ * sections as valid and does this work for us.
+ */
+void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
+{
+	int nr, size, index;
+	struct section *sec, *relasec;
+	struct symbol *sym;
+	struct rela *rela;
+	void **funcs, *newdata;
+	unsigned char *insn;
+
+	nr = 0;
+	list_for_each_entry(sym, &kelf->symbols, list)
+		if (sym->type == STT_FUNC && sym->status != SAME)
+			nr++;
+
+	/* create __mcount_loc */
+
+	/* allocate section resources */
+	ALLOC_LINK(sec, &kelf->sections);
+	size = nr * sizeof(*funcs);
+	funcs = malloc(size);
+	if (!funcs)
+		ERROR("malloc");
+	sec->name = "__mcount_loc";
+
+	/* set data */
+	sec->data = malloc(sizeof(*sec->data));
+	if (!sec->data)
+		ERROR("malloc");
+	sec->data->d_buf = funcs;
+	sec->data->d_size = size;
+	sec->data->d_type = ELF_T_BYTE;
+
+	/* set section header */
+	sec->sh.sh_type = SHT_PROGBITS;
+	sec->sh.sh_entsize = sizeof(*funcs);
+	sec->sh.sh_addralign = 8;
+	sec->sh.sh_flags = SHF_ALLOC;
+	sec->sh.sh_size = size;
+
+	/* create .rela__mcount_loc */
+
+	/* allocate section resources */
+	ALLOC_LINK(relasec, &kelf->sections);
+	relasec->name = ".rela__mcount_loc";
+	relasec->base = sec;
+	INIT_LIST_HEAD(&relasec->relas);
+
+	/* set data, buffers generated by kpatch_rebuild_rela_section_data() */
+	relasec->data = malloc(sizeof(*relasec->data));
+	if (!relasec->data)
+		ERROR("malloc");
+
+	/* set section header */
+	relasec->sh.sh_type = SHT_RELA;
+	relasec->sh.sh_entsize = sizeof(GElf_Rela);
+	relasec->sh.sh_addralign = 8;
+
+	/* populate sections */
+	index = 0;
+	list_for_each_entry(sym, &kelf->symbols, list) {
+		if (sym->type != STT_FUNC || sym->status == SAME)
+			continue;
+
+		/* add rela in .rela__mcount_loc to fill in function pointer */
+		ALLOC_LINK(rela, &relasec->relas);
+		rela->sym = sym;
+		rela->type = R_X86_64_64;
+		rela->addend = 0;
+		rela->offset = index * sizeof(*funcs);
+
+		/*
+		 * Modify the first instruction of the function to "callq
+		 * __fentry__" so that ftrace will be happy.
+		 */
+		newdata = malloc(sym->sec->data->d_size);
+		memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+		sym->sec->data->d_buf = newdata;
+		insn = newdata;
+		if (insn[0] != 0xf)
+			ERROR("bad first instruction in %s", sym->name);
+		insn[0] = 0xe8;
+		insn[1] = 0;
+		insn[2] = 0;
+		insn[3] = 0;
+		insn[4] = 0;
+
+		rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+					list);
+		if (rela->type != R_X86_64_NONE ||
+		    strcmp(rela->sym->name, "__fentry__"))
+			ERROR("bad first rela in %s", sym->sec->rela->name);
+		rela->type = R_X86_64_PC32;
+
+		index++;
+	}
+
+	/* sanity check, index should equal nr */
+	if (index != nr)
+		ERROR("size mismatch in funcs sections");
+}
+
 /*
  * This function strips out symbols that were referenced by changed rela
  * sections, but the rela entries that referenced them were converted to
@@ -2195,6 +2303,8 @@ int main(int argc, char *argv[])
 	kpatch_create_dynamic_rela_sections(kelf_out, lookup, hint, name);
 	kpatch_build_strings_section_data(kelf_out);
 
+	kpatch_create_mcount_sections(kelf_out);
+
 	/*
 	 *  At this point, the set of output sections and symbols is
 	 *  finalized.  Reorder the symbols into linker-compliant
diff --git a/kpatch-build/list.h b/kpatch-build/list.h
index 825fd95..877aa85 100644
--- a/kpatch-build/list.h
+++ b/kpatch-build/list.h
@@ -161,6 +161,17 @@ static inline void list_replace(struct list_head *old,
 #define list_entry(ptr, type, member) \
 	container_of(ptr, type, member)
 
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr:	the list head to take the element from.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+	list_entry((ptr)->next, type, member)
+
 /**
  * list_for_each_entry	-	iterate over list of given type
  * @pos:	the type * to use as a loop counter.