How do struct module works in kernel - linux-kernel

I have written a interrupt driver linux version 3.8 for learning. I am using some gpio apis such as
gpio_request(gpioButton, "mypreciousss"); // Set up the gpioButton
When I saw inside this gpio_request it is using
if (!try_module_get(chip->owner))
here chip->owner is a struct module type variable.
gpio_request was the first function in my init function, and I did nothing to create struct module.
So how try_module_get can use one?

Here I am pasting the code snippet from function gpio_request() (linux 3.8)
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip == NULL)
goto done;
if (!try_module_get(chip->owner))
goto done;
Here, they are taking descriptor corresponding to passed GPIO, and that descriptor structure is used for further updates.

Related

How to print source file name with dladdr() function?

I was trying to print a backtrace using dladdr(). info.dli_fname in the following code snippet is displaying the file name of an ELF file. Could you please tell me if it is possible to resolve and print the name of the source file and line number programmatically without the help of addr2line or gdb?
Code:
void print_caller(void)
{
int rc = -1;
Dl_info info = {0};
void *pc = __builtin_return_address(0);
rc = dladdr(pc, &info);
printf(" ==> %p: %s (in %s)\n", pc, info.dli_sname, info.dli_fname);
}
Output:
$ ./a.out
==> 0x55a6b04a1589: foo2 (in ./a.out)
tell me if it is possible to resolve and print the name of the source file and line number programmatically
It is definitely possible -- addr2line and gdb do that.
But it is very non-trivial -- it requires understanding and decoding (possibly multiple) complicated debugging info formats.
If you only care about a single platform (looks like Linux), things are a bit easier -- you only need to decode DWARF.
But that format is still pretty complicated. You should start with a helper library, such as libdwarf.

Autoconf: check struct member type

