Compiling module with external toolchain - linux

I created the make file
obj-m += hello.o
all:
make -C /home/developer/Desktop/xukr-20120201-omap3/linux-2.6.37-tn M=/home/developer/Desktop/module_test modules
clean:
make -C /home/developer/Desktop/xukr-20120201-omap3/linux-2.6.37-tn M=/home/developer/Desktop/module_test clean
Then, i found a simple hello program
#define __KERNEL__ /* We're part of the kernel */
#define MODULE /* Not a permanent part, though. */
/* Standard headers for LKMs */
#include <linux/modversions.h>
#include <linux/module.h>
#include <linux/tty.h> /* console_print() interface */
/* Initialize the LKM */
int init_module()
{
console_print("Hello, world - this is the kernel speaking\n");
/* More normal is printk(), but there's less that can go wrong with
console_print(), so let's start simple.
*/
/* If we return a non zero value, it means that
* init_module failed and the LKM can't be loaded
*/
return 0;
}
/* Cleanup - undo whatever init_module did */
void cleanup_module()
{
console_print("Short is the life of an LKM\n");
}
And i tried to compile on command line with this
make ARCH=arm CROSS_COMPILE=angstrom-linux-gnueabi-
And i get this error
/bin/sh: angstrom-linux-gnueabi-gcc: not found
What is wrong with this? i am really new at this.
Thanks in advance,

You could use remake to debug and understand your Makefile. Invoke it as remake -x -d it will give you a lot of debugging output, while behaving otherwise as GNU make.
As I commented, don't forget to use $(MAKE) instead of make inside your Makefile.
Regarding the error: angstrom-linux-gnueabi-gcc: not found you need to install the appropriate cross-compiler (and cross-linker) toolchain on your system (or perhaps set appropriately your PATH environment variable, so that it would be found).
All this won't solve your problem, but will help you understanding it

Related

Why does dynamically loading of PIEs no longer work in glibc? [duplicate]

There is a large number of questions on SO about how to execute a library or dynamically load an executable. As far as I can tell, all the answers come down to: compile your executable as position-independent code and load it with dlopen. This worked great --- and still works great on macOS --- until a recent change in glibc, which explicitly disabled dlopening PIEs. This change is now in the current version of glibc (2.30) on ArchLinux, for example, and trying to dlopen a position-independent executable gives an error: "cannot dynamically load position-independent executable".
It's difficult to guess what prompted such a radical change that breaks so much code and useful use cases. (The explanations on Patchwork and Bugzilla don't make much sense to me.) But there is now a question: what to do if you want to create an executable that's also a dynamic library, or vice versa?
A solution was linked from one of the comments. Reproducing it here for posterity:
#include <stdio.h>
#include <unistd.h>
const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-x86-64.so.2";
extern "C" {
void lib_entry(void)
{
printf("Entry point of the service library\n");
_exit(0);
}
}
Compiling with g++ -shared test-no-pie.cpp -o test-no-pie -Wl,-e,lib_entry produces a shared object (dynamic library) that can also be executed on Linux.
I have two questions:
What if I want to pass command-line arguments? How to modify this solution so it accepts arc,argv?
Are there other alternatives?
It's difficult to guess what prompted such a radical change
Not really: it never worked correctly.
that breaks so much code
That code was broken already in subtle ways. Now you get a clear indication that it will not work.
Are there other alternatives?
Don't do that?
What problem does dlopening an executable solve?
If it's a real problem, open a GLIBC bugzilla feature request, explaining that problem and requesting a supported mechanism to achieve desired result.
Update:
at least say why "it never worked correctly". Is it some triviality like potentially clashing globals between the executables, or something real?
Thread-local variables is an example that doesn't work correctly. Whether you think they are "real" or not I have no idea.
Here is the code:
// foo.c
#include <stdio.h>
__thread int var;
__attribute__((constructor))
static void init()
{
var = 42;
printf("foo.c init: %d %p\n", var, &var);
}
int bar() {
printf("foo.c bar: %d %p\n", var, &var);
return var;
}
int main()
{
printf("foo.c main: %d %p bar()=%d\n", var, &var, bar());
return 0;
}
gcc -g foo.c -o foo -Wl,-E -fpie -pie && ./foo
foo.c init: 42 0x7fb5dfd7d4fc
foo.c bar: 42 0x7fb5dfd7d4fc
foo.c main: 42 0x7fb5dfd7d4fc bar()=42
// main.c
// Error checking omitted for brevity
#include <dlfcn.h>
#include <stdio.h>
int main()
{
void *h1 = dlopen("./foo", RTLD_LOCAL|RTLD_LAZY);
int (*bar)(void) = dlsym(h1, "bar");
printf("main.c: %d\n", bar());
return 0;
}
gcc -g main.c -ldl && ./a.out
foo.c init: 42 0x7fb7305da73c
foo.c bar: 0 0x7fb7305da73c <<< what?
main.c: 0 <<< what?
This is using GNU C Library (Debian GLIBC 2.28-10) stable release version 2.28.
Bottom line: this was never designed to work, and you just happened to not step on many of the land-mines, so you thought it is working, when in fact you were exercising undefined behavior.
Please see this answer:
https://stackoverflow.com/a/68339111/14760867
The argc, argv question is not answered there, but when I found I needed one, I hacked something together to parse /proc/self/cmdline at runtime for pam_cap.so use.

