Booting custom kernel on xeon-phi - gcc

I am trying to boot a custom kernel on Xeon-phi instead of the default Linux kernel. At this link, I found a way to cross compile my kernel which compiles successfully using k1om-mpss-linux-gcc cross compiler. Is cross compiling enough ? I get the error
mykernel.img is not a k1om Linux bzImage
Edit:
So, I used /usr/linux-k1om-4.7/bin/x86_64-k1om-linux-gcc compiler to compile a simple helloworld.c program and the kernel source. I get two different types of results for objdump -f on the executables.
for helloworld.c:
hello: file format elf64-k1om
architecture: k1om, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000400400
for mykernel:
mykernel: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0010000c
I compiled using the same compiler, yet they show different architectures. What is the reason for this ?

The first thing to do is figure out what mykernel.img is. Try running file on it.
$ file /opt/mpss/3.4/sysroots/k1om-mpss-linux/boot/vmlinux-2.6.38.8+mpss3.4
/opt/mpss/3.4/sysroots/k1om-mpss-linux/boot/vmlinux-2.6.38.8+mpss3.4: ELF 64-bit LSB executable, version 1 (SYSV), statically linked, BuildID[sha1]=0xa4c16ee85c11aca4e78dc4ae46d3827fb74289c1, not stripped
$ objdump -f /opt/mpss/3.4/sysroots/k1om-mpss-linux/boot/vmlinux-2.6.38.8+mpss3.4
/opt/mpss/3.4/sysroots/k1om-mpss-linux/boot/vmlinux-2.6.38.8+mpss3.4: file format elf64-k1om
architecture: k1om, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000001000000

The answer to your original question - no, unfortunately, it is not as simple as just cross-compiling. There were a number of changes made to the kernel that comes with the MPSS. I don't know all the changes but a big one that I do know is that they had to add support for the larger register set on the coprocessor in order to be able to save state on a context switch.
As to why the file format is elf32-i386 instead of elf32-k1om -
The web site you referenced referred to recompiling the kernel that came with the MPSS after possibly make a few changes in the files. You'll notice that they also copied over a configuration file for the installed version of the kernel. So they had all the files to remake the kernel exactly as it had been made.
I suspect that, in your case, either a) there was a configuration script of some sort in your source directory that picked up the architecture you were running on and caused confusion when the makefile ran or b) your makefile had no idea what k1om was. In either case, it fell back to what it believed to the the lowest common denominator i386. As I say, this is just a suspicion on my part but a careful reading of your makefiles should lead to the answer.

Related

GCC error with -mcpu32 flag, CPU32 compiler needed

I am patching code into my car's ECU. This has a Motorola MC68376 processor, so I'm using the appropriate CPU32 instruction set.
I want to continue to write in assembly code so that I can explicitly manage control registers, RAM access and allocation, as well as copying code structures which are already in use.
My first patch was successfully compiled in EASy68k, but that program does not support the full instruction set for the CPU32. For example, the DIVS.L command is not supported, so I cannot take a quotient of a 32-bit value.
Thus, before writing my own compiler out of sheer incompetence with available tools, I'm looking for an easier path. I read that gcc has the capability to compile code for the CPU32, but I have failed to get it to work.
I'm using MinGW's gcc (6.3.0) and Eclipse (2020-03). I added the '-mcpu32' or '-march=cpu32' flags to the compiler call, according to:
https://gcc.gnu.org/onlinedocs/gcc/M680x0-Options.html
Unfortunately this returns an error:
gcc: error: unrecognized command line option '-mcpu32'; did you mean '-mcpu='?
or
error: bad value (cpu32) for -march= switch
May I please have some advice for making this work? Does anyone know of a better CPU32 compiler that works with Eclipse?
I did not understand that gcc is conventionally distributed as binary files that are compiled with different functionality to suit the needs of a given user.
There seem to be two paths forward:
1) compile my own cross-compiler version of GCC
2) download a pre-compiled cross-compiler version of GCC
I chose to follow route 2).
I began the process of installing the 'Windows Subsystem for Linux' and Ubuntu 20.04 Focal Fossa, because I found a pre-made compiler that should be capable of performing cross compilation for the m68k processor: "gobjc-10-m68k-linux-gnu"
https://ubuntu.pkgs.org/20.04/ubuntu-universe-i386/gobjc-10-m68k-linux-gnu_10-20200411-0ubuntu1cross1_i386.deb.html
While I was installing that, I also found an m68k-elf gcc toolchain that is pre-compiled for windows 10:
https://gnutoolchains.com/m68k-elf/
I played with the latter for much of today. Although I was unable to get the toolchain integrated well with Eclipse, it works from the command line to compile a *.s assembly code file. This includes compatibility with the '-mcpu32' flag that I wanted at the outset.
There is still a lot for me to figure out, even after floundering through learning gcc's assembler directives (https://www.eecs.umich.edu/courses/eecs373/readings/Assembler.pdf) and the differences in gcc's assembly syntax compared to the MC68k reference manual (https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf).
I can even convert the code section of the output file to be a proper s-record by using objcopy with the '-O srec' and '--only-section=.text' flags. This helps me patch the code into my ECU.
Thus I've answered my original question.

