.text, .bss, .data sections are not showed in kernel module - linux

I have the following kernel module and Makefile for Linux running on Beaglebone board.
#include <linux/module.h>
#include <linux/kernel.h>
s32 gval = 200;
static s32 __init test_init(void)
{
pr_info("%s done : gval:%d\n", __FUNCTION__, gval);
return 0;
}
static void __exit test_deinit(void)
{
pr_info("%s done : gval:%d\n", __FUNCTION__, gval);
}
module_init(test_init);
module_exit(test_deinit);
MODULE_LICENSE("GPL");
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
BBB_KERNEL_SRC=kernel_source_path
EXTRA_CFLAGS += -g -DDEBUG
obj-m += test_km.o
test_km-objs := kmodule.o
all:
make -C $(BBB_KERNEL_SRC) M=$(PWD) modules
clean:
make -C $(BBB_KERNEL_SRC) M=$(PWD) clean
The module builds fine and test_km.ko file is generated, when the test_km.ko file is insmod, the /sys/modules/test_km/sections shows the following.
.ARM.exidx.exit.text
.ARM.exidx.init.text
.exit.text
.gnu.linkonce.this_module
.init.plt
.init.text
.note.Linux
.note.gnu.build-id
.plt
.rodata
.rodata.str1.4
.strtab
.symtab
Why the .text, .data, .bss sections not present for this kernel module.
I have downloaded the kernel source from https://github.com/beagleboard
Linux kernel version : 5.10.120

Why the .text, .data, .bss sections not present for this kernel module?
TL;DR : Because you haven't coded any.
The macros, module_init() and module_exit() place those functions in the init and exit sections.
s32 gval = 200; is only references by the init and exit code and the tools have deduced that just the constant 200 can be used.
You need to add non-init and non-exit code and then the tools will start to put things in .text, .data and .bss.

Related

The address where filename has been loaded is missing [GDB]

I have following sample code
#include<stdio.h>
int main()
{
int num1, num2;
printf("Enter two numbers\n");
scanf("%d",&num1);
scanf("%d",&num2);
int i;
for(i = 0; i < num2; i++)
num1 = num1 + num1;
printf("Result is %d \n",num1);
return 0;
}
I compiled this code with -g option to gcc.
gcc -g file.c
Generate separate symbol file
objcopy --only-keep-debug a.out a.out.sym
Strip the symbols from a.out
strip -s a.out
Load this a.out in gdb
gdb a.out
gdb says "no debug information found" fine.
Then I use add-symbol-file command in gdb
(gdb) add-symbol-file a.out.debug [Enter]
The address where a.out.debug has been loaded is missing
I want to know how to find this address?
Is there any command or trick to find it?
This address is representing WHAT?
I know gdb has an other command symbol-file but it overwrites the previous loaded symbols.
So I have to use this command to add many symbol files in gdb.
my system is 64bit running ubuntu LTS 12.04
gdb version is 7.4-2012.04
gcc version is 4.6.3
objcopy --only-keep-debug a.out a.out.sym
If you want GDB to load the a.out.sym automatically, follow the steps outlined here (note in particular that you need to do the "add .gnu_debuglink" step).
This address is representing WHAT
The address GDB wants is the location of .text section of the binary. To find it, use readelf -WS a.out. E.g.
$ readelf -WS /bin/date
There are 28 section headers, starting at offset 0xe350:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 0000000000400238 000238 00001c 00 A 0 0 1
...
[13] .text PROGBITS 0000000000401900 001900 0077f8 00 AX 0 0 16
Here, you want to give GDB 0x401900 as the load address.

C++-Assembly linking on x86 / ubuntu - undefined reference to ThreadRoot, SWITCH

