Thursday, January 27, 2011

Implementing System Call on Linux 2.6 for i386



In this post I would like to take you through a sequence of steps in creating your own system call in three exercises.
Exercise1: editing the kernel source so as to add new system call.
Exercies2: Compiling the modified kernel source to generate a new kernel image
Exercise3: creating an application (user space program) to access you’re newly created system call.

Exercise1

System call: Basically system calls are kernel space routines used by application to invoke kernel devices. System calls provide the interface between a process and operating system.

To edit the kernel download the source code from www.kernel.org and unzip it as follows,

$ tar xvf linux-2.6.32.tar.gz
xvf options used with tar.
(Linux-2.6.32.tar.gz is the name of the zipped folder downloaded)

Generally source is placed at the following path /usr/lib, this is a convention followed. So copy the unzipped folder to /usr/lib path.
Note: iam explaining the following steps assuming that you are at the following path /usr/src/linux-headers-2.6.32 that is in the source folder.
Check your current path using the command pwd
$ pwd
/usr/lib/linux-2.6.32
$ ls (displays the contents of source folder as shown in the below screen shot.)

Step1: Assign unique id for the new system call.

To do so open the file at the path /usr/lib/linux-2.6.32/arch/x86/include/asm/unistd-32.h and add your system call. This file contains the list of system calls each with a unique id (some thing like a count value or serial no)
Note: i am adding system call to X86 architecture as most of the desktops are with x86

Go to the end of this file and see the last system call, and if its id is say 336 then add your system call with id 336+1 that is 337 and increment the macro NR_syscalls by one, if it is 337 then make it 337+1 that is 338 . NR_syscalls hold the count of total no of system calls, as you have added one hence that has to be incremented right.

$ vim arch/x86/include/asm/unistd_32.h

Add this to file: #define __NR_mycall 337
Modify this : #define NR_syscalls 338

*save the above changes to file.

Step2: Declare system call routine prototype.

To do so open the file at the path /usr/lib/linux-2.6.32/arch/x86/include/asm/syscall.h
Note: in this file you find separate sections/ segments for 32-bit, 64-bit and a common segment for 32 & 64-bit machines. I am adding routine for new system call in the '32 & 64 bit segment' as this call can be invoked on both the machines.

$ vim arch/x86/include/asm/syscall.h

Add: asmlinkage int sys_mycall(void);

  • asmlinkage is a GNU standard.
  • int return type of the syscall.
  • sys” its a prefix, convention followed for system calls.
  • mycall is the name of our new system call.
*save the above changes to file.

Step3: store system call address in syscall table data structure.
To do so open the file at the path /usr/lib/linux-2.6.32/arch/x86/kernel/syscall_table_32.s
This is one of the assembly sources and add this below line of code at the end of the file and even see to it that it is at the appropriate position 337.

$ vim arch/x86/kernel/syscall_table_32.s

Add: .long sys_mycall

  • .long is the instruction to assembler

Step4: implement syscall routine, that is functionality to be achieved by our new system call.
To do so we go into one of the branches (directories) of the source code. Usually the system calls related to network are implemented in the /net directory and memory management calls are implemented in /mm directory and so on. I suggest to implement our new system call functionality in /kernel branch (directory) in existing sys.c file as a beginner.
Go to end of the file and add the following code, here our new system call prints the name of the application that invokes it. Here i am using a MACRO current (kernel space global pointer, I will discuss on it in further posts)
$ cd kernel
$ pwd ( to confirm the path )
/usr/lib/linux-2.6.32/kernel
$ vim sys.c
Add:   
          asmlinkage int sys_mycall(void)
          {
                  printk(“New sys call invoked by %s app\n”, current->comm);
           }
Note: functionality should be achieved using kernel frame work only. Prink is provided in the kernel frame work as you known by the time.

Note: here we implemented the functionality in the existing .c file to make you understand procedure in a simple way, where in we can do the same by creating our own branch in the kernel source directory, here we have to create a Makefile for our .c file and even need to make changes in the Makefile of source directory.

*save the above changes to file.
Click here for Exercise2


Please leave comment :-)                                                Queries are at free of cost

Compiling Kernel Source

Exercise 2

As the kernel source is modified to add a new system call in Exercise1, then we need to compile it to generate a new kernel image and this new image is used at the next boot of the system.

(Mainline kernel is called as vanilla kernel)
Note: I am assuming that you are in source directory, at /usr/lib/linux-2.6.32

Step1: Assign kernel version tag.
 
To do so open the Makefile at the path /usr/lib/linux-2.6.32/Makefile and at the top of the file you will find the field EXTRAVERSION, edit as follows