Cross Compilation kernel and kernel modules problems

I've been spending the last week trying to reach one objective that i still haven't reached.
My final goal would be to cross-compile for some architectures (in this question i will take as an example only one which is MIPSLE) a couple of kernel modules that i'd like to use on my home router, by loading them at runtime with INSMOD.
My router is missing of some iptables functionalities and that's why during the kernel compilation, who compiled it decided to get rid of them.
The current kernel version is quite obsolete: Linux version 2.6.36+ by doing /proc/version
I read a lot of documentations and still i'm not sure if it possible to compile just some modules or if it's necessary to compile the whole kernel everytime (some people said that for some modules is possible and for others with more dependencies is not, is that true ?).
In this case the kernel modules i need are located in /net/ipv4/netfilter/
Since i didn't get how to compile just kernel modules in a standalone way, i decided to cross-compile the entire kernel and take the modules i needed.
So i've downloaded the proper toolchain (uclibc mipsle toolchain) and i was successfull in compiling a simple working hello world that i've executed on my router where i have an ssh shell.
So i'm sure that the toolchain i'm using it's the correct one.
Now, since i wanted to test with a recent version of kernel i've downloaded the latest ubuntu 20 with correspective kernel and i've successfully compiled it and the kernel modules that i was speaking about before, were there inside the netfilter folder in .ko format , PERFECT !
I clearly used the /boot/config_file of my host machine as .config
So, after I've downloaded the exact same kernel version that my router has (2.6.36) and I've tried to compile it with a .config file that i've found on GitHub related to a mipsle device with my same kernel version.
Here i think we have the first problem, I tried to find the .config of my device in order to have a smooth configuration but i don't have the /boot folder and in also was not in /proc.
How can i get it?
Anyway, I've used it and the compilation didn't look like failed, but these are the last lines:
CC drivers/usb/storage/usual-tables.o
LD drivers/usb/storage/usb-storage.o
LD drivers/usb/storage/built-in.o
LD drivers/usb/built-in.o
LD drivers/video/built-in.o
LD drivers/built-in.o
LD vmlinux.o
MODPOST vmlinux.o
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
KSYM .tmp_kallsyms1.S
AS .tmp_kallsyms1.o
LD .tmp_vmlinux2
KSYM .tmp_kallsyms2.S
AS .tmp_kallsyms2.o
LD vmlinux
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/mips/boot/vmlinux.bin
Building modules, stage 2.
MODPOST 1 modules
CC drivers/scsi/scsi_wait_scan.mod.o
LD [M] drivers/scsi/scsi_wait_scan.ko
It says "1 Modules" but I don't understand why and inside the /net/ipv4/netfilter folder now I have .o files instead of .ko like if they've not been linked.
Since i was getting mad and I didn't know what to try more after several attempts, I've decided to use the config file of my host machine (ubuntu 2020, kernel 5.4.0.26) and the compilation was successful, with .ko files inside the folder.
The problem was that obviously they were modules compiled for x86-64 instead of MIPS and other clear "problems" related to the configuration of my x86-64 machine.
So, what i think now is that the .config I've found could be broken somehow, I also tried to disable, by adding a comment, that SCSI module, but nothing, I always get the same stuff.
And obviously between each try I always did a make distclean and make clean.
What do you suggest me to do? I won't even post all the references i've read about this stuff because i could sigsegv StackOverflow's server with that amount of data.
Thanks to everyone and sorry for the wall-post.
i'm not sure if it possible to compile just some modules or if it's necessary to compile the whole kernel every time
Well, you can compile just single modules, but compiling a module requires the kernel to be already built. Once you do that one time though, you should be able to compile other modules singularly. That is, of course, if you do not wish to embed them in the kernel itself (CONFIG_XXX=y instead of CONFIG_XXX=m). You should be able to compile only the module you want like this (assuming /path/to/linux is the directory where your already built kernel source resides):
$ cd /path/to/linux
$ cd path/to/module/folder
$ make -C /path/to/linux M=$(pwd) modules
I tried to find the .config of my device in order to have a smooth configuration but i don't have the /boot folder and it also was not in /proc. How can i get it?
Where did you look precisely? The presence of /proc/config.gz depends on CONFIG_IKCONFIG_PROC (see also here). If you cannot find the file then it's most likely because that configuration option was disabled when the kernel was built. You may try look under /boot (as you already did), or under /lib/modules/$(uname -r)/build/.config, but unfortunately there's not much else to do otherwise.
I've seen people suggest trying to run modprobe configs and then check /proc/config.gz, but that seems strange since as far as I know the kernel config shouldn't be configurable to be available as a loadable module.
What do you suggest me to do?
Well, the most important thing you want right now is to find the configuration file for your router (or a compatible one). If you cannot find that, it will be pretty hard to get everything right. You might want to search for OpenWRT versions available for your router (if any), or really anywhere else on the internet as long as you can find a suitable configuration. Include your router brand and/or model in your searches. StackOverflow can't really help you that much about this though.
You can try cross-compiling a 5.4 kernel with default config plus the module you want. For example, assuming you have the right cross-compilation toolchain ready:
cd /path/to/linux
make ARCH=mips CROSS_COMPILE=your-cross-toolchain-prefix- defconfig
make ARCH=mips CROSS_COMPILE=your-cross-toolchain-prefix- menuconfig
# ... enable the module, tune the config ...
make -j ARCH=mips CROSS_COMPILE=your-cross-toolchain-prefix-
In any case, consider the fact that jumping from a 2.6 to a 5.4 kernel is a pretty big change, and it's likely to end up breaking everything, so be sure to make a backup of your router's firmware before trying anything.

