[FTRACE] vmlinux __mcount_loc section

 [FTRACE] vmlinux __mcount_loc section

kernel/scripts/Makefile.build

ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
ifdef BUILD_C_RECORDMCOUNT
ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
  RECORDMCOUNT_FLAGS = -w
endif
# Due to recursion, we must skip empty.o.
# The empty.o file is created in the make process in order to determine
# the target endianness and word size. It is made before all other C
# files, including recordmcount.
sub_cmd_record_mcount =					
	if [ $(@) != "scripts/mod/empty.o" ]; then	
		$(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)";	
	fi;
recordmcount_source := $(srctree)/scripts/recordmcount.c 
		    $(srctree)/scripts/recordmcount.h
else
sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" 
	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" 
	"$(if $(CONFIG_64BIT),64,32)" 
	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" 
	"$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" 
	"$(if $(part-of-module),1,0)" "$(@)";
recordmcount_source := $(srctree)/scripts/recordmcount.pl
endif # BUILD_C_RECORDMCOUNT
cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),	
	$(sub_cmd_record_mcount))
endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT

s上面record mcount有两种类型,一个是c语言类型,另一个是perl类型

# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
    $(call if_changed_rule,cc_o_c)
    $(call cmd,force_checksrc)
$(call if_changed_rule,cc_o_c)就会call rule_cc_o_c:
define rule_cc_o_c
    $(call cmd_and_fixdep,cc_o_c)
    $(call cmd,gen_ksymdeps)
    $(call cmd,checksrc)
    $(call cmd,checkdoc)
    $(call cmd,objtool)
    $(call cmd,modversions_c)
    $(call cmd,record_mcount)
endef

会对kernel里的每一个c文件对应的.o文件进行处理,处理完后形成__mcount_loc section:

kernel/include/asm-generic/vmlinux.lds.h

#ifdef CONFIG_FTRACE_MCOUNT_RECORD
/*
 * The ftrace call sites are logged to a section whose name depends on the
 * compiler option used. A given kernel image will only use one, AKA
 * FTRACE_CALLSITE_SECTION. We capture all of them here to avoid header
 * dependencies for FTRACE_CALLSITE_SECTION's definition.
 *
 * Need to also make ftrace_stub_graph point to ftrace_stub
 * so that the same stub location may have different protocols
 * and not mess up with C verifiers.
 */
#define MCOUNT_REC()	. = ALIGN(8);				
			__start_mcount_loc = .;			
			KEEP(*(__mcount_loc))			
			KEEP(*(__patchable_function_entries))	
			__stop_mcount_loc = .;			
			ftrace_stub_graph = ftrace_stub;

  

reference: https://www.cnblogs.com/openix/p/4163995.html

原文地址:https://www.cnblogs.com/aspirs/p/14696965.html