How to cross-compile ARM version of LKM? - linux-kernel

I need to perform MITM attack on a router, which is embedded linux system and its architecture is ARM. The linux kernel is 2.4.24. By MITM attack I mean intercept the packet, reedit it and send it forward. I want to use netfilter. But when I try to cross compile the LKM, I encountered plenty of problems.
As usual, a LKM Makefile is as below:
obj-m+=hello.o
KDIR = /lib/modules/$(shell uname -r)/build
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean
I downloaded linux kernel 2.4.24. But when it comes to the cross compile environment, the problems arise.
How to set KDIR path? The Path where linux_kernel_2.4.24.tar.gz is extracted? Do I need to cross-compile the kernel first? How?
Firstly, I set KDIR to the path of linux_kernel_2.4.24, then make, the error is "The present kernel configuration has modules disabled". By now I have not successfully make menuconfig this verion of kernel.
Secondly, I try to cross-compile on CentOS 5.4 32bit, whose kernel is 2.6.18. When I add CC=arm-linux-gcc to Makefile and set KDIR as /lib/modules/$(shell uname -r)/build, the result says "there is no arm...".
Can anyone specify how to compile LKM of the old version kernel on the latest linux? And how to cross-compile ARM version of LKM?

How to set KDIR path? The Path where linux_kernel_2.4.24.tar.gz is extracted?
Yes, just as you normally would for any other kind of module, KDIR needs to point to the built kernel source root.
Do I need to cross-compile the kernel first? How?
Yes you do. You do this by:
Downloading/compiling/installing the correct cross-compilation toolchain. For example, on Debian to get an ARM cross-compilation toolchain I can do sudo apt install binutils-arm-linux-gnueabi, which will install all the binaries you normally have in binutils with the prefix arm-linux-gnueabi- (e.g. arm-linux-gnueabi-gcc, arm-linux-gnueabi-objdump, etc...). You need all of the binutils, not only gcc.
Setting ARCH= to your desired target architecture, for example ARCH=arm.
Setting CROSS_COMPILE= to your cross-compilation toolchain prefix, for example CROSS_COMPILE=arm-linux-. This also works if you want to use a downloaded toolchain as you can specify CROSS_COMPILE=/path/to/toolchain/ assuming this directory contains all the needed executables.
Getting a valid config for the target system. If you have a .config on the system you can use that one (simply copy it from the target system into KDIR/.config) and then update it with make menuconfig.
Building with make all or whatever other target you need.

Related

Why does my kernel module Makefile build a .ko with kernel 4.14 but not 5.6?

I have a Makefile made by following this example:
cross compile kernel module
I built a 4.14 Linux kernel from an older Xilinx source, and then built a out-of-kernel module with that script, pointing it to the said 4.14 kernel sources, and filling in the blanks for my particular platform architecture.
That worked.
(It's based on this code, if that matters: dma-proxy.c)
Now I need a newer version, and got Xilinx sources with a kernel named 5.6.0-rc1.
(--branch "zynqmp-soc-for-v5.7" from here)
Building that kernel also worked fine.
If I now use a scrubbed clean directory (incl. hidden files) with my module source code and that Makefile again, pointing to the newer kernel sources, it does neither produce a .ko file nor an error message.
All I get is:
make ARCH=arm64 CROSS_COMPILE="aarch64-linux-gnu-" -C /home/sk/src/XILINX/linux-xlnx SUBDIRS=/home/sk/src/XILINX/dma-proxy/driver modules
make[1]: Entering directory '/home/sk/src/XILINX/linux-xlnx'
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
MODPOST 28 modules
make[1]: Leaving directory '/home/sk/src/XILINX/linux-xlnx'
No .ko file in my folder as it was before when building with 4.14, and it doesn't list actually compiling anything.
I find it curious that it says "MODPOST 28 modules", whereas with pointing it to kernel 4.14, it expectedly says "1 modules"
Has anything changed between 4.14 and 5.x that would cause this?
Mkay, here is the suggested makefile template by the tutorial I referenced in the question:
PWD := $(shell pwd)
obj-m += hello.o
all:
make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KERNEL) SUBDIRS=$(PWD) modules
clean:
make -C $(KERNEL) SUBDIRS=$(PWD) clean
Turns out that if I replace SUBDIRS=$(PWD) with M=$(PWD), it works. Now if I google explicitly for that M variable in conjunction with building kernel modules, I do find text that show it that way. But the net is also littered with examples using SUBDIRS, and it worked for me with a fairly recent kernel (4.14).
Then I did find references hinting at this being an old way of doing it, like from here:
make -C $KDIR SUBDIRS=$PWD
Same as M=. The SUBDIRS= syntax is kept for backwards compatibility.
In fact, this seems to be really old, like, kernel 2.6.7 old. Unfortunately, fairly recent tutorials show the old way.

Can we have a compiler running in embedded device