Cross-compiling for a specific platform -- linking libc

I have to compile a simple binary for a very old Linux system. I have no gcc/build libs available on the target machine but I do have access to the machine.
I am having trouble compiling the code on my machine and having it execute on target machine.
I am copying libc.so to my local machine and trying to compile and link the program so that it will execute on the target machine.
I have copied the libc from the target machine to mine and tried compiling it with my target executable.
this has gotten closes to a successful execution:
gcc -nostdlib ./libc-[version].so myFile.c -emain -o outfile.out
upon execution a very simple PoC test program runs, and then seg faults upon exit. the actual program simply seg faults.
It seems I have somewhat of a lack of understanding of linking. Any help?
It seems I have somewhat of a lack of understanding of linking.
You do. A "normal" user-level program doesn't start executing at main, it starts at _start.
The _start symbol typically comes from crt0.o file (part of libc), and knows how to "interface" between the way the kernel supplies arguments, and the way main expects to find them. It also initializes various data that must be initialized before main runs (e.g. stdio streams).
What you want to do then is:
Find out the actual link command that gcc main.o performs. You can do so by adding the -v flag.
Replicate such command, providing crt0.o and other input files, appropriate for your version of target libc.
It might be easier to spin up a VM with the OS matching your target (and with old tools that target it), and build your program inside of that VM.
Otherwise you'll likely have to set up a full cross-compiler environment (which includes libc and all other libraries you need). This is not a trivial proposition, and is certainly not accomplished by copying libc.so from the target machine. But it is well-documented and is certainly doable (with some skill).

