How to simplify this Makefile with loop - makefile

I have lines like these in my Makefile, can anyone suggest how to write a loop for it, or any other way to simplify it.
OBJS :=
obj-y :=
include cpu/Makefile
OBJS += $(patsubst %,cpu/%, $(obj-y))
obj-y :=
include drivers/Makefile
OBJS += $(patsubst %,drivers/%, $(obj-y))
obj-y :=
include lib/Makefile
OBJS += $(patsubst %,lib/%, $(obj-y))
obj-y :=
include init/Makefile
OBJS += $(patsubst %,init/%, $(obj-y))
...
Internal Makefiles are without any target and are used for include purpose only. For example cpu/Makefile is something like this:
obj-$(CONFIG_XYZ) += something.c
obj-$(CONFIG_ABC) += something_else.c
All configs are either set to y or n

Let's take this in stages.
First, patsubst is overkill for this job; addprefix will do:
obj-y :=
include cpu/Makefile
OBJS += $(addprefix cpu/, $(obj-y))
Then notice that we can pull "cpu" out as a variable:
DIR=cpu
obj-y :=
include $(DIR)/Makefile
OBJS += $(addprefix $(DIR)/, $(obj-y))
Then use eval and a recipe template or "canned recipe":
define ADD_OBJECTS
obj-y :=
include $(1)/Makefile
OBJS += $$(addprefix $(1)/, $$(obj-y))
endef
$(eval $(call ADD_OBJECTS,cpu))
Then put that eval statement in a foreach loop:
$(foreach DIR,cpu drivers lib init,$(eval $(call ADD_OBJECTS,$(DIR))))

Related

gccgo -shared symbol lookup using dlsym

I have been trying to use -buildmode=plugin but the .so file is too large. It's almost ~1MB for a simple file like
package main
var URI string
func Eval() bool {
return (URI == "Yes")
}
So an experiment I compiled with gccgo instead of go build -buildmode=pluginI ran the command
gccgo -o test.so -fPIC -shared test.go
The file size is really small now almost 16Kb.
The question is can I look up symbols in the above .so file using dlsym? Looks like dlsym retrieves C symbols and not Go symbols. Any way to retrieve, set go symbols?
Update:
nm output
U __gcc_personality_v0
U getenv
U getpagesize
w __gmon_start__
0000000000002eb3 T __go_init_main
U internal..z2fbytealg..types
U internal..z2fcpu..import
U internal..z2fcpu..types
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000022d9 T main.Eval
0000000000006d20 D main.Eval..f
00000000000024bd T main.struct.4runtime.gList.2.runtime.n.0int32.5..eq
0000000000006d28 D main.struct.4runtime.gList.2.runtime.n.0int32.5..eq..f
0000000000002760 T main.struct.4Size.0uint32.2Mallocs.0uint64.2Frees.0uint64.5..eq
0000000000006d30 D main.struct.4Size.0uint32.2Mallocs.0uint64.2Frees.0uint64.5..eq..f
0000000000006d40 D main..types
0000000000007150 D main.URI
U malloc
U memcmp
00000000000000b8 B __morestack_current_segment
0000000000000000 B __morestack_initial_sp
00000000000000c0 B __morestack_segments
U protect
Fn Call:
sym := s
eval, err := h.GetSymbolPointer(sym)
if err != nil {
fmt.Printf("Didn't find it ")
return -1, fmt.Errorf("Unable to find symbol")
}
x := (*func() bool)(eval)
test := (*x)() //Panics here straight away
_ = test
return 0, nil
}

How do I get the root directory of a relative path

I need to extract the name first of the first directory in a relative path.
I know I can go about:
relPath := "a/b/c/file.so"
splitPath := strings.Split(relPath, string(os.PathSeparator))
rootDirName := splitPath[0]
Is there a better way?
If you're asking whether there is way to do it with 1 standard Go function: not that I know of.
An alternative way would be:
relPath := "a/b/c/file.so"
i := strings.Index(relPath, string(os.PathSeparator))
rootDirName := relPath[:i]
Or if it is possible that the path contains no / at all:
relPath := "a/b/c/file.so"
i := strings.Index(relPath, string(os.PathSeparator))
rootDirName := ""
if i != -1 {
rootDirName = relPath[:i]
}
This has the benefit of not having to split the whole string and might, therefore, be a little faster on long paths.

Makefile: LKM sources as variables not working