It may sound weird but I would like to know if we can have compiler in embedded device (lets say gcc support on imx6).
Of course, it is not uncommon to have target tools, but is is not trivial. A non-native (from the host perspective) compiler must be cross-compiled for the target architecture. You didn't provide any details, but maybe your build system can build target tools for you. Of course, you need much more than just a compiler. You probably need make, autotools, and probably more. It depends on what you are trying to compile on the target.
Your best bet would be to gain some proficiency using a cross-compiler environment. If you haven't already, you might check out the Yocto Project. It supports i.mx6 (and much more) and probably provides a path to get target tools on your board.
Good luck!
To arm arch, it will be easy to get target compiler, linaro ubuntu of linaro project will provide a completely solution for arm arch, it can provide GNOME desktop、toolchain and informative tools on your target.
You can get more info from the following link:
https://wiki.linaro.org/Platform/DevPlatform/Ubuntu
Yes that should easy enough.. What version of cross-compiler do you have in your machine, download the matching gcc compiler from here https://ftp.gnu.org/gnu/gcc/
Now what you want to do is cross-compile the GCC which you downloaded using the crosscompiler which you already have.
Following is an example of compiling 4.7.4, NOTE: replace the HOST and BUILD according to your platform:
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
../gcc-4.7.4/configure --build=$BUILD \
--host=$HOST \
--target=$HOST \
--prefix=/usr \
--disable-nls \
--enable-languages=c,c++ \
--with-float=hard
make -j $JOBS
make DESTDIR=<path_where_to_install> install

How do I compile and run GCC 4.9.x?

I'm running debian wheezy and wanted to upgrade from GCC 4.7.2 to GCC 4.9.0.
As per these instructions I installed libgmp-dev, libmpfr-dev and libmpc-dev (my package manager gave me versions 2:5.0.5+dfsg-2, 3.1.0-5 and 0.9-4 respectively) and ran the following to compile gcc (note that in my case it was 4.9.0 instead of 4.6.2):
tar xzf gcc-4.6.2.tar.gz
cd gcc-4.6.2
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
$PWD/../gcc-4.6.2/configure --prefix=$HOME/gcc-4.6.2
make
make install
I now have a objdir directory full of stuff, but where is g++, and where should I put this directory?
I'm guessing I should move it to usr/local and add something to my PATH variable, but I don't know what exactly, and how to make sure it is searched before my old gcc install.
After doing these commands (note the --prefix option of configure)
$PWD/../gcc-4.9.0/configure --prefix=$HOME/gcc-4.9.0
make install
the new gcc will be installed in $HOME/gcc-4.9.0 directory (there should be subdirectories like bin, lib, share inside it).
Full path to gcc will be $HOME/gcc-4.9.0/bin/gcc, and g++ (which is symlink to gcc) will be here: $HOME/gcc-4.9.0/bin/g++.
There can be no separate g++ in objdir because gcc compiler driver implements drivers for several languages; the mode (C or C++) is selected based on argv[0] (name of binary, which was used to run driver: gcc or g++; this mode also affects linking flags) and on source file extensions (gcc accepts both C and C++ programs as input for compilation into object files). So, g++ may be generated as symlink by make install, and the place to store generated symlink is $prefix/bin.
After building the GCC and installing it in the $HOME/gcc-4.9.0 directory, you can use it; but default system gcc will be not updated. Update of distributive gcc should be done via distributive tools (apt, dpkg-build, etc). Current prebuild version of system-wide gcc for Wheezy is 4.7.2, 4.8.2 for Jessie and Sid and 4.9-2 for "Experimental".

Cross Compile Linux Kernel Module

I am looking into cross compiling a kernel module for an ARM linux. I have my toolchain installed.
But there's something I am not quite getting from various how-tos.
The module I want to build is gadgetfs.
The kernel version on my host is 3.5.0-34-generic while
on the target it's 3.6.9-0.1
Now what kernel sources or headers do I actually need to download and install, and where?
I downloaded linux-3.6.9.tar.bz2 from kernel.org and extracted it.
In drivers/usb/gadget/ there's a Makefile and according to this site I need to append these lines to it, then run make:
KDIR := /lib/modules/`uname -r`/build
PWD := `pwd`
obj-m := dummy_hcd.o gadgetfs.o
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
But what do i have to replace uname -r with? Cause this would give me my host's kernel version. But my target version is different. Where is the /lib/modules/3.6.9 folder?
CROSS_COMPILE and ARCH is both set.
You need to cross compile (or download pre-compiled) matching version of Linux for your target on your host machine with right configuration since Linux doesn't have a stable binary API. Host's kernel version is not relevant.
After having target build available on your host you can build a module via
make -C kernel_build_dir M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules
under that module's directory.

cross compile opencv for porting to TI DM6446

I have set up target fs on
/home/myself/filesys/bin..etc//
GCC
compile:
host $ arm_v5t_le-gcc hello.c -o hello
run:
target $ cd /opt/hello
target $./hello
I have installed opencv2.3 on host ubuntu machine now I want opencv to be ported to DM6446
so i follow
uncompress opencv2.3 tarball
sudo cmake OpenCV-2.3.1
sudo make ARCH=arm CROSS_COMPILE=arm_v5t_le-
but when I run the sample test from bin it runs on x86 machine which was made for ARM
I think I am not following the correct procedure to make opencv.
Is there anything I have to do to make opencv for ARM architecture,
what are the steps to follow in cross compiling?
The 2nd command you executed should provide a clue as to whether you are cross-compiling or not. If you look closely it would have shown that it was building for the i686 and not for the ARM platform.
This blog discusses how to Cross Compile using cmake.
cmake uses different environment variables from standard make (so don't use ARCH, and CROSS-COMPILE).

Resources