prefix = /usr
datarootdir = ${prefix}/share
datadir = /usr/share

ksplice-script = $(datadir)/ksplice/ksplice-obj.pl

KSPLICE_KID ?= $(error "You must set KSPLICE_KID.")
KSPLICE_VERSION ?= $(error "You must set KSPLICE_VERSION.")
map_printk ?= $(error "You must set map_printk.")

ifneq ($(KSPLICE_STANDALONE),)
    KSPLICE_CFLAGS += -DKSPLICE_STANDALONE
endif
KSPLICE_CFLAGS += -DKSPLICE_KID=$(KSPLICE_KID)
KSPLICE_CFLAGS += -DMAP_PRINTK=0x$(map_printk)L

comma ?= ,
name-fix ?= $(subst $(comma),_,$(subst -,_,$(1)))
target = $(call name-fix,$(mod))
KSPLICE_MID = $(KSPLICE_KID)_$(target)
KSPLICE = ksplice-$(KSPLICE_MID)
KSPLICE_CORE = ksplice-$(KSPLICE_KID)

quiet_cmd_ksplice-collect = COLLECT $@
cmd_ksplice-collect = \
	$(ksplice-script) finalize $< $<.final $* && \
	$(LD) --script=$(obj)/ksplice.lds -r -o $@ $<.final

ksplice-pack-cflags = $(KSPLICE_CFLAGS) \
	"-DKSPLICE_MID=$(KSPLICE_MID)" \
	$(addprefix -DKSPLICE_TARGET=,$(target)) \
	"-DKSPLICE_VERSION=\"$(KSPLICE_VERSION)\""

ksplice-primary-objs = primary-$(target).o collect-primary-$(mod).o
ksplice-helper-objs = helper-$(target).o collect-helper-$(mod).o

ifneq ($(KSPLICE_STANDALONE),)
obj-m += $(KSPLICE_CORE).o
UDIS86 = x86/libudis86
kudis86 += \
	$(UDIS86)/itab.o \
	$(UDIS86)/input.o \
	$(UDIS86)/decode.o \
	$(UDIS86)/syn.o \
	$(UDIS86)/syn-intel.o \
	$(UDIS86)/syn-att.o \
	$(UDIS86)/udis86.o
$(KSPLICE_CORE)-objs = ksplice-rmsyms.o $(kudis86)
endif

define ksplice-pack-vars
obj-m += $(KSPLICE).o $(KSPLICE)-helper.o
$(KSPLICE)-objs = $(ksplice-primary-objs)
$(KSPLICE)-helper-objs = $(ksplice-helper-objs)
CFLAGS_primary-$(target).o = $(ksplice-pack-cflags)
CFLAGS_helper-$(target).o = $(ksplice-pack-cflags)
CPPFLAGS_ksplice.lds = $(ksplice-pack-cflags) -P
endef

$(foreach mod,$(KSPLICE_MODULES),$(eval $(ksplice-pack-vars)))

ifneq ($(KSPLICE_MODULES),)
$(foreach mod,$(KSPLICE_MODULES),$(obj)/primary-$(target).o): $(obj)/%.o: $(src)/primary.c FORCE
	$(call if_changed_rule,cc_o_c)
$(foreach mod,$(KSPLICE_MODULES),$(obj)/helper-$(target).o): $(obj)/%.o: $(src)/helper.c FORCE
	$(call if_changed_rule,cc_o_c)
endif

$(obj)/collect-primary-%.o: $(obj)/%.o.KSPLICE_primary $(obj)/ksplice.lds FORCE
	$(call if_changed,ksplice-collect)
$(obj)/collect-helper-%.o: $(obj)/%.o.KSPLICE_helper $(obj)/ksplice.lds FORCE
	$(call if_changed,ksplice-collect)

ifeq ($(quiet_cmd_cpp_lds_S),)
quiet_cmd_cpp_lds_S = LDS     $@
      cmd_cpp_lds_S = $(CPP) -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) $(cpp_flags) -D__ASSEMBLY__ -o $@ $<

%.lds: %.lds.S FORCE
	$(call if_changed_dep,cpp_lds_S)
endif

$(obj)/ksplice.lds: $(src)/ksplice.lds.S FORCE
	$(call if_changed_dep,cpp_lds_S)

CFLAGS_offsets.o += $(KSPLICE_CFLAGS)
extra-y += offsets.o

ifneq ($(KSPLICE_STANDALONE),)
CFLAGS_ksplice.o += $(KSPLICE_CFLAGS)
extra-y += ksplice.o

RMSYMS = \
	apply_paravirt \
	find_bug \
	search_exception_tables \
	thread_return \
	bust_spinlocks \
	task_curr \
	__kernel_text_address \
	tasklist_lock \
	stop_machine_run \
	module_mutex \
	modules \
	init_mm \
	phys_base \
	kallsyms_addresses \
	kallsyms_num_syms \
	kallsyms_names \
	kallsyms_token_table \
	kallsyms_token_index \
	__module_text_address \
	__start___ksymtab \
	__stop___ksymtab \
	__start___ksymtab_gpl \
	__stop___ksymtab_gpl \
	__start___ksymtab_gpl_future \
	__stop___ksymtab_gpl_future \
	__start___ksymtab_unused \
	__stop___ksymtab_unused \
	__start___ksymtab_unused_gpl \
	__stop___ksymtab_unused_gpl \
	__start___ksymtab_gpl_future \
	__stop___ksymtab_gpl_future \
	__start___kcrctab \
	__start___kcrctab_gpl \
	__start___kcrctab_gpl_future \
	__start___kcrctab_unused \
	__start___kcrctab_unused_gpl \
	ftrace_trace_function

quiet_cmd_ksplice-rmsyms = RMSYMS  $@
cmd_ksplice-rmsyms = \
	$(ksplice-script) rmsyms $< $<.rmsyms $(RMSYMS) && \
	$(LD) -r -o $@ $<.rmsyms $(src)/ksplice-rmsyms.lds
$(obj)/ksplice-rmsyms.o: $(obj)/ksplice.o $(obj)/offsets.o FORCE
	$(call if_changed,ksplice-rmsyms)
endif # KSPLICE_STANDALONE