I tried to compile a loadable kernel module, when I stumbled across this weird problem:
obj-m := $(ROOTKIT).o
# $(ROOTKIT)-y += $(CORE_OBJS) $(SRCS_OBJS) $(LIBS_OBJS) $(INCL_OBJS)
$(ROOTKIT)-y += src/core.o src/libs/syscalltable.o src/network_keylog.o src/server.o
$(ROOTKIT)-y += src/module_hiding.o src/getdents_hook.o src/socket_hiding.o src/packet_hiding.o
$(ROOTKIT)-y += src/port_knocking.o src/privilege_escalation.o src/include/utils.o
ccflags-y := -I$(SRCS_H) -I$(LIBS_H) -I$(INCL_H)
This code works fine as is. But when I use the single line $(ROOTKIT)-y which is commented above instead of the three-liner, it only compiles the $(CORE_OBJS) which is only one file. I get the output that all functions defined in the other files are undefined.
Why is that so, even though echo says the content of these variables are the exact same as writing out every filename? Is there a way listing the object files in variables or do i have to manually type all of them every time I add files in the future?
Output of the $(XXXX_OBJS) variables:
src/core.o
src/network_keylog.o src/packet_hiding.o src/module_hiding.o src/getdents_hook.o src/port_knocking.o src/server.o src/socket_hiding.o src/privilege_escalation.o
src/libs/syscalltable.o
src/include/utils.o
EDIT: To have a look at the complete Makefile:
# Module name
ROOTKIT := rootkit
# Build
UNAME := $(shell uname -r)
MODULEDIR := /lib/modules/$(UNAME)
BUILDDIR := $(MODULEDIR)/build
KERNELDIR := $(MODULEDIR)/kernel
# Source files
SRCS_S := src
LIBS_S := src/libs
INCL_S := src/include
# Header files
SRCS_H := $(PWD)/$(SRCS_S)/headers
LIBS_H := $(PWD)/$(LIBS_S)/headers
INCL_H := $(PWD)/$(INCL_S)/headers
# Initial file
CORE := src/core.c
# Objects
CORE := src/core.c
CORE_OBJS := $(patsubst %.c, %.o, $(CORE))
SRCS_OBJS := $(patsubst %.c, %.o, $(filter-out $(CORE), $(wildcard $(SRCS_S)/*.c)))
LIBS_OBJS := $(patsubst %.c, %.o, $(wildcard $(LIBS_S)/*.c))
INCL_OBJS := $(patsubst %.c, %.o, $(wildcard $(INCL_S)/*.c))
# Module
obj-m := $(ROOTKIT).o
# $(ROOTKIT)-y += $(CORE_OBJS) $(SRCS_OBJS) $(LIBS_OBJS) $(INCL_OBJS)
$(ROOTKIT)-y += src/core.o src/libs/syscalltable.o src/network_keylog.o src/server.o
$(ROOTKIT)-y += src/module_hiding.o src/getdents_hook.o src/socket_hiding.o src/packet_hiding.o
$(ROOTKIT)-y += src/port_knocking.o src/privilege_escalation.o src/include/utils.o
ccflags-y := -I$(SRCS_H) -I$(LIBS_H) -I$(INCL_H)
# Recipes
all:
$(MAKE) -C $(BUILDDIR) M=$(PWD) modules
load:
insmod $(KERNELDIR)/net/ipv4/netfilter/nf_reject_ipv4.ko
insmod $(KERNELDIR)/net/ipv6/netfilter/nf_reject_ipv6.ko
insmod rootkit.ko
clean:
$(MAKE) -C $(BUILDDIR) M=$(PWD) clean
You seem to be misusing substitution references.
SRCS := foo.c
OBJS_1 := $(SRCS:.c=.o) # evaluates to 'foo.o'
OBJS_2 := $($(SRCS):.c=.o) # evaluates to nothing
The assignment to OBJS_1 is how substitution refs work; the assignment to OBJS_2 is simply a syntax error, it expands to $(foo.c:.c=.o) and then to '' (since there's no variable with that name). So your assignments like this one:
LIBS_OBJS := $($(wildcard $(LIBS_S)/*.c):.c=.o)
result in empty variables. I don't know how you got the "Output of the $(XXXX_OBJS) variables" (since nothing in your makefile actually displays them), but in fact only CORE_OBJS contains anything, and that's all that gets into $(ROOTKIT)-y.
To fix it, just forgo the substitution references and use patsubst:
LIBS_OBJS := $(patsubst %.c, %.o, $(wildcard $(LIBS_S)/*.c))
EDIT: all right, let's start small and build up.
Step 1: Try the following makefile, and tell us the result (in a comment):
SRCS_S := src
SRCS_OBJS := $(patsubst %.c, %.o, $(wildcard $(SRCS_S)/*.c))
SRC_LIST += $(SRCS_OBJS)
$(info $(SRC_LIST))
(If the output is unmanageable, you might try it with a source directory containing foo.c and bar.c)

GNU make and nmake: computed names with multiple values

GNU make manual describes usage of computed names as follows:
VAR1 := 5
VARX := VAR1
$(info $((VARX)))
Output: 5
How to use computed name with multiple values inside?
VAR1 := 5
VAR2 := 7
VARY := VAR1 VAR2
$(info ???(VARY))
So that output would be 5 7?
Does NMake have similar functionality?
For GNU-make:
$(foreach item,$(VARY),$($(item)))

How can I OR together to gnumakefile conditions?

Using gmake v3.80, how can I create a rule that ORs together two things. I'm starting with this code:
ifeq "$(BUILD_ARCH)" "lnx86_22"
TEST_ARCH := i86
endif
ifeq "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
And would like to combine the two ifeq(s) into a single if that ORs the two conditions together, perhaps something like this?
ifeq "$(BUILD_ARCH)" "lnx86_22" OR "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
What is the actual syntax that would allow me to do this?
You can use $(filter ...) for that. Like this:
ifneq (,$(filter $(BUILD_ARCH),lnx86_22 linux_24_i86))
TEST_ARCH := i86
endif
Another option would be to use constructed variable names:
lnx86_22_ARCH := i86
linux_24_i86_ARCH := i86
...
TEST_ARCH := $($(BUILD_ARCH)_ARCH)
ifeq (,$(TEST_ARCH))
$(error Failed, unknown arch $(BUILD_ARCH))
Failed, unknown arch $(BUILD_ARCH)
endif
If you are able to upgrade to newer versions of GNU make there are other options available.

Resources