How to set custom predefined macros for gcc via Linux environment to avoid passing them all the time

I have several projects in which I use many custom macros. For example,
//prog.c
#include <stdio.h>
#ifdef DBG_LEVEL_1
#define P(d) printf("%s:%d\n", #d, d);
#else
#define P(...)
#endif
#ifdef INLINE
#define INL static inline
#else
#define INL
#endif
INL void func_Sqr(int a)
{
printf("sqr(a):%d\n", a*a);
}
int main()
{
int a = 3;
P(a);
func_Sqr(a);
return 0;
}
I compile this in several ways,
gcc prog.c
gcc -DINLINE prog.c
gcc -DDBG_LEVEL_1 prog.c
gcc -DDBG_LEVEL_1 -DINLINE-DINLINE prog.c
Is there way to set these macros as enabled as default via environment variable?
We can solve this by creating a makefile where these macros are set. But I want to know if there any Linux environment related solution
Is there way to set these macros as enabled as default via environment variable?
Generally, no there is not. Gcc arguments are not affected by environment variables (except maybe DEPENDENCIES_OUTPUT..).
I advise to write a small wrapper function around the command, for example a bash function:
wgcc() {
gcc "${GCCARGS[#]}" "$#"
}
and then doing:
GCCARGS+=(-DA=1 -DB=2)
wgcc something.c
is trivial to do, easy to understand and maintain and communicate with other team members, easy to implement and share. Suprising haisenbugs will be easy to track - wgcc is unique name different then gcc. Still you could overwrite the original command with gcc() { command gcc "${GCCARGS[#]}" "$#"; } or by creating a /usr/local/bin/gcc file, making it a bit more confusing.
But! You can and I woult strongly advise not to do that, because it will be confusing to others and hard to maintain. You can use COMPILER_PATH environment variable to overwrite compiler tools and provide custom options. In steps:
Create a temporary directory
In that directory link all the subprograms of gcc to it's normal prefix, except the tools the behavior you want to modify, like cc1.
Then create cc1 as a script with that will call the original cc1 but will use some environment variable to pass extra arguments.
Then export the path as COMPILER_PATH so gcc will pick it up.
On my archlinux with gcc10.0.1 I did:
mkdir /tmp/temp
cd /tmp/temp
for i in /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/{cc1plus,collect2,lto-wrapper,lto1}; do ln -vs "$i"; done
printf "%s\n" '#!/bin/sh' '/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/cc1 $GCCARGS "$#"' > cc1
chmod +x cc1
export COMPILER_PATH=/tmp/temp
After that you can:
export GCCARGS=-DA=1
gcc -xc - <<<'int main() { printf("A=%d\n", A); }'
./a.out
> A=1

Loading executable or executing a library