How to properly make a object file from header file (using an I2C board with a debian linux machine)

I have some source files that previously have been compiled for X86 architecture. Now I need to compile them for ARM architecture. When I try to use something like
g++ -c -x c++ foo.h
gcc -c -x c foo.h
it only gives me few instructions. I believe it doesn't link my header file to other included files. I only get "Disassembly of section .comment:".
Please note it does prompt me for other files, for example if foo includes foo1.h and foo2.h, if I don't include foo1 and foo2 headers in the same directory the compiler doesn't work.
Another thing which I don't understand is that both gcc and g++ produce the same assembly code, maybe because they only generate the comment section they look the same.
A little bit more details about my problem:
I'm using a USB-I2C converter board. The board provides only support for x86/x64 architecture. I managed to access the source file and to get the driver setup. Now I need to test everything together. In order to do so I need to be able to compile a sample code. When I want to do so, it calls on static libraries that need to be in .a extension. I need to create my own library.a file. In order to do so, I have found the source c files (.h header). Now I need to link them together during compilation and make object files, and eventually archive them together in a .a file.
Thank you for your help.
Edit (update):
A quick summary of what I have achieved so far:
- I was able to find a driver from a github repo.
- I was able to make the module
- I also compiled a new fresh kernel from a raspbian source code (I'm doing this for a Raspberry PI3):
uname -a
Linux raspberrypi 4.9.35-v7+ #1 SMP Tue Jul 4 22:40:25 BST 2017 armv7l GNU/Linux
I was able to load the module properly:
lsmod
Module Size Used by
spi_diolan_u2c 3247 0
i2c_diolan_u2c 3373 0
diolan_u2c_core 4268 2 i2c_diolan_u2c,spi_diolan_u2c
lsusb
Bus 001 Device 010: ID a257:2014
dmesg
[ 126.758990] i2c_diolan_u2c: loading out-of-tree module taints kernel.
[ 126.759241] i2c_diolan_u2c: Unknown symbol diolan_u2c_transfer (err 0)
[ 130.651475] i2c_diolan_u2c: Unknown symbol diolan_u2c_transfer (err 0)
[ 154.671532] usbcore: registered new interface driver diolan-u2c-core
[ 5915.799739] usb 1-1.2: USB disconnect, device number 4
[10591.295014] usb 1-1.2: new full-speed USB device number 6 using dwc_otg
[10591.425984] usb 1-1.2: New USB device found, idVendor=a257, idProduct=2014
[10591.425997] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[10591.426005] usb 1-1.2: Product: Diolan DLN1
[10591.426012] usb 1-1.2: Manufacturer: Diolan
What I'm not sure:
If the kernel space is properly mapped to physical hardware (if the loaded module can get ahold of my diolan-board)!!!
progress: based on my research, I think a hot-plug protocol would take care of that, but not sure!
confusion: why the lsusb still only shows the device ID. I know the manufacturer and kernel driver can determine what info to be shown, but only showing ID doesn't seem right to me
What I want to do now:
I would like to write a simple c source or python code to interact with my device. Basically I don't know how I can make connection between user space and kernel space. The manufacturer has provided some source code examples, libraries, etc. . However, I have given up on using them because they are for another architecture , based on qt, and I find it near impossible to find replacement for libraries they use in their static libraries ( I figured those libraries by restoring their .a archived file provided for x86)
I just need to know exactly what the next step should be for me to move on towards getting the board working with the PI.
Thank you :)
You don't make any object file from a header file. On Linux object files (and executables) are ELF files. Use file(1) (or objdump(1) ...) to check.
Instead, a header file should be included (by #include preprocessor directive) in some *.cc file (technically a translation unit).
(You could precompile headers, but this is only useful to improve compilation time, which it does not always, and is an advanced and GCC specific usage; see this)
You do compile a C++ source file (some *.cc file) into an object file suffixed .o (or a C source file *.c compiled into an object file suffixed .o)
Read more about the preprocessor, and do spend several days reading about C or C++ (which are different programming languages). Read also more about compiling and linking.
I recommend to compile your C++ code with g++ -Wall -Wextra -g to get all warnings (with -Wall -Wextra ) and debug information (with -g).
A minimal compilation command to compile some yourfile.cc in C++ into an object file yourfile.o should probably be
g++ -c -Wall -Wextra -g yourfile.cc
(you could remove -Wall -Wextra -g but I strongly recommend to keep them)
You may need to add other arguments to g++. They order matters a lot. Read the chapter about Invoking GCC
Notice that yourfile.cc contains very likely some (and often several) #include directives (usually near its start)
You very rarely need the -x c++ option to g++ (or -x c with gcc). I used it only once in my lifetime. In your case it surely is a mistake.
Very often, you use some build automation tool like GNU make. So you just use make to compile (but you need to write a Makefile - where tabs are significant)
Notice that some libraries can be header only (but this is not very usual), then you don't build any shared or static ELF libraries from them, but you just include headers in your own C or C++ code.
addenda
Regarding your http://dlnware.com/sites/dlnware.com/files/downloads/linux_setup.2.0.0.zip package (which indeed is poorly documented), you should look at the several examples given in the linux_setup/examples/ directory. Such code all have a #include "../common/dln_generic.h" (for instance, 4th line of examples/leds_gui/main.cpp) which itself have other includes. All the examples are Qt applications and provide a *.pro file for qmake (which itself generates a Makefile for make from that .pro file). And passing -x c++ to g++ is rightly not mentioned at all.
You don't compile header files, you compile the C files that include them.
All code in a header file should be declarations and type definitions, which give information to the compiler, but don't actually produce any machine code. That's why there's nothing in your object files.

seg fault when running arm-elf-gcc compiled code

Using MacPorts i have just installed arm-elf-gcc on to my MacBook Pro. This worked flawlessly and all seems to run fine.
However, after compiling a simple hello world test program in C and C++ and trying to run either on the target board (an ARM9 based board running Debian Linux) they immediately seg fault.
I'm a bit stuck as how to go about debugging this, as the target board has limited tools available and no gdb. I have successfully built and run other code using a Linux hosted cross compiler so it should work.
Any ideas?
Following the suggestion I have built and run gdbserver, I get the following in gdb on the host:
Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
I thought it may be a problem with the standard c libs so I removed any calls and have just an empty main that return 0, it is compiled with -Wall -g hello-arm.cpp -static. As a test I compiled the same source with a Linux hosted cross compiler and it runs and exits fine. The only difference I can see is the that Linux compiled version is over twice the size and the difference in output from the file command:
arm-elf-gcc: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped
arm-*-linux: ELF 32-bit LSB executable, ARM, version 1, statically linked, for GNU/Linux 2.4.18, not stripped
The usual method of debugging in this situation is to run gdbserver on the target board, and connect to it (via ethernet) with gdb running on a host computer.
Alternately, you could try comparing the assembly in a Mac-compiled "Hello World" program and a (working) Linux-compiled one to see what's different.
After digging around for a couple of days I am starting to understand a bit more about embedded compilers. I wasn't really sure of the difference between arm-elf-gcc installed via MacPorts and the arm-unknown-linux toolchain I had installed on my Linux box. I just came across a pdf titled "An introduction to the GNU compiler" which contains the following paragraph:
Important: Using the GNU Compiler to
create your executable is not quite
the same as using the GNU Linker,
arm-elf-ld, yourself. The reason is
that the GNU Compiler automatically
links a number of standard system
libraries into your executable. These
libraries allow your program to
interact with an operating system, to
use the standard C library functions,
to use certain language features and
operations (such as division), and so
on. If you wish to see exactly which
libraries are being linked into the
executable, you should pass the
verbose flag
-v to the compiler.
This has important implications for
embedded systems! Such systems do not
usually have an operating system.
This means that linking in the system
libraries is almost always
meaningless: if there is no operating
system, for example, then calling the
standard printf function does not make
much sense.
So when I get back to my dev machine later I will determine the libraries linked in with the Linux build and add them to the arm-elf-gcc build.
I'll update this when I have more information but I just want to document my findings in case any one else has these problems.

Resources