網頁

2011年8月11日 星期四

kernel- hash list

The overall structure of the hash list in kernel is shown as blow.

Here is the data structure.

struct hlist_head {
struct hlist_node *first;
};

struct hlist_node {
struct hlist_node *next, **pprev;
};

Kernel provides some interface to build a whole hash list quickly and they are more useful.

Some figures are illustrated to desrcbie how to use these function calls for the hash list. 

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}

Insert  a node to the head of hash list.

There are 2 case for this operation and please see below.

Case 1:

no any node exists in the hash list.

Case 2:

Otherwise , there are  more than one nodes  at least in the list.

static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}

Add the node N before the Node next.

 

static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;

if(next->next)
next->next->pprev = &next->next;
}

Add the node Next after node N.

static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}

Remove the node N from the list.

2011年8月9日 星期二

Linux kernel - contain_of

This marco is mostly used in kernel .
The figure is illustrated to descible how the marco "contain_of" work.

The following is the  source code using the marco "contain_of".

#include <stdio.h>

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({            \
     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
     (type *)( (char *)__mptr - offsetof(type,member) );})

struct  St_Inner{
    int         dw_a;
};

struct St_Outer {
    int         dw_a;
    struct St_Inner    St_b;
    int         dw_c;
};

     
int main ()
{
    struct St_Outer  src;
    struct St_Outer  *p_dest;
    struct  St_Inner *p_Inner;
    p_Inner = &src.St_b;
    
    
    p_dest = container_of (p_Inner,struct St_Outer, St_b);
    
    printf ("p_dest %x == src %x\n",p_dest,&src);
    return 0;
}

2011年7月20日 星期三

Interesting callback function

typedef void( *fp_t )(char *);
fp_t( *fp) [2];

It is easy to understand to expand it shown as the following.
void(*(*fp)[4])(char*);
Here is an example to show  where this callback function can be used.
#include <stdio.h>

typedef void( *fp_t )(char *);

void  spi_read(char *data)
{
printf ("spi_read\n");
}
void  spi_write(char *data)
{
printf ("spi_write\n");
}
void  nand_read(char *data)
{
printf ("nand_read\n");
}
void  nand_write(char *data)
{
printf ("nand_write\n");
}
void (*spi_fp[2]) (char *);
void (*nand_fp[2]) (char *);
int main()
{
    int i;
 
    fp_t( *fp) [2];
    spi_fp[0] = spi_read;    
    spi_fp[1] = spi_write;    
    nand_fp[0] = nand_read;    
    nand_fp[1] = nand_write;    
    
    fp = &spi_fp;
    for (i=0;i<2;i++)
    {
        (*fp)[i] (0);
    }
    return 0;
}

2011年6月14日 星期二

LD_DEBUG and LD_LIBRARY_PATH

It is useful to find out which library are loaded when running the program.
LD_DEBUG = help ./a.out
Vaild option for LD_DEBUG
libsdisplay library search paths
relocdisplay relocation processing
filesdisplay progress for input file
symbolsdisplay symbol table processing
bindingsdisplay information about symbol binding
versionsdisplay version dependencies
allall previous options combined
statisticsdisplay relocation statistic
unuseddetermined unused DSOs
helpdisplay this help message and exit
LD_DEBUG=libs ./a.out
17315:    find library=libc.so.6 [0]; searching
17315:     search cache=/etc/ld.so.cache
17315:      trying file=/lib/tls/i686/cmov/libc.so.6
17315:
17315:
17315:    calling init: /lib/tls/i686/cmov/libc.so.6
17315:
17315:
17315:    initialize program: ./a.out
17315:
17315:
17315:    transferring control: ./a.out
17315:
17315:
17315:    calling fini: ./a.out [0]
17315:
17315:
17315:    calling fini: /lib/tls/i686/cmov/libc.so.6 [0]
17315:
From above result, it will find the file "ld.so.conf" to know where the standard library is located.
In this case, the library I only use is glibc. So it is a simple code.
But it is handy tool if your program is very complex and you want to know which library is linked.
gcc --share b.c -o libb.so
gcc -o a{,.c} -lb -L.
Then you should export libary PATH "LD_LIBRARY_PATH"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH;./
The program will be executed successfully.
You can try LD_DEBUG again and the loader will search additional path "./" you assigned  and load the specific library to memory.

