gcc attribute 初始化函数列表

gcc的__attribute__编译属性有很多子项,用于改变作用对象的特性。这里讨论section子项的作用。

__attribute__的section子项使用方式为:

?


1

__attribute__((section("section_name")))

其作用是将作用的函数或数据放入指定名为"section_name"的段。

看以下程序片段:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

#include <unistd.h>

#include <stdint.h>

#include <stdio.h>

typedef void (*myown_call)(void);

extern myown_call _myown_start;

extern myown_call _myown_end;

#define _init __attribute__((unused, section(".myown")))

#define func_init(func) myown_call _fn_##func _init = func

static void mspec1(void)

{

        write(1, "aha!\n", 5);

}

static void mspec2(void)

{

        write(1, "aloha!\n", 7);

}

static void mspec3(void)

{

        write(1, "hello!\n", 7);

}

func_init(mspec1);

func_init(mspec2);

func_init(mspec3);

/* exactly like below:

static myown_call mc1  __attribute__((unused, section(".myown"))) = mspec1;

static myown_call mc2  __attribute__((unused, section(".myown"))) = mspec2;

static myown_call mc3  __attribute__((unused, section(".myown"))) = mspec3;

*/

void do_initcalls(void)

{

        myown_call *call_ptr = &_myown_start;

        do {

                fprintf (stderr, "call_ptr: %p\n", call_ptr);

                (*call_ptr)();

                ++call_ptr;

        } while (call_ptr < &_myown_end);

}

int main(void)

{

        do_initcalls();

        return 0;

}

在自定义的.myown段依次填入mspec1/mspec2/mspec3的函数指针,并在do_initcalls中依次调用,从而达到构造并调用初始化函数列表的目的。

两个extern变量:

?


1

2

extern myown_call _myown_start;

extern myown_call _myown_end;

来自ld的链接脚本,可以使用:

?


1

ld --verbose

获取内置lds脚本,并在:

?


1

__bss_start = .;

之前添加以下内容:

?


1

2

3

4

_myown_start = .;

  .myown           : { *(.myown) } = 0x90000000

  _myown_end = .;

  code_segment    : { *(code_segment) }

即定义了.myown段及_myown_start/_myown_end变量(0x90000000这个数值可能需要调整)。

保存修改后的链接器脚本,假设程序为s.c,链接器脚本保存为s.lds,使用以下命令编译:

?


1

gcc s.c -Wl,-Ts.lds

执行结果:

?


1

2

3

4

5

6

7

[[email protected] ]# ./a.out

call_ptr: 0x8049768

aha!

call_ptr: 0x804976c

aloha!

call_ptr: 0x8049770

hello!

Have Fun!

转载:http://my.oschina.net/senmole/blog/50710

时间: 2024-10-17 19:35:16

gcc attribute 初始化函数列表的相关文章

GCC中初始化函数是如何被处理的?

本文译至: http://gcc.gnu.org/onlinedocs/gccint/Initialization.html 如我们所知,在GCC通过给代码追加__attribute__((constructor))和__attribute__((destructor))的方式可以追加初始函数和终止函数, 这篇文章介绍了GCC内部是如何实现上述处理的. 简单的说,就是在最经常的情况下,初始函数会被追加到.ctor section中,.init会调用对应的函数处理这些初始函数.终止情况类似. --

GCC中初始化函数是怎样被处理的?

本文译至: http://gcc.gnu.org/onlinedocs/gccint/Initialization.html 如我们所知,在GCC通过给代码追加__attribute__((constructor))和__attribute__((destructor))的方式能够追加初始函数和终止函数, 这篇文章介绍了GCC内部是怎样实现上述处理的. 简单的说,就是在最常常的情况下,初始函数会被追加到.ctor section中,.init会调用相应的函数处理这些初始函数.终止情况类似. --

c++初始化函数列表

以下三种情况下需要使用初始化成员列表: 一,需要初始化的数据成员是对象的情况: 二,需要初始化const修饰的类成员: 三,需要初始化引用成员数据: 原因: C++可以定义引用类型的成员变量,引用类型的成员变量必须在构造函数的初始化列表中进行初始化.对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起),因此只能用初始化列表对齐进行初始化.成员类型是没有默认构造函数的类.若没有提供显示初始化式,则编译器隐式使用成

LoadRunner中的Web 函数列表

web test LoadRunner fuction_list D:\Program Files (x86)\Mercury Interactive\Mercury LoadRunner\bin>ls -l *.chm -rw-rw-rw-   1 user     group       25893 May 20  2004 FuncRef.chm -rw-rw-rw-   1 user     group       29443 May 20  2004 RPM_Configuration

VC和gcc在保证函数static变量线程安全性上的区别

VC和gcc不同,不能保证静态变量的线程安全性.这就给我们的程序带来了很大的安全隐患和诸多不便.这一点应该引起我们的重视!尤其是在构造函数耗时比较长的时候,很可能给程序带来意想不到的结果.本文从测试代码开始,逐步分析原理,最后给出解决方案. 多线程状态下,VC不能保证在使用函数的静态变量的时候,它的构造函数已经被执行完毕,下面是一段测试代码: class TestStatic { public: TestStatic() { Sleep(1000*10); m_num = 999; } publ

虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout << "A:A" <<endl; } virtual void getb(){ cout << "A:B" <<endl; } }; class B :public A{ public: B(){} virtual void g

第3阶段——内核启动分析之start_kernel初始化函数(5)

内核启动分析之start_kernel初始化函数(init/main.c) stext函数启动内核后,就开始进入start_kernel初始化各个函数, 下面只是浅尝辄止的描述一下函数的功能,很多函数真正理解需要对linux相关体系有很深的了解后才能明白 代码如下: asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __sto

8.1.4 在 F# 中使用函数列表

首先,我们声明一个表示有关客户信息的类型:客户有很多属性,因此,用F# 的记录类型表示最自然的选择,我们在前一章已经看过.清单 8.4 显示了类型声明,和所创建样本客户的代码. 清单 8.4 Client 记录类型和样本值 (F# Interactive) > type Client = { Name : string; Income : int;YearsInJob : int UsesCreditCard : bool;CriminalRecord : bool };; type Clien

linux gcc attribute

_attribute__((error("message"))) Declare that calling the marked function is an error. __attribute__((warning("message"))) Declare that calling the marked function is suspect and should emit a warning. __attribute__((deprecated)) Decla