On a Linux 2.4.25 system I have two loadable kernel modules, com20020 and xsoe. These modules should be independent of each other, but /proc/modules has the lines
xsoe 4528 0 (unused)
com20020 10112 0 [xsoe]
- saying that xsoe is referring to com20020. Perhaps there is a programming error so that xsoe inadvertently uses a symbol from com20020. How can I find the cause of this dependency (preferably without unloading com20020)? (depmod -n offers no clue.)
I looked at /proc/ksyms for suspicious symbols in com20020 which might also appear in the source of xsoe; eventually I saw the line
d129e694 debug [com20020]
there. Both the sources of com20020 and xsoe had the definitions unsigned debug; MODULE_PARM(debug, "i"); and in the outputs of nm com20020.o and nm xsoe.o the symbol appeared as common:
00000004 C debug
The cure was to define the object debug to have internal linkage (storage-class
static).
The search for common symbols could be automated with a bash command like
join -j 3 <(nm com20020.o) <(nm xsoe.o)|grep C$
Related
Currently, I'm learning RISC-V, use the RISC-V toolchain, and edit a new ld script for my embedded. I write a example, and compile to watch the opcode.
Example:
#include <stdio.h> //float.c
int main()
{
float a=1.04;
printf("a=%f\n",a);
return 0;
}
My steps is:
1. riscv64-unknown-elf-gcc -S float.c *//generate assembly code*
2. riscv64-unknown-elf-as float.s -o float.o *//generate obj file*
3. riscv64-unknown-elf-ld -T elf64lriscv1.x float.o *//use own script to link, -T is using other script*
and then,it will show "float.c:(.text+0x50): undefined reference to `printf'
I'm try
Add -lc parameter, but doesn't working, it will show more undefined message.
My ld script
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv","elf64-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
SEARCH_DIR("/path/to/install/riscv/toolchain/riscv64-unknow-elf/lib");
/*MEMORY{ //for my embedded allocation
flash : org = 0x0, l = 0x10000
ram : org= 0x10000, l = 512
}*/
SECTIONS{
_start =0x10000;
.text :
{
*(.text)
}
.bss :
{
*(.bss)
*(.sbss)
}}
Also, i'm trying to use the default script, like this command:
$ riscv-unknown-elf-ld float.o -o float
but it is same result....
please help me!
Regards!
printf is provided by the C standard library (and is very difficult to implement). You need to link it (perhaps by adding -lc to your riscv-unknown-elf-ld command, or by giving the complete path of that library)
You might pass additional options to your riscv-unknown-elf-ld perhaps -M, -L search-dir, --trace, --verbose, etc. Read also more carefully the chapter about ld scripts.
Since you are cross-compiling, you might need to cross-compile some libc from source code.
You need to spend more time understanding the behavior of linkers and ELF object files and executable format (see also elf(5)). Consider reading Linkers and Loaders
You could use other cross- binutils programs (like cross- objdump, nm, readelf etc...) to explore the relevant object files.
If you are coding for a bare metal system, you might want to compile in freestanding mode (passing -ffreestanding to your GCC) and provide so implement your own printf (or other output) function. Existing free software C libraries could inspire you (but you need to find one or work many months to develop some equivalent). Study for inspiration the source code of GNU libc or of musl-libc.
I recommend also reading about OSes, e.g. Operating Systems: Three Easy Pieces (since the OS concepts are relevant to you, because an embedded system on the bare metal share features with OSes). OSDEV wiki might also be helpful (but is not about RISC-V).
You could need several months of work (or even years), so budget it appropriately.
BTW, I am surprized that you use a float in your example. Floating point is difficult. See floating-point-gui.de ; For a first try, I would consider using integer only.
How are intermodule dependencies resolved when both modules are built outside of the kernel tree and modversioning is enabled?
Modversioning is used to ensure that binary loadable modules are compatible with the kernels they are loaded upon. It is enabled with .config option CONFIG_MODVERSIONS.
We have two dynamically loaded kernel modules, one of which uses an exported symbol from the other. Although the module with the dependence on the other is loaded after the other, insmod complains that it can not resolve a dependency.
[FWIW, these particular modules would serve no useful purpose in the open source world. The people who designed these modules like to keep them out of the kernel tree for their own SCM purposes. The solution of deploying these as a kernel patch will not work.]
This is what the kernel log shows.
<4>foomod: no symbol version for bar_api
<4>foomod: Unknown symbol bar_api
However, if I cat /proc/kallsyms, the bar_api is there and shown as exported.
Another developer here suggested that we use a .conf file to get invoked from the loadmodules script that ignores this error and forces a load, something like this.
install foomod { /sbin/modprobe --ignore-install --force-modversion foomod
$CMDLINE_OPTS; }
I think there has got to be a cleaner way to fix this.
I've tried modifying the Makefile to reference symvers of the module exporting the symbol. The module source for each are in peer directories. It does not seem to matter, but I could be doing this wrong.
KBUILD_EXTRA_SYMBOLS := ../barmod/Module.symvers
This is the content of Module.symvers:
0x00000000 bar_api bar_api barmod
The 0x00000000 is supposed to be valid with modversioning disabled. I think if I could use modprobe like this and see the exported function, then the modprobe would be successful. However, this would only work when modversions is disabled.
# modprobe --dump-modversions foomod.ko
0x00000000 bar_api
However, copying both drivers into the kernel tree and building from within it works. This is a partial listing of the symbols referenced with checksums.
# modprobe --dump-modversions foomod.ko
0x46085e4f add_timer
0x7d11c268 jiffies
0x6a9f26c9 init_timer_key
0x7ec9bfbc strncpy
0xe43dc92b misc_register
0x3302b500 copy_from_user
0x85f8a266 copy_to_user
0xc6538cfc bar_api
0xea147363 printk
: :
Way back around ~2002 having CONFIG_MODVERSIONS would have caused the build to append a checksum generated from genksyms to each exported kernel function. Symbols would look something like this: printk_R1b7d40. This is the last time I've had to deal with modversioning since all of my work since has been with open-source code, within the stock kernel code, or with modversioning disabled. However, today's builds use genksyms to create a checksum for each symbol that goes into a special section. This special section is checked for a checksum match.
There used to be a kernel macro called EXPORT_SYMBOL_NOVERS() that would have worked, but that has been deprecated.
The Linux kernel used is 2.6.32.
I've found these articles relevant and helpful, but inconclusive:
http://lxr.free-electrons.com/source/Documentation/kbuild/modules.txt
http://lwn.net/Articles/21393/
http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
http://lwn.net/Kernel/LDD2/ch11.lwn
How do I cleanly export a function from a loadable module and allow it to be used by another, dependent loadable module when both are built outside of the Linux kernel?
when we cat 'proc/kallsyms' or 'system.map' we get symbols like this
....
c033718c T nf_hook_slow
c04ca284 r __ksymtab_nf_hook_slow
c04ca28c r __ksymtab_nf_hooks
c04d24a0 r __kcrctab_nf_hook_slow
c04d24a4 r __kcrctab_nf_hooks
c04e9122 r __kstrtab_nf_hook_slow
c04e9179 r __kstrtab_nf_hooks
c054d854 D nf_hooks
c0571ca0 d nf_hook_mutex
....
what is the meaning of T, r, D, d stuffs?
I can find symbols in kernel source as EXPORT_SYMBOL(...)
but there are others prefixing with __ksymtab... or __kstrtab...
what are these?
Is is possible that there are symbols in System.map but excluded in /proc/kallsyms?
(assuming kernel is compiled properly)
I have netfilter enabled linux kernel but I cant find the symbol 'nf_hooks'
but there is '__ksymtab_nf_hook'. is there some way to get address of nf_hooks
using __ksymtab_nf_hook?
I see in my linux source code EXPORT_SYMBOL(nf_hook) but I cant find it if I
'cat /proc/kallsyms'. is there some typical reason for this?
thank you in advance.
The format is similar to that of the output of nm utility, see also this page.
To put it simple, 'T' usually denotes a global (non-static but not necessarily exported) function, 't' - a function local to the compilation unit (i.e. static), 'D' - global data, 'd' - data local to the compilation unit. 'R' and 'r' - same as 'D'/'d' but for read-only data.
These are the items from the special sections needed to export symbols so that the symbols could be used by kernel modules.
For each exported symbol, al least the following is defined by EXPORT_SYMBOL():
__kstrtab_<symbol_name> - name of the symbol as a string
__ksymtab_<symbol_name> - a structure with the information about the symbol: its address, address of __kstrtab_<symbol_name>, etc.
__kcrctab_<symbol_name> - address of the control sum (CRC) of the symbol - it is used, for example, to check if the kernel or a module provides an exactly the same symbol as needed by a given kernel module. If a module requires a symbol with a given name and CRC and the kernel provides a symbol with that name but a different CRC (e.g. if the module was compiled for a different kernel version), the module loader will refuse to load that kernel module (unless this check is disabled).
Take a look at the implementation of EXPORT_SYMBOL() macro in linux/export.h for details.
Not sure but I have not encountered a situation so far when a function ("text symbol") or a variable ("data symbol") was present in System.map but not shown in /proc/kallsyms if the kernel is compiled properly and with kallsyms fully enabled (CONFIG_KALLSYMS=y, CONFIG_KALLSYMS_ALL=y). If CONFIG_KALLSYMS_ALL=n, only the functions (to be exact, symbols from *.text sections) will be shown in /proc/kallsyms.
Depends on your kernel version. You can take a look at the definition of EXPORT_SYMBOL() for your kernel and find which type __ksymtab_<symbol_name> variables are. In the kernel 3.11, it is struct kernel_symbol defined in linux/export.h. Having the definition of that struct and its address, I suppose, you can get the address of the symbol: struct kernel_symbol::value. Haven't tried this myself though.
Note, however, that __ksymtab_nf_hook is for nf_hook but not for nf_hooks. The name must match. nf_hooks and nf_hook are different entities.
Hard to tell without seeing the code and the relevant part of /proc/kallsyms. Maybe it is #ifdef'ed out and not compiled at all, may be there is something else.
Besides, nf_hooks is a data item so it might not show up in /proc/kallsyms if CONFIG_KALLSYMS_ALL is 'n'.
Sometimes when I do nm on a .so file (for example, libstdc++.so.6), it says no symbols, and I need to use nm --dynamic. But for some other .so files, I can see the symbols without --dynamic.
The doc says:
Display the dynamic symbols rather than the normal symbols. This is only meaningful for dynamic objects, such as certain types of shared libraries.
But it is confusing... what "types" of shared libraries need --dynamic? How is this determined? During the compilation of the library? I thought all shared libraries are dynamic (I mean, can be dynamically loaded during run time), but seems that my understanding is not quite right.
It could very well possible that if your symbol is not exported from your shared library, it would end up in the normal symbol table instead of the dynamic symbol table.
There are many types of symbols in ELF files.
symbols part of the Normal Symbol table. This is the output from mere nm libabc.so or objdump --syms libabc.so. These symbols are only used during static linking.
symbols part of the Dynamic Symbol table. This is the output from nm --dynamic libabc.so or objdump --dynamic-syms libabc.so. Dynamic symbol table is the one used by the run-time linker/loader which binds the symbols between the ELF file which refers them and the ELF file which defines them. It is also used by the static linker, while linking a shared library with an application which requires it. This is the component which helps in showing all the undefined symbol errors during linking.
Hidden symbols - these are the symbols which have been marked using _attribute_ ((visibility("hidden"))). These symbols are not exported outside and can only be used within the library. The visibility is checked during the linking step, and hence is enforced only for shared libraries. The default visibility is public, i.e. the symbols are exported unless otherwise specified. The behavior can be modified using the -fvisibility=default|internal|hidden|protected.
Set the default ELF image symbol visibility to the specified
option—all symbols will be marked with this unless overridden within
the code. Using this feature can very substantially improve linking
and load times of shared object libraries, produce more optimized
code, provide near-perfect API export and prevent symbol clashes. It
is strongly recommended that you use this in any shared objects you
distribute. Despite the nomenclature, default always means public ie;
available to be linked against from outside the shared object.
protected and internal are pretty useless in real-world usage so the
only other commonly used option will be hidden. The default if
-fvisibility isn't specified is default, i.e., make every symbol public—this causes the same behavior as previous versions of GCC.
An overview of these techniques, their benefits and how to use them is
at http://gcc.gnu.org/wiki/Visibility.
To answer your question when would you use the --dynamic option of nm, it would be when you want to list all the symbols exported by your shared library, and the only ones that are available to the ELF images which reference them.
You need to use --dynamic or -D option on a shared library if it is stripped and thus only contains a dynamic symbol table.
You may want to use this option for other shared libraries to explicitly display the dynamic symbol table as this is the table that is consulted by the dynamic linker.
The file utility indicates whether a shared library is stripped or not. Example:
$ file /usr/lib64/libcrypt-nss-2.26.so
[..] ELF 64-bit LSB shared object, x86-64 [..], not stripped
$ file /usr/lib64/libxml2.so.2.9.7
[..] ELF 64-bit LSB shared object, x86-64 [..], stripped
Example for how the different symbol tables may contain different symbols:
$ nm -D /usr/lib64/libcrypt-nss-2.26.so | wc -l
39
$ nm /usr/lib64/libcrypt-nss-2.26.so | wc -l
112
I was trying to make virtualbox kernel modules builtin, I'm almost completed here, but at the final step, it stopped compiling, because kernel seems to treat all vbox* modules as a single one:
drivers/vboxnetadp/built-in.o: In function `cleanup_module':
(.exit.text+0x0): multiple definition of `cleanup_module'
drivers/vboxdrv/built-in.o:(.exit.text+0x0): first defined here
drivers/vboxnetadp/built-in.o: In function `init_module':
(.init.text+0x0): multiple definition of `init_module'
.. suppressed output ...
make[1]: *** [drivers/built-in.o] Error 1
make: *** [drivers] Error 2
Any thoughts ? Here's how I got that:
I copied all module sources into drivers folder, edit the makefile, put a obj-y += vbox/, and edit all Makefile of vbox modules, change obj-m to obj-y to make them builtin, pretty dirty hack, but worked.
EDIT
Why need to do that ? I need to disable module loading on my machine, so no modules should be present, I've made all modules wrote by myself builtin, only thing left is vbox's ones now
I would say your question rather belongs to Stack Overflow, since it is basically a c-programming-language-question.
The problem you are facing is that you try to compile two (previously separate) programs into one. Both seem to use the same functions - meant within their own context.
My guess is that you will have to rename all these multiple occurrences of init_module or other functions into separate name-spaces (like net_init_module and drv_init_module). Or perhaps there is a way to declare these functions to be "local" - it`s been a while that I programmed in C...