$ Vim Makefile

Modify: EXTRAVERSION = mytest
*save the above changes to file.

Step2: Choose kernel configuration.
 
To do so type that following command. This will generate a configuration file “.config”. Any file that starts with “.” is a hidden file, to list the hidden files use option 'a' with 'ls' command.
$ make menuconfig (this pumps kernel info onto console, wait until prompt returns)

Note: refer to man pages on make, type “make help” at your terminal.

Step3: Compile the source to create kernel image (raw) and modules.

$ make
This takes around 30 min on a normal desktop, to speed up, create threads if yours is a multicore machine. To do so type the following command, here 4 is the no of threads.

$ make -j4

Step4: Install the modules on file system
 
To do so type the following command.
$ make modules_install
This copies the modules into disk space and adds folder at /lib/modules/[name]

Step5: Update bootloader and boot folder with new kernel information.

To do so type the following command.
$ make install
Grub contains the list of kernel images, one among them is chosen at boot time.


Please leave comment :-)                                                  Queries are at free of cost

Wednesday, January 26, 2011

How to Create Dynamic Library in Linux


Steps In Creating Dynamic Library
Click here to understand compilation stages in Linux

Step1: implement the library source. Let us assume there are two files namely one.c and two.c each implementing one function as follows
$ vim one.c
#include<stdio.h>
void fun1(){
printf("This is function 1\n");
}
~
$ vim two.c
#include<stdio.h>
void fun2(){
printf("This is function 2\n");
}
~
Step2: compile the sources to generate relocatables. Relocatable binary is created in two forms
position dependent : in this relocated code is bound to offset
position independent : in this relocated code is not bound to offset, because of which sharing of libraries among multiple applications becomes easy.
Preferably we compile them to get position independent relocatables because of some advantages (will cover latter on).
Note: ‘.so’ is the extension for dynamic libraries.

$ gcc -c -fpic one.c 
        ( to create a relocatable one.o )
$ gcc -c -fpic two.c 
       ( to create a relocatable two.o ) 
$ gcc -shared -o libmyown.so one.o two.o
        ( libmyown.so is the name of the dynamic library to be created )
         - shared flag used to create a shared library 

$ vim mylib.h
void fun1();
void fun2();

to make use of the library above created write a test application as follows.
$ vim test.c

#include <stdio.h>
#include <mylib.h>

main()
{
    printf("This is test to create own library\n");
    fun1();/*call to function */
    fun2();/*call to function */
}

Now compile the source file as follows.

$ gcc -I ./ test.c -o testdynamic ./libmyown.so 
         - I option to let the compiler to check for "mylib.h" in current working directory
         
$ ./testdynamic
This is test to create own library
This is function 1
This is function 2

                                   
Please leave comment :-)                                                Queries are at free of cost

Stages of Compilation in Linux using gcc

When you write a program, it doesn't do anything until you compile it. People working on Linux machine use GCC a compiler for C, C++, java, Fortan and other program code that can be used in Unix, GNU/Linux machines. It is distributed as Free Software under the GNU General Public License (GNU GPL). It is useful to know the step by step compilation stages as a developer or even for a beginner.
        During the compilation we go through four stages and each stage use a tool to translate code from one to other till we reach the loadable binary image (binary file) for execution in architecture. As we are using sequence of tools hence it is called as GNU tool chain. Understanding the various stages of compilation helps in cross compilation of code.
Below steps shows compilation process using gcc compiler
Source file:
        It contains the source program in test format. It can be of any language c, c++, etc. For eg: first.c is a C source code.


Step1:
Pre-processing: (here we use cpp tool)
  • it helps in creating fast and efficient code.
  • it reads from header files for creating a pre-processed source file.
  • all macros and constant symbols are replaced.
  • all conditional pre-processor directives are processed by pre-processor.
  • it provides conditional pre-processor directives are pre-processed by processor
$ gcc -E first.c -o first.i 

    - E option to halt the compilation at pre-processing stagem. Refer man page.
    - o option to redirect the output to the new file first.i.


first.i contains the entire header file content + code.To see the sequence of approach in generation of first.i
$ gcc -v -E first.c -o first.i
    - v option stands for verbose.
 

Step2:
Assembler:
(here we use compiler tool)

  • Takes pre-processed file and creates file with '.s' extension called as assembly file.
  • It is mainly required for optimixation (speed and space) of code.

$ gcc -S first.i -o first.s

     - S option to halt at assembly stage.

Step3:
Relocatable Binary:
(here we use assembler tool)

  • contains offset address of the assembly code, it is assigned at compile time.object dump of first.o shows offset address.