I am building Nachos source on Ubuntu 12.04
If we believe "lscpu" output, machine arch is x86. I am getting the following error at the last step of make:
$ make
g++ -m32 -P -I../network -I../filesys -I../userprog -I../threads -I../machine -I../lib -iquote -Dx86 -DLINUX -c ../threads/switch.S
g++ bitmap.o debug.o libtest.o sysdep.o interrupt.o stats.o timer.o console.o machine.o mipssim.o translate.o network.o disk.o alarm.o kernel.o main.o scheduler.o synch.o thread.o addrspace.o exception.o synchconsole.o directory.o filehdr.o filesys.o pbitmap.o openfile.o synchdisk.o post.o switch.o -m32 -o nachos
scheduler.o: In function `Scheduler::Run(Thread*, bool)':
/home/userx/nachos/NachOS-4.0/code/build.linux/../threads/scheduler.cc:133: undefined reference to `SWITCH'
thread.o: In function `Thread::StackAllocate(void ()(void), void*)':
/home/userx/nachos/NachOS-4.0/code/build.linux/../threads/thread.cc:345: undefined reference to `ThreadRoot'
/home/userx/nachos/NachOS-4.0/code/build.linux/../threads/thread.cc:356: undefined reference to `ThreadRoot'
collect2: ld returned 1 exit status
make: * [nachos] Error 1
$
Here is the switch.S that has the symbol defs --
/* We define two routines for each architecture:
*
* ThreadRoot(InitialPC, InitialArg, WhenDonePC, StartupPC)
<...>
#ifdef SOLARIS
.globl ThreadRoot
ThreadRoot:
#else
.globl _ThreadRoot
_ThreadRoot:
#endif
#ifdef x86
.text
.align 2
.globl ThreadRoot
.globl _ThreadRoot
_ThreadRoot:
ThreadRoot:
<...>
.globl SWITCH
.globl _SWITCH
_SWITCH:
SWITCH:
<...>
#endif
I have skipped the #ifdefs for more arch like DECMIPS, POWERPC, APPLEPOWERPC etc.
Yes, my env $PATH includes dir where switch.s resides :/home/userx/nachos/NachOS-4.0/code/threads/
Please let me know if any more info is needed to debug. Thanks a lot.
Try adding underscore in the C header file that have extern "C" SWITCH and ThreadRoot, and change too the .c file in where the error is. I mean use _SWITCH instead SWITCH and the same for ThreadRoot.

How do I share global variables in a shared library(.so) across the processes that use the same shared library?

I am trying to count the number of different processes using the shared library by defining the static global variable on the top of the library. Created a shared library, os.so and calling it from main.c. Code as follows.
/// cat os.c
#include <stdio.h>
static int count = 0;
void incre() {
++count ;
printf("Process using os.so is %d\n",count);
}
gcc -c -fpic os.c
gcc -shared os.o -o os.so
/// cat main.c
#include <stdio.h>
#include <dlfcn.h>
void main() {
void (*ptr2) (void);
void *handle;
handle = dlopen("./os.so", RTLD_NOW);
if (handle == NULL) {
printf("failed to open library\n");
exit(2);
}
ptr2 = dlsym(handle,"incre");
ptr2();
getchar();
dlclose(handle);
}
gcc main.c -ldl produces a.out
Now I am running 2 different instances of a.out in separate shells. Surprisingly, I am getting the output same as "Process using os.so is 1 " from both the processes. Since count is an global variable, I am expecting it to incremented in the shared library address space.
Also I observed from the output /proc/pid/maps for both the processes that they are referring to same file descriptor of os.so.
# cat /proc/1943/maps
00920000-00921000 r-xp 00000000 fd:01 298166 /home/user1/personal/programs/logic /libraries/os.so
# cat /proc/1944/maps
00152000-00153000 r-xp 00000000 fd:01 298166 /home/user1/personal/programs/logic /libraries/os.so
My question is why the global data is not shared for all the processes which uses os.so?
If I declare static variable in incre() in os.so, still it is not shared?
Is it the same with windows dll's also?

gcc, static library, external assembly function becomes undefined symbol

I have a problem with g++ building an application which links to a static library, where the latter shall contain some global functions written in external asm-files, compiled with yasm. So in the library, I have
#ifdef __cplusplus
extern "C" {
#endif
extern void __attribute__((cdecl)) interp1( char *pSrc );
extern void __attribute__((cdecl)) interp2( char *pSrc );
#ifdef __cplusplus
}
#endif
which I reference elsewhere inside the library. Then, there is the implementation in an asm-file, like this:
section .data
; (some data)
section .text
; (some text)
global _interp1
_interp1:
; (code ...)
ret
global _interp2
_interp2:
; (code ...)
ret
Compiling and Linking work fine for the library, I do
yasm -f elf32 -O2 -o interp.o interp.asm
and then
ar -rc libInterp.a objs1.o [...] objsN.o interp.o
ranlib libInterp.a
Now finally, to link the library to the main application, I do
g++ -O4 -ffast-math -DNDEBUG -fomit-frame-pointer -DARCH_X86 -fPIC -o ../bin/interp this.o that.o -lboost_thread -lpthread ./libInterp.a
and I get the errors
undefined reference to `interp1'
undefined reference to `interp2'
What am I doing wrong here? any help is appreciated.
Depending on the target type, gcc will not prepend a leading underscore to external symbols. It appears that this is the case in your scenario.
The simple fix is probably to remove the underscores from the names in your assembly file.
A couple alternatives you might consder might be to use something like one of the following macros for your symbols in the assembly file:
from http://svn.xiph.org/trunk/oggdsf/src/lib/codecs/webm/libvpx/src/vpx_ports/x86_abi_support.asm
; sym()
; Return the proper symbol name for the target ABI.
;
; Certain ABIs, notably MS COFF and Darwin MACH-O, require that symbols
; with C linkage be prefixed with an underscore.
;
%ifidn __OUTPUT_FORMAT__,elf32
%define sym(x) x
%elifidn __OUTPUT_FORMAT__,elf64
%define sym(x) x
%elifidn __OUTPUT_FORMAT__,x64
%define sym(x) x
%else
%define sym(x) _ %+ x
%endif
from http://www.dcs.warwick.ac.uk/~peter/otherstuff.html
%macro public_c_symbol 1
GLOBAL %1,_%1
%1:
_%1:
%endmacro
public_c_symbol my_external_proc:
; ...
RET

Building 16 bit os - character array not working

I am building a 16 bit operating system. But character array does not seem to work.
Here is my example kernel code:
asm(".code16gcc\n");
void putchar(char);
int main()
{
char *str = "hello";
putchar('A');
if(str[0]== 'h')
putchar('h');
return 0;
}
void putchar(char val)
{
asm("movb %0, %%al\n"
"movb $0x0E, %%ah\n"
"int $0x10\n"
:
:"m"(val)
) ;
}
It prints:
A
that means putchar function is working properly but
if(str[0]== 'h')
putchar('h');
is not working.
I am compiling it by:
gcc -fno-toplevel-reorder -nostdinc -fno-builtin -I./include -c -o ./bin/kernel.o ./source/kernel.c
ld -Ttext=0x9000 -o ./bin/kernel.bin ./bin/kernel.o -e 0x0
What should I do?
Your data segment is probably not loaded in to the target. What are you doing after the link with your brand new kernel.bin file, which is in fact an elf file ?

Resources