I am new to autoconf so I would ask you how could I check if a struct member is declared with a particular type.
For example I should check if struct posix_acl.a_refcount is declared as refcount_t and not atomic_t.
I know AC functions as ac_fn_c_check_decl and ac_fn_c_check_member, but none that accomplish this task.
Thank you!
Disclaimer: As there are no other answers at the time this answer is being written, this represents my best attempt to provide a solution, but you may need to adjust things to make it work for you. Caveat emptor.
You would need to use the AC_COMPILE_IFELSE macro with code that uses atomic_t, and if the compilation succeeds, then you're using atomic_t. As future-proofing, you might also add a test for refcount_t if the atomic_t test fails.
Example:
# _POSIX_ACL_REFCOUNT_T(type-to-check)
# ------------------------------------
# Checks whether the Linux kernel's `struct posix_acl'
# type uses `type-to-check' for its `a_refcount' member.
# Sets the shell variable `posix_acl_refcount_type' to
# `type-to-check' if that type is used, else the shell
# variable remains unset.
m4_define([_POSIX_ACL_REFCOUNT_T], [
AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING([whether struct posix_acl uses $1 for refcounts])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
[#include <uapi/../linux/posix_acl.h>
struct posix_acl acl;
$1 v = acl.a_refcount;]
)],
[AC_MSG_RESULT([yes])
AS_VAR_SET([posix_acl_refcount_type], [$1])],
[AC_MSG_RESULT([no])
)
])
_POSIX_ACL_REFCOUNT_T([atomic_t])
# If posix_acl_refcount_type isn't set, see if it works with refcount_t.
AS_VAR_SET_IF([posix_acl_refcount_type],
[],
[_POSIX_ACL_REFCOUNT_T([refcount_t])]
)
dnl
dnl Add future AS_VAR_SET_IF tests as shown above for the refcount type
dnl before the AS_VAR_SET_IF below, if necessary.
dnl
AS_VAR_SET_IF([posix_acl_refcount_type],
[],
[AC_MSG_FAILURE([struct posix_acl uses an unrecognized type for refcounts])]
)
AC_DEFINE([POSIX_ACL_REFCOUNT_T], [$posix_acl_refcount_type],
[The type used for the a_refcount member of the Linux kernel's posix_acl struct.])
The tests assume that you already have a variable containing the kernel source directory, and the kernel source's include directory is specified in CPPFLAGS or CFLAGS prior to attempting the tests. You can add more tests at the position indicated, and if the resulting posix_acl_refcount_type shell variable is still not defined after all those tests, then the final AS_VAR_SET_IF invocation will invoke AC_MSG_FAILURE to stop configure with the specified error message.
Note that I used <uapi/../linux/posix_acl.h> to specifically target the kernel's linux/posix_acl.h header rather than the userspace API uapi/linux/posix_acl.h header installed in a system's include directory with the uapi/ stripped off, which may result in the compile tests above failing due to the missing struct posix_acl in the userspace API. This may not work the way I'd expect and may need modification.

dyld_insert_libraries ignored when calling application through bash

For my application, I am using DYLD_INSERT_LIBRARIES to switch libraries. I am running Mac OS X, El Capitan.
If I set these environment variables in my shell:
export PYTHONHOME=${HOME}/anaconda
export DYLD_INSERT_LIBRARIES=${HOME}/anaconda/lib/libpython2.7.dylib:${HOME}/anaconda/lib/libmkl_rt.dylib
If I launch my application directly, it works properly. However, if I call it through a bash script I have written, the DYLD_INSERT_LIBRARIES is ignored.
If I add the same 2 lines to my bash script, my application works again.
It looks like DYLD_INSERT_LIBRARIES is being unset when the bash script is called, as proven by this test script.
#!/bin/bash
set -e
echo ${DYLD_INSERT_LIBRARIES}
Is there any way to let the bash script inherit and pass down DYLD_INSERT_LIBRARIES?
This is a security feature of recent macOS versions.
The system bash executable has been marked as "restricted", disabling the DYLD_* features. To work around this, you can make a copy of bash and use that instead.
By looking for the following details in the implementations of dyld, I see that this restriction goes back at least to 10.6.
In the macOS 10.13 dyld implementation this logic is in pruneEnvironmentVariables, with the comment:
// For security, setuid programs ignore DYLD_* environment variables.
// Additionally, the DYLD_* enviroment variables are removed
// from the environment, so that any child processes don't see them.
However the actual logic to set the restriction is in configureProcessRestrictions:
// any processes with setuid or setgid bit set or with __RESTRICT segment is restricted
if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) {
gLinkContext.processIsRestricted = true;
}
...
if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
// On OS X CS_RESTRICT means the program was signed with entitlements
if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) {
gLinkContext.processIsRestricted = true;
}
// Library Validation loosens searching but requires everything to be code signed
if ( flags & CS_REQUIRE_LV ) {
gLinkContext.processIsRestricted = false;
...
As you can see, it depends on, issetugid, hasRestrictedSegment, and the CS_RESTRICT / SIP entitlements. You might be able to test for restricted status directly, or you could probably construct a function to test for these conditions yourself based on this information.

Setting kernel tunable parameter

As I wanted to introduce new kernel module parameter say new_param=1 /0 ,then after that parameter has to be checked inside kernel code as
if (new_param==1)
do some work.....
else
do other...
In this way I wanted to check by introducing new kernel module parameter.Can anyone please help me? What are the steps I need to follow to do this ?
One way to use a custom kernel parameter is to add it to the kernel command line and parse it out of /proc/cmdline, i.e.:
Add the parameter to the kernel command line
BOOT_IMAGE=<image> root=<root> ro quiet splash vt.handoff=7 your_parameter=<value>
When you boot, you will be able to access this parameter by parsing the contents of /proc/cmdline:
$ cat /proc/cmdline
BOOT_IMAGE=<image> root=<root> ro quiet splash vt.handoff=7 your_parameter=<value>
I believe a solution more tailored to your needs would include using __setup(), which is mentioned (but not explained well) in /Documentation/kernel-parameters.txt.
There are quite a few examples in the kernel source. One of such would be in /drivers/block/brd.c:
#ifndef MODULE
/* Legacy boot options - nonmodular */
static int __init ramdisk_size(char *str)
{
rd_size = simple_strtol(str, NULL, 0);
return 1;
}
__setup("ramdisk_size=", ramdisk_size);
#endif
Following this example, you could add your __init and __setup() in the relevant source file. For parsing integers from an option string in your __init function, see get_option() in /lib/cmdline.c
Update
For modules, you should use module_param(), which takes three arguments: variable name, variable type, sysfs permissions. More on the class is found at /linux/moduleparam.h.
In the module that you want to be able to pass parameters to, first declare the parameters as globals. An example usage would include the following in the module source:
int foo = 200;
module_param(foo, int, 0);
Recompile the module and you will see that you can load it via modprobe <module-name> foo=40.

Julia: Having a function f() containing the macro #printf, how can I access the output outside f()?

In the Julia NMF package a verbose option provides information on convergence using the #printf macro.
How can I access this output without rewriting the NMF package io?
To rephrase, having a function f() containing the macro #printf, how can I access the output outside f()?
This does seem like useful functionality to have: I would suggest that you file an issue with the package.
However, as a quick hack, something like the following should work:
oldout = STDOUT
(rd,wr) = redirect_stdout()
start_reading(rd)
# call your function here
flush_cstdio()
redirect_stdout(oldout)
close(wr)
s = readall(rd)
close(rd)
s

Resources