for eg: a relocatable code contains call 19<>. Its position depends on main position.
This file contains source in assembly and library routines.

$ gcc -c first.s -o first.o

Note: first.o is not readable. To view the content we use a tool "objdump" called as binary disassembler tool.

$ objdump -D first.o
    - D option stands for disassemble, refer man pages.
 

Step4:
Linking:
(here we use linker tool)

  • linker tool is used to build the executable image, here we are packaging that gives lodable binary code that can be loaded and executed.

$ gcc first.o
    gcc first.o by default creates a.out, to get executable of specified name
we can give as
$ gcc first.o -o first (here first is the executable name we specified)

  • This executable (first) will be green in color in Bash shell.
  • This loadable fiel contaions loadable address in the form of segement and offset called as absolute address. 
  • Function calls entries present it PLT called as procesure linkage table.
  • Executable file contains some run time library. 
  • This file is mainly created by linker which is OS dependent.
    to view the content of executable first page wise,
$ objdump -D first | more
 


Observations:
So finally we are with five different files first.c, first.i, first.s, first.o, first, we shall
check out these file formats using the tool file.
( just a sequence of steps together shown )

$ gcc -E first.c -o first.i
$ gcc -S first.i -o first.s
$ gcc -c first.s -o first.o
$ gcc first.o -o first
$ file first.c
first.c: ASCII text
$ file first.i
first.i: ASCII C program text
$ file first.s
first.s: ASCII assembler program text
$ file first.o
first.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file first
first: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
$

$ objdump -D first.o | more
first.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0:         55                                          push          %ebp 
1:         89 e5                                     mov           %esp,%ebp 
3:         83 e4 f0                                 and           $0xfffffff0,%esp 
6:         83 ec 10                                sub            $0x10,%esp 
9:         c7 04 24 00 00 00 00            movl          $0x0,(%esp) 
10:       e8 fc ff ff ff                            call 11       <main+0x11> 
15:       c9                                          leave 
16:       c3                                          ret
--More--
$ objdump -D first | more (go down and see <main> section)
080483e4 <main>:
80483e4:         55                                          push          %ebp
80483e5:         89 e5                                     mov           %esp,%ebp
80483e7:         83 e4 f0                                 and           $0xfffffff0,%esp
80483ea:         83 ec 10                                sub            $0x10,%esp
80483ed:         c7 04 24 00 00 00 00            movl          $0x0,(%esp)
80483f4:       e8 fc ff ff ff                              call 11       <main+0x11>
80483f9:       c9                                            leave
80483fa:       c3                                            ret 
--More--

       You can view machine instruction code and important thing to observe is the address at the extreme left of each line, this is an offset address which is reloaded or remapped to a virtual address by adding this offset to a base address of the segment.

       We have obtained executable (first) from the relocatable (first.o) and here in first observe the address of the instruction that are mapped to some virtual 32-bit address. The step3 output (first.o) is hence called as relocatable as the offset address are remapped to some virtual address. Linker does the job of relocating offset address to the platform specific address. This virtual address concept is huge and interesting and even important topic of discussion which i will post soon. :-)


Note: Creation of files from .c to .o can be used in any architecture. Where as the executables are specific to platform and architecture.

Please leave comment :-)                                                Queries are at free of cost

Tuesday, January 25, 2011

How to Create a Static Library in Linux

Basically libraries are of two types
$ gcc first.c -o first
This gives an executable which is of dynamic type. This can be known by using the tool file.

$ file first
First: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
$ gcc first.c -o first
$ ls -l
-rwxr-xr-x 1 gvamshi gvamshi 7139 2011-01-23 14:26 first
-rw-r--r-- 1 gvamshi gvamshi 63 2011-01-23 14:26 first.c
-l is the option used with ls for long listing.

We run the executable we obtained above by compilation as follows.
$ ./first
This is Linux 2.6.32

To generate an executable of static type, we use a flag static as shown below.
$ gcc -static first.c -o firststatic
$ ls -l
-rwxr-xr-x 1 gvamshi gvamshi 7139 2011-01-23 14:26 first
-rw-r--r-- 1 gvamshi gvamshi 63 2011-01-23 14:26 first.c
-rwxr-xr-x 1 gvamshi gvamshi 578015 2011-01-23 14:35 firststatic
$ ./firststatic
This is Linux 2.6.32

Here the thing to observe is the size of both executables that is first and firststatic, here the size of firststatic is approximately ten times that of first, this is because the libraries are also loaded into it. As the libraries are loaded with our code then this firststatic can be executed on any machine which is of same architecture and of same linux kernel version even if the machine doesn't have libc libraries, where as the executable first need the libc on the machine to run as the libraries are dynamically linked and are loaded at run time by the tool link-loader. As the libraries are linked dynamically the size of executable first is small. Static executable (firststatic) in now independent of libc library.
Note: In gnu linker by default follow dynamic linking strategy.

