How to keep asm output from Linux kernel module build - linux

I'm working on a Linux kernel module for a 2.6.x kernel and I need to view the assembly output, though it's currently being done as a temporary file an deleted afterwords. I'd like to have the assembly output mixed with my C source file so I can easily trace where my problem lies. This is for an ARMv6 core and apparently objdump doesn't support this architecture. I've included my makefile below.
ETREP=/xxSourceTreexx/
GNU_BIN=$(ETREP)/arm-none-linux-gnueabi/bin
CROSS_COMPILE := $(GNU_BIN)/arm-none-linux-gnueabi-
ARCH := arm
KDIR=$(ETREP)/linux-2.6.31/
MAKE= CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) make
obj-m += xxfile1xx.o
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean

Objdump does support that architecture. Your executable will be called arm-none-linux-gnueabi-objdump

Assuming gcc and the gnu assembler a more readable output than objdump can be had. Tell the assembler to retain its intermediate code using flags to gcc:
-Wa,-alh=basename.s
And to get basename to be the actual source filename you need to tell make:
-Wa,-alh=$<.s
which will leave piles of foo.c.s files laying around your source directory. The big problem here is that the way gcc works it uses temporary files between code generation and assembly. I can't find a way to make gcc save its intermediates but the assembler is happy to stash a listing for you.
Getting that argument into the Makefile CFLAGS is left as an exercise for the reader (because I kinda hate "make" and hate "gnu info" even more.

To get an assembly language listing of my Linux kernel modules, I added the assembler switches to the kernel scripts/Makefile.build.
#cmd_cc_o_c = $(CC) $(c_flags) -c -o $(#D)/.tmp_$(#F) $<
cmd_cc_o_c = $(CC) $(c_flags) -c -Wa,-alh=$<.lst -o $(#D)/.tmp_$(#F) $<

You could try the flag "-save-temps" to gcc.
It works for me in my embedded project, I haven't tried it on kernel builds.

The proper way is likely to add target dependencies in your module makefile / Kbuild file:
always-m += basename.s
(As kbuild has the proper targets to generate the .s files)
If you are lazy as I am, this could look like:
MOD_NAME := some_module_name
myunits := file1 file2 file3 ... and many more... without .c extension
obj-m := $(MOD_NAME).o
$(MOD_NAME)-y := $(addsuffix .o,$(myunits))
# Comment/uncomment to generate assembly / preprocessor output
always-m += $(addsuffix .s,$(myunits)) $(MOD_NAME).mod.s
always-m += $(addsuffix .i,$(myunits)) $(MOD_NAME).mod.i
(2 bonuses here: assembly for the generated module meta-registration file, and the preprocessor output)

Related

How do I correctly link a shared object (.so file) in a makefile when cross-compiling?

I have some C++ code on an openSuse platform that I need to compile to be executed on a different linux-based target. Part of the code is a dynamic library libfoo.so. I compile everything with make and then copy the compiled executable prog together with the libfoo.so to the target. When I then run the executable, I get some errors indicating the libfoo could not be initialized. I've tried everything I could find to tell the executable where it can find the libfoo.so but I still get the error.
Could anybody tell me what I am doing wrong here? I feel like it could be an error in the Makefile.
I am very new to C++ and using Makefiles in general, and on top of it all, the target runs kind of a proprietary linux version, so I cannot provide much information about it. I do have the appropriate compiler for it though.
My directory structure on the openSuse platform:
|src
|--Foolib
|----foolib.h
|----libfoo.so
|--Otherlib
|----otherlib.h
|----otherlib.hpp
|---+OtherlibSrcDirectory
|--bar.cpp
|--bar.h
|--Makefile
Directory structure on the target:
|program
|--libfoo.so
|--prog
My Makefile:
LIBS = -LFoolib -lfoo
INC = -I OtherLib -I Foolib
CXXFLAGS += -lpthread -std=c++11 -D_GLIBCXX_USE_NANOSLEEP $(INC)
LDFLAGS = '-Wl,-rpath,$$ORIGIN'
SRC_FILES = bar.cpp
OBJ = $(SRC_FILES:%.cpp=%.o)
prog: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) -o $# $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(LIBS) -c $<
Basically, bar.h includes Foolib/foolib.h as well as Otherlib/OtherlibSrcDirectory and bar.cpp includes bar.h. Then some functions from foolib.h are called in bar.cpp and they return error values. If necessary I can provide some more insights into the code but I'll leave it out for now to keep it a bit shorter.
Any help would be highly appreciated!
Found my mistake.
libfoo.so was already on the target machine and it was located in the correct folder (/lib). My program had been able to find it without problems.
My mistake: I executed my program on the target machine without root permissions.
Without root permissions, I am not allowed to initialize Foolib.
sudo ./prog fixed everything.

header and c files not included in build linux kernel

For a lpc3250 board, we had to developer a Linux kernel module to control the PWM output. I've created a 'helper' module which contains methodes like PMW1_ENABLE which set the correct bit at 1.
Unfortunately I run into problems when I create multiple .c and .h files. When I put all the code in just 1 file, the solution works fine. When I split it nicely in additional .c and .h files, something weird is happening. Even just printk statements do not show up on the console.
Most weird part, during cross compiling, no errors are shown so it looks like the binary is ok but it isn't.
Does this sound familiair? Could it be an issue with my makefile?
ARCH := arm
CROSS_COMPILE := /usr/local/xtools/arm-unknown-linux-uclibcgnueabi/bin/arm-linux-
CC= $(CROSS_COMPILE)gcc
obj-m := pwmdriver.o
pwmdriver-objs := pwmhelper.o pwmdriver.o
KDIR := /home/student/felabs/sysdev/tinysystem/linux-2.6.34
WORKINGDIRFIXED := /home/student/PRT/5_AssigPWM
export
all:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) modules
clean:
$(MAKE) -C $(KDIR) M=$(WORKINGDIRFIXED) clean