There is a large number of questions on SO about how to execute a library or dynamically load an executable. As far as I can tell, all the answers come down to: compile your executable as position-independent code and load it with dlopen. This worked great --- and still works great on macOS --- until a recent change in glibc, which explicitly disabled dlopening PIEs. This change is now in the current version of glibc (2.30) on ArchLinux, for example, and trying to dlopen a position-independent executable gives an error: "cannot dynamically load position-independent executable".
It's difficult to guess what prompted such a radical change that breaks so much code and useful use cases. (The explanations on Patchwork and Bugzilla don't make much sense to me.) But there is now a question: what to do if you want to create an executable that's also a dynamic library, or vice versa?
A solution was linked from one of the comments. Reproducing it here for posterity:
#include <stdio.h>
#include <unistd.h>
const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-x86-64.so.2";
extern "C" {
void lib_entry(void)
{
printf("Entry point of the service library\n");
_exit(0);
}
}
Compiling with g++ -shared test-no-pie.cpp -o test-no-pie -Wl,-e,lib_entry produces a shared object (dynamic library) that can also be executed on Linux.
I have two questions:
What if I want to pass command-line arguments? How to modify this solution so it accepts arc,argv?
Are there other alternatives?
It's difficult to guess what prompted such a radical change
Not really: it never worked correctly.
that breaks so much code
That code was broken already in subtle ways. Now you get a clear indication that it will not work.
Are there other alternatives?
Don't do that?
What problem does dlopening an executable solve?
If it's a real problem, open a GLIBC bugzilla feature request, explaining that problem and requesting a supported mechanism to achieve desired result.
Update:
at least say why "it never worked correctly". Is it some triviality like potentially clashing globals between the executables, or something real?
Thread-local variables is an example that doesn't work correctly. Whether you think they are "real" or not I have no idea.
Here is the code:
// foo.c
#include <stdio.h>
__thread int var;
__attribute__((constructor))
static void init()
{
var = 42;
printf("foo.c init: %d %p\n", var, &var);
}
int bar() {
printf("foo.c bar: %d %p\n", var, &var);
return var;
}
int main()
{
printf("foo.c main: %d %p bar()=%d\n", var, &var, bar());
return 0;
}
gcc -g foo.c -o foo -Wl,-E -fpie -pie && ./foo
foo.c init: 42 0x7fb5dfd7d4fc
foo.c bar: 42 0x7fb5dfd7d4fc
foo.c main: 42 0x7fb5dfd7d4fc bar()=42
// main.c
// Error checking omitted for brevity
#include <dlfcn.h>
#include <stdio.h>
int main()
{
void *h1 = dlopen("./foo", RTLD_LOCAL|RTLD_LAZY);
int (*bar)(void) = dlsym(h1, "bar");
printf("main.c: %d\n", bar());
return 0;
}
gcc -g main.c -ldl && ./a.out
foo.c init: 42 0x7fb7305da73c
foo.c bar: 0 0x7fb7305da73c <<< what?
main.c: 0 <<< what?
This is using GNU C Library (Debian GLIBC 2.28-10) stable release version 2.28.
Bottom line: this was never designed to work, and you just happened to not step on many of the land-mines, so you thought it is working, when in fact you were exercising undefined behavior.
Please see this answer:
https://stackoverflow.com/a/68339111/14760867
The argc, argv question is not answered there, but when I found I needed one, I hacked something together to parse /proc/self/cmdline at runtime for pam_cap.so use.

How to stop vim from creating log files