2011年6月7日 星期二

Overlay attribute in LDScript

For each section within the OVERLAY, the linker automatically defines two symbols. The symbol __load_start_secname is defined as the starting load address of the section. The symbol __load_stop_secname is defined as the final load address of the section. 
OVERLAY 0x1000 : AT (0x4000)
{
   .text0 { o1/*.o(.text) }
   .text1 { o2/*.o(.text) }
}
This will define both `.text0' and `.text1' to start at address 0x1000. `.text0' will be loaded at address 0x4000, and `.text1' will be loaded immediately after `.text0'. The following symbols will be defined: __load_start_text0__load_stop_text0,__load_start_text1__load_stop_text1.
C code to copy overlay .text1 into the overlay area might look like the following.
extern char __load_start_text1, __load_stop_text1;
memcpy ((char *) 0x1000, &__load_start_text1,
          &__load_stop_text1 - &__load_start_text1);
Note that the OVERLAY command is just syntactic sugar, since everything it does can be done using the more basic commands. The above example could have been written identically as follows.
.text0 0x1000 : AT (0x4000) { o1/*.o(.text) }
__load_start_text0 = LOADADDR (.text0);
__load_stop_text0 = LOADADDR (.text0) + SIZEOF (.text0);
.text1 0x1000 : AT (0x4000 + SIZEOF (.text0)) { o2/*.o(.text) }
__load_start_text1 = LOADADDR (.text1);
__load_stop_text1 = LOADADDR (.text1) + SIZEOF (.text1);
. = 0x1000 + MAX (SIZEOF (.text0), SIZEOF (.text1));
Reference from The GNU linker.

2011年6月4日 星期六

Weak function

From gnu gcc document:
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations.

libweak.c
#include <stdio.h>

void weakfunc() __attribute__((weak));

void weakfunc()
{
    printf ("default weak function\n");

}
main.c
#include <stdio.h>
void weakfunc()
{
    printf ("weak function from main\n");    
}

int main ()
{
    weakfunc();
    return 0;
}
Compile the library and main function.
#gcc -shared -o libweak.so weakfunc.c
#gcc  -o weakfunc{,.c} -lweak -L.
#LD_LIBRARY_PATH=. ./main
weak function from main 
From above, it is very clear that the weak function of the library is replaced.
#objdump -t libweak.so |grep weakfunc
0000046c  w    F .text 00000014   weakfunc
In the library, this function has weak attribute.
#objdump -t main |grep weakfunc
080484e4  g    F .text 00000014   weakfunc
However, this function is presented as  global attribute.

2011年6月2日 星期四

Andriod 專有名詞整理

最近研究了Andriod,整理了一些專有名詞如
IPL (InitialProgramLoader):
Initialize the hardware setting, such as memory, cpu clock , flash, about the development board.
It is similar with the bootloader in the embedded system, like u-boot.

SPL (Second Program Loader):
The main goal is to load system OS to memory.
In addition, some features is provided as the below list.
(1) check hardware, like LCD, led.
(2) search the active partion and load it to memory.
(3) connection with PC and recieve commands from PC host.

HBoot:
This is  HTC’s SPL
fastboot:
Fastboot is protocol used to update the flash filesystem in Android devices from a host over USB.
The command "fastboot.exe" you can run on your host after fastboot has been started on a device connected via USB.
e.g.
$ fastboot erase boot

Andriod Recovery:
The recovey of  the mainstream andriod can provide some options to recovery your systems or factory-to-default, even
though it can load official ROM in the zip file of SD card and recovey the system.
ClockworkMod recovery is one of the widely used custom andriod recovery and it provide more options to recovery unofficial or official
ROM from the zip file of SD card.