How to specify directory when use "gcc -c" to generate *.o files? [duplicate]

I am wondering why gcc/g++ doesn't have an option to place the generated object files into a specified directory.
For example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
I know that it's possible to achive this with separate -o options given to the compiler, e.g.:
gcc -c file1.c -o ../builddir/objdir/file1.o
gcc -c file2.c -o ../builddir/objdir/file2.o
gcc -c file3.c -o ../builddir/objdir/file3.o
... and I know that I can write Makefiles via VPATH and vpath directives to simplify this.
But that's a lot of work in a complex build environment.
I could also use
gcc -c file1.c file2.c file3.c
But when I use this approach my srcdir is full of .o garbage afterwards.
So I think that an option with the semantics of --outdir would be very useful.
What is your opinion?
EDIT: our Makefiles are written in such a way that .o files actually placed into builddir/obj. But I am simply wondering if there might be a better approach.
EDIT: There are several approaches which place the burden to achieve the desired behavior to the build system (aka Make, CMake etc.). But I consider them all as being workarounds for a weakness of gcc (and other compilers too).
This is the chopped down makefile for one of my projects, which compiles the sources in 'src' and places the .o files in the directory "obj". The key bit is the the use of the patsubst() function - see the GNU make manual (which is actually a pretty good read) for details:
OUT = lib/alib.a
CC = g++
ODIR = obj
SDIR = src
INC = -Iinc
_OBJS = a_chsrc.o a_csv.o a_enc.o a_env.o a_except.o \
a_date.o a_range.o a_opsys.o
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
$(OUT): $(OBJS)
ar rvs $(OUT) $^
.PHONY: clean
clean:
rm -f $(ODIR)/*.o $(OUT)
How about changing to the directory and running the compile from there:
cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c
That's it. gcc will interpret includes of the form #include "path/to/header.h" as starting in the directory the file exists so you don't need to modify anything.
A trivial but effective workaround is to add the following right after the gcc call in your Makefile:
mv *.o ../builddir/objdir
or even a soft-clean (possibly recursive) after the compilation is done, like
rm -f *.o
or
find . -name \*.o -exec rm {} \;
You can use a simple wrapper around gcc that will generate the necessary -o options and call gcc:
$ ./gcc-wrap -c file1.c file2.c file3.c --outdir=obj
gcc -o obj/file1.o -c file1.c
gcc -o obj/file2.o -c file2.c
gcc -o obj/file3.o -c file3.c
Here is such a gcc_wrap script in its simplest form:
#!/usr/bin/perl -w
use File::Spec;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure(pass_through);
my $GCC = "gcc";
my $outdir = ".";
GetOptions("outdir=s" => \$outdir)
or die("Options error");
my #c_files;
while(-f $ARGV[-1]){
push #c_files, pop #ARGV;
}
die("No input files") if(scalar #c_files == 0);
foreach my $c_file (reverse #c_files){
my($filename, $c_path, $suffix) = fileparse($c_file, ".c");
my $o_file = File::Spec->catfile($outdir, "$filename.o");
my $cmd = "$GCC -o $o_file #ARGV $c_file";
print STDERR "$cmd\n";
system($cmd) == 0 or die("Could not execute $cmd: $!");
}
Of course, the standard way is to solve the problem with Makefiles, or simpler, with CMake or bakefile, but you specifically asked for a solution that adds the functionality to gcc, and I think the only way is to write such a wrapper. Of course, you could also patch the gcc sources to include the new option, but that might be hard.
I believe you got the concept backwards...?!
The idea behind Makefiles is that they only process the files that have been updated since the last build, to cut down on (re-)compilation times. If you bunch multiple files together in one compiler run, you basically defeat that purpose.
Your example:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
You didn't give the 'make' rule that goes with this command line; but if any of the three files has been updated, you have to run this line, and recompile all three files, which might not be necessary at all. It also keeps 'make' from spawning a seperate compilation process for each source file, as it would do for seperate compilation (when using the '-j' option, as I would strongly suggest).
I wrote a Makefile tutorial elsewhere, which goes into some extra detail (such as auto-detecting your source files instead of having them hard-coded in the Makefile, auto-determining include dependencies, and inline testing).
All you would have to do to get your seperate object directory would be to add the appropriate directory information to the OBJFILES := line and the %.o: %.c Makefile rule from that tutorial. Neil Butterworth's answer has a nice example of how to add the directory information.
(If you want to use DEPFILES or TESTFILES as described in the tutorial, you'd have to adapt the DEPFILES := and TSTFILES := lines plus the %.t: %.c Makefile pdclib.a
rule, too.)
Meanwhile I found a "half-way" solution by using the -combine option.
Example:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o
this "combines" all source files into one single object file.
However, this is still "half-way" because it needs to recompile everything when only one source file changes.
I think that telling pass gcc doesn't have an separate option to say where to put object file, since it already has it. It's "-c" - it says in what directory to put object.
Having additional flag for directory only must change meening of "-c".
For example:
gcc -c file.c -o /a/b/c/file.o --put-object-in-dir-non-existing-option /a1/a2/a3
You can not put /a/b/c/file.o under /a1/a2/a3, since both paths are absolute. Thus "-c" should be changed to name object file only.
I advise you to consider a replacement of makefile, like cmake, scons and other.
This will enable to implement build system as for for simple project as well as for bigger one too.
See for example how it's easy to compile using cmake your example.
Just create file CMakeList.txt in srcdir/:
cmake_minimum_required(VERSION 2.6)
project(test)
add_library(test file1.c file2c file3.c)
And now type:
mkdir -p builddir/objdir
cd builddir/objdir
cmake ../../srcdir
make
That's all, object files will reside somewhere under builddir/objdir.
I personaly use cmake and find it very convinient. It automatically generates dependencies and has other goodies.
I am trying to figure out the same thing. For me this worked
CC = g++
CFLAGS = -g -Wall -Iinclude
CV4LIBS = `pkg-config --libs opencv4`
CV4FLAGS = `pkg-config --cflags opencv4`
default: track
track: main.o
$(CC) -o track $(CV4LIBS) ./obj/main.o
ALLFLAGS = $(CFLAGS) $(CV4FLAGS)
main.o: ./src/main.cpp ./include/main.hpp
$(CC) $(ALLFLAGS) -c ./src/main.cpp $(CV4LIBS) -o ./obj/main.o
``
This is among the problems autoconf solves.
If you've ever done ./configure && make you know what autoconf is: it's the tool that generates those nice configure scripts. What not everyone knows is that you can instead do mkdir mybuild && cd mybuild && ../configure && make and that will magically work, because autoconf is awesome that way.
The configure script generates Makefiles in the build directory. Then the entire build process happens there. So all the build files naturally appear there, not in the source tree.
If you have source files doing #include "../banana/peel.h" and you can't change them, then it's a pain to make this work right (you have to copy or symlink all the header files into the build directory). If you can change the source files to say #include "libfood/comedy/banana/peel.h" instead, then you're all set.
autoconf is not exactly easy, especially for a large existing project. But it has its advantages.
Personally for single files I do this,
rm -rf temps; mkdir temps; cd temps/ ; gcc -Wall -v --save-temps ../thisfile.c ; cd ../ ; geany thisfile.c temps/thisfile.s temps/thisfile.i
temps folder will keep all the object, preprocessed and assembly files.
This is a crude way of doing things and I would prefer above answers using Makefiles.

Compiling out-of-tree kernel module against any kernel source tree on the filesystem

I am trying to compile a module against any source tree on the file system but I am having trouble with the Makefile. This was the original Makefile I had against the kernel specified:
obj-m += new-mod.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
This Makefile would compile correctly, but goal is to have it compile against any source tree. I have tried just:
obj-m += new-mod.o
I thought that "all:" is assumed but I get error:
make: *** No targets. Stop.
I have also added:
all:
to the Makefile with no difference except for error message:
make: Nothing to be done for `all'
I have tried a lot of documentation but no luck. I would greatly appreciate any help.
goal is to have it compile against any source tree
ya you can do it providing a compiled source-code path
just replace make -C /lib/modules/$(shell uname -r)/build M=$PWD modules
with this
make -C <path-to-compiled-src-code> M=$PWD modules
make -C /home/vinay/linux-3.9 M=$PWD modules
try below makefile
Makefile –
# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
obj-m := new-mod.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
KERNEL_SOURCE := /usr/src/linux
PWD := $(shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
clean:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif
In above you can change KERNEL_SOURCE := /usr/src/linux-->to.--> your sr-code KERNEL_SOURCE := <path to compiled-src-code>
for further info find below liks
while building kernel modules why do we need /lib/modules?
A simple program on linux device driver
How to make a built-in device driver in linux
Build against your custom kernel source ( not the one that is installed),
You can use following steps.
1.download kernel from kernel.org (tar)
2.Extract
3.make x86_64_defconfig
4.make prepare
5.make modules_prepare
Now you have to change Makefile to point to kernel source you had downloaded and extracted. Something similar mentioned in example by Vinay Answer.
Just remember you cannot insmod this module as kernel running and module built is for different kernel.

Requesting makefile writing tips

build: source1.c source2.c header.h lib.so
gcc source1.c source2.c -shared lib.so -o exec.bin
exec.bin: source1.o source.o
source1.o: source1.c
gcc source1.c -c -o source1.o
source2.o: source2.c
gcc source2.c -c -o source2.o
clean:
rm exec.bin source1.o source2.o
I have some instructions to make this Makefile which depends on those 4 source files to compile a program(the program context is irrelevant).
It also has to create the object files and compile only if modifications were made.
The code above is what I managed to write. I'm new at this and I can't seem to find out the problem is.
Generally, your prerequisites are messed up. You want to declare the prerequisites for the targets that need them. You also want each recipe to build exactly the target that you wrote in the makefile.
For example, you have a rule with a target build, but it creates an output file named exec.bin. That's not right: if the recipe creates a file named exec.bin then the target should be named exec.bin. If you want to have a pretend rule like build then you should declare it to be phony.
Also, you have header.h as a prerequisite of build. Even leaving aside the target name, do you re-link the objects when a header file changes? Not directly. You recompile source files when a header file changes. So the header file should be a prerequisite of the object file, not the executable.
Lastly, your life is much simpler if you leverage the built-in rules. You can rewrite your makefile like this:
CC = gcc
SRC = source1.c source2.c
LIB = lib.so
OBJ = $(SRC:%.c=%.o)
.PHONY: build
build: exec.bin
exec.bin: $(OBJ)
$(CC) $(OBJ) $(LIB) -o $#
$(OBJ): header.h
clean:
rm -f exec.bin $(OBJ)
We aren't defining rules on how to build object files from source files, because make already has built-in rules that will do that for us.
ETA:
If you can't use the built-in rules, then create your own pattern rule. For example:
XOBJ = $(SRC:%.c=%.xo)
%.xo : %.c
<whatever command>
$(XOBJ): header.h
Here's a tip for writing new Makefiles: don't do it. There are better tools available. For example, CMake is a very usable tool which generates Makefiles from a more legible language (unfortunately not a standard language like Python, but otherwise it's pretty nice).
CMake will automatically generate "clean" and "help" and other targets, plus more features you don't yet know you need (like optimized builds).
Here's something to get you started (name this file CMakeLists.txt):
add_library(foo SHARED source1.c source2.c)
add_executable(exec source3.c)
target_link_libraries(exec foo)

Resources