Every time I open vim, it generates various log files.
bt_regexp_debug.log
bt_regexp_log.log
nfa_regexp_debug.log
nfa_regexp_dump.log
nfa_regexp_run.log
Why do they get created, and how can I get read of them?
From regexp_nfa.c:
#ifdef ENABLE_LOG
log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
[...]
#ifdef ENABLE_LOG
{
FILE *f = fopen(NFA_REGEXP_RUN_LOG, "a");
and from regexp.c:
#ifdef BT_REGEXP_LOG
f = fopen("bt_regexp_log.log", "a");
All the calls to this seem to be wrapped in either a #ifdef ENABLE_LOG or #ifdef BT_REGEXP_LOG. On other words: they're compile-time switches.
Looking at the top of these two files, I see:
#ifdef DEBUG
# define NFA_REGEXP_ERROR_LOG "nfa_regexp_error.log"
and:
#ifdef DEBUG
/* show/save debugging data when BT engine is used */
# define BT_REGEXP_DUMP
Conclusion: Your Vim is compiled with DEBUG defined.
You can verify this with vim --version, where it should show DEBUG BUILD at the bottom. I don't see any way to disable creating these files at runtime; you'll need to recompile Vim.
There doesn't seem to be a configure switch to enable/disable this. It should be disabled by default. In feature.h I see:
/*
* DEBUG Output a lot of debugging garbage.
*/
/* #define DEBUG */
And in Makefile I see:
#CFLAGS = -g -DDEBUG -Wall -Wshadow -Wmissing-prototypes
Note that both are commented out.
It's also possible you manually ran make with make CFLAGS="-DDEBUG".
P.S. I didn't know any of this either, but quickly found the answer by using grep on the Vim source tree. Learn to love grep. grep is your friend. ;-)

Can't compile kernel module for BeagleBone Debian

I'm following Derek Molloys guide to building loadable kernel modules, but get stuct at some points.
I have the kernel code in a .c-file:
hello.c
#include <linux/init.h> // Macros used to mark up functions e.g., __init __exit
#include <linux/module.h> // Core header for loading LKMs into the kernel
#include <linux/kernel.h> // Contains types, macros, functions for the kernel
MODULE_LICENSE("GPL"); ///< The license type -- this affects runtime behavior
MODULE_AUTHOR("Derek Molloy"); ///< The author -- visible when you use modinfo
MODULE_DESCRIPTION("A simple Linux driver for the BBB."); ///< The description -- see modinfo
MODULE_VERSION("0.1"); ///< The version of the module
static char *name = "world"; ///< An example LKM argument -- default value is "world"
module_param(name, charp, S_IRUGO); ///< Param desc. charp = char ptr, S_IRUGO can be read/not changed
MODULE_PARM_DESC(name, "The name to display in /var/log/kern.log"); ///< parameter description
/** #brief The LKM initialization function
* The static keyword restricts the visibility of the function to within this C file. The __init
* macro means that for a built-in driver (not a LKM) the function is only used at initialization
* time and that it can be discarded and its memory freed up after that point.
* #return returns 0 if successful
*/
static int __init helloBBB_init(void){
printk(KERN_INFO "EBB: Hello %s from the BBB LKM!\n", name);
return 0;
}
/** #brief The LKM cleanup function
* Similar to the initialization function, it is static. The __exit macro notifies that if this
* code is used for a built-in driver (not a LKM) that this function is not required.
*/
static void __exit helloBBB_exit(void){
printk(KERN_INFO "EBB: Goodbye %s from the BBB LKM!\n", name);
}
/** #brief A module must use the module_init() module_exit() macros from linux/init.h, which
* identify the initialization function at insertion time and the cleanup function (as
* listed above)
*/
module_init(helloBBB_init);
module_exit(helloBBB_exit);
and the makefile as this:
Makefile
obj-m+=hello.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
when I try to run make in a directory with onl the two above files, i get
Make: Nothing to be done for all
I'm running 3.8.13-bone47, but I wasn't able to find the exact header files matching on this link that Derek recommended, so I downloaded 3.8.13-bone71 instead. Could that be the problem? Do I have to download the headers, when I'm compiling in directly on the BeagleBone? I have also tried change the lines in the Makefile to a hardcoded distribution name that matches mine (3.8.13-bone47), doesn't work either.
Thank you very much guys!
I solved my question. I had two problems:
Missing Tabs in Makefile
I added a tab to the beginning of each line with a make statement. It has to be an actually tab, the <\t> didn't work for me.
Wrong Header files
It turns out that the proper version of the header files is quite important :) I got the ones from http://rcn-ee.net/deb/trusty-armhf/v3.8.13-bone47/ and added the mach/timex.h file, and was the able to follow Derek's guide from then on.

Resources