Steps In Creating Static Library

Step1: implement the library source. Let us assume there are two files namely one.c and two.c each implementing one function as follows
$ vim one.c
#include <stdio.h>
void fun1(){
    printf("This is function 1\n");
}

$ vim two.c
#include <stdio.h>
void fun2(){
    printf("This is function 2\n");
}


Step2: compile the sources (one.c, two.c) to generate relocatables
$ gcc -c one.c
$ gcc -c two.c
ls -l
total 16
-rw-r--r-- 1 gvamshi gvamshi 66 2011-01-23 14:59 one.c
-rw-r--r-- 1 gvamshi gvamshi 844 2011-01-23 15:01 one.o
-rw-r--r-- 1 gvamshi gvamshi 66 2011-01-23 14:58 two.c
-rw-r--r-- 1 gvamshi gvamshi 844 2011-01-23 15:01 two.o
$

Note: “.a “ is the extension for the static libraries.

Using the archive tool ar we create a static library.

$ ar rcs libmyown.a one.o two.o

- libmyown.a is the own static library to be created. According to the general naming conventions a library should start with “lib” .
- rcs are the options (replace, create, symbol) for more details refer to man pages as follows.
- one.o and two.o are the list of sources to be packed into archive.

The above created static library is position dependent.

$ man ar (this gives description about the usage of ar)
$ info ar (this gives information like an ebook)

To list what all files have gone into archive type use option‘t’ of ar.
$ ar -t libmyown.a
one.o
two.o

you can even view the list of file that are packed into libc.a standard library as follows. To see where libc.a located in your machine use whereis as follows, which gives the path for libc.a
$ whereis libc.a
libc: /usr/lib/libc.so /usr/lib/libc.a /usr/share/man/man7/libc.7.gz

$ ar -t /usr/lib/libc.a init-first.o |more
libc-start.o
sysdep.o
version.o
check_fds.o
libc-tls.o
elf-init.o
dso_handle.o
errno.o
--More--
Now we can ship our library to costumer, along with this we even need to ship the header file to give the function prototypes. Create a header file mylib.h as follows.

$ vim mylib.h
void fun1();
void fun2();

to make use of the library above created write a test application as follows.
$ vim test.c

#include <stdio.h>
#include <mylib.h>

main()
{
    printf("This is test to create own library\n");
    fun1();/*call to function */
    fun2();/*call to function */
}

Now compile the source file as follows.

$ gcc test.c -o test (gives an error)
test.c:2:18: error: mylib.h: No such file or directory

to figure out where the error occurred use the following option
$ gcc -v test.c -o test
v option with gcc, stands for verbose.
the error is because the header files included are searched at the following locations.
/usr/local/include
         /usr/lib/gcc/i486-linux-gnu/4.4.3/include
           /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed
           /usr/include
where in our header file exists in the current working directory, and is not in above of the paths, so we have to explicitly say this by using the option I.
$ gcc -I ./ test.c -o test (gives error)
/tmp/ccFPPIsN.o: In function `main':
test.c:(.text+0x16): undefined reference to `fun1'
test.c:(.text+0x1b): undefined reference to `fun2'
collect2: ld returned 1 exit status

Still we end up with the above errors as we missed library, so follow the below step.

$ gcc -I ./ test.c -o teststatic ./libmyown.a
$ ./teststatic
This is test to create own library
This is function 1
This is function 2

Here important thing to note is what ever the executable (teststatic) we generated is not complete static, it is dynamically linked, this can be know by the tool file.

$ file teststatic
teststatic: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped

Therefore to obtain a complete static executable use the -static flag with the above command and check out the type of file as above.

$ gcc -static -I ./ test.c -o test_complete_static ./libmyown.a
$ file test_complete_static
test_complete_static: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.15, not stripped

One more thing to discuss is, in the above output there is something like “not stripped”. Which means there is some extra information like metadata in the executable. That extra unnecessary information can be removed using the tool strip. After stripping the file check out the earlier and current file sizes.
$ ls -l test_complete_static
-rwxr-xr-x 1 gvamsi gvamsi 578100 2011-01-23 17:14 test_complete_static

$ strip test_complete_static
$ ls -l test_complete_static
-rwxr-xr-x 1 gvamsi gvamsi 515108 2011-01-23 17:15 test_complete_static


                                   

Please leave comment :-)                                                  Queries are at free of cost