/**/ /*
 * SimpleSection.c
 *
 * Linux:
 *     gcc -c SimpleSection.c
 *
 * Windows:
 *     c1 SimpleSection.c /c /Za
 
*/


int  printf( const   char *  format, );

int  global_init_var  =   86 ;
int  global_uninit_var;

void  func1(  int  i )
{
    printf(
"%d\n",i);
}


int  main( void )
{
    
static int static_var = 85;
    
static int static_var2;

    
int a = 1;
    
int b;

    func1( static_var 
+ static_var2 + a+ b);

    
return a;
}

该笔记是在看该书时的一些记录
zhy@desktop:~/doublemint/test$ ll SimpleSection.o
-rw-r--r-- 1 zhy zhy 1100 2011-07-06 20:32 SimpleSection.o
使用objdump可以查看ELF文件的各个段的信息
-h就是把ELF文件的各个段的基本信息打印出来(-x可以打印更多的信息)
zhy@desktop:~/doublemint/test$ objdump -h SimpleSection.o

SimpleSection.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000005b  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  00000000  00000000  00000090  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  00000000  00000000  00000098  2**2
                  ALLOC
  3 .rodata       00000004  00000000  00000000  00000098  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      00000025  00000000  00000000  0000009c  2**0
                  CONTENTS, READONLY
  5 .note.GNU-stack 00000000  00000000  00000000  000000c1  2**0
                  CONTENTS, READONLY
也可以用size直接查看ELF文件的代码段、数据段和BSS段的长度( dec表示3个段长度的和的十进制,hex表示长度和的16进制)
zhy@desktop:~/doublemint/test$ size SimpleSection.o
   text    data     bss     dec     hex filename
     95       8       4     107      6b SimpleSection.o
不知道这里的text的size为什么是95,0x5b十进制大小应该是91才对阿
zhy@desktop:~/doublemint/test$ objdump -s -d SimpleSection.o

SimpleSection.o:     file format elf32-i386

Contents of section .text:
 0000 5589e583 ec088b45 08894424 04c70424  U......E..D$...$
 0010 00000000 e8fcffff ffc9c38d 4c240483  ............L$..
 0020 e4f0ff71 fc5589e5 5183ec14 c745f801  ...q.U..Q....E..
 0030 0000008b 15040000 00a10000 00008d04  ................
 0040 020345f8 0345f489 0424e8fc ffffff8b  ..E..E...$......
 0050 45f883c4 14595d8d 61fcc3             E....Y].a..    
Contents of section .data:
 0000 56000000 55000000                    V...U...       
Contents of section .rodata:
 0000 25640a00                             %d..           
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520342e  .GCC: (Ubuntu 4.
 0010 332e342d 31307562 756e7475 31292034  3.4-10ubuntu1) 4
 0020 2e332e34 00                          .3.4.          

Disassembly of section .text:

00000000 <func1>:
   0: 55                    push   %ebp
   1: 89 e5                 mov    %esp,%ebp
   3: 83 ec 08              sub    $0x8,%esp
   6: 8b 45 08              mov    0x8(%ebp),%eax
   9: 89 44 24 04           mov    %eax,0x4(%esp)
   d: c7 04 24 00 00 00 00  movl   $0x0,(%esp)
  14: e8 fc ff ff ff        call   15 <func1+0x15>
  19: c9                    leave 
  1a: c3                    ret   

0000001b <main>:
  1b: 8d 4c 24 04           lea    0x4(%esp),%ecx
  1f: 83 e4 f0              and    $0xfffffff0,%esp
  22: ff 71 fc              pushl  -0x4(%ecx)
  25: 55                    push   %ebp
  26: 89 e5                 mov    %esp,%ebp
  28: 51                    push   %ecx
  29: 83 ec 14              sub    $0x14,%esp
  2c: c7 45 f8 01 00 00 00  movl   $0x1,-0x8(%ebp)
  33: 8b 15 04 00 00 00     mov    0x4,%edx
  39: a1 00 00 00 00        mov    0x0,%eax
  3e: 8d 04 02              lea    (%edx,%eax,1),%eax
  41: 03 45 f8              add    -0x8(%ebp),%eax
  44: 03 45 f4              add    -0xc(%ebp),%eax
  47: 89 04 24              mov    %eax,(%esp)
  4a: e8 fc ff ff ff        call   4b <main+0x30>
  4f: 8b 45 f8              mov    -0x8(%ebp),%eax
  52: 83 c4 14              add    $0x14,%esp
  55: 59                    pop    %ecx
  56: 5d                    pop    %ebp
  57: 8d 61 fc              lea    -0x4(%ecx),%esp
  5a: c3                    ret  

可以看到.text段里所包含的正式SimpleSection.c里两个函数func1()和main()的命令。
先说明下,一个十六进制位表示4个二进制位,1个字节为8位,因此,0x55表示一个字节。
.text段的第一个字节"0x55"就是"func1()"函数的第一条"push %ebp"指令,而最后一个字节0xc3正式main()函数的最后一条指令"ret",字节数为91个,即0x5b字节,与前面得到的结果一致。(size结果为95,有待查找)
数据段和只读数据段
.data段保存的是那些已经初始化了的全局静态变量和局部静态变量(值不为0,否则放入.bss段)。SimpleSection.c代码里面一共有两个这样的变量,分别是global_init_varabal与static_var。
这两个变量每个4个字节,一共刚好8个字节,所以".data"段大小为8各字节,对应的十进制大小也即是程序里的变量大小。为什么存放的次序为-x54,0x00,0x00,0x00而不是0x00,0x00,0x00,0x54?这涉及CPU的字节序(Byte Order)的问题,也就是所谓的大端(Big-endian)和小端(Little-endian)的问题。
SimpleSection.c里面我们在调用"printf"的时候,用到了一个字符串常量"%d\n",它是一种只读的数据,所以它被放到了".rodata"段。
%的utf-8编码为0x25
d的utf-8编码为0x64
\n,即LINE FEED(LF) or new line(NL),end of line(EOL)的utf-8编码为0x0a
以\0结尾。
utf-8在这些字符上与ASCII相同,rodata段的4各字节刚好是这个字符串常量的ASCII字节序,最后以\0结尾。
.bss段存放的是未初始化的全局变量和局部静态变量,如上述代码中的global_uninit_var,static_var2就是被存放在.bss段,其实更准确的说法是.bss段为他们预留了空间。
但我们可以看到该段大小只有4个字节,这与global_uninit_var和static_var2的大小的8个字节不符合。
先看下SYMBOL TABLE:
SYMBOL TABLE:
00000000 l    df *ABS* 00000000 SimpleSection.c
00000000 l    d  .text 00000000 .text
00000000 l    d  .data 00000000 .data
00000000 l    d  .bss 00000000 .bss
00000000 l    d  .rodata 00000000 .rodata
00000000 l     O .bss 00000004 static_var2.1202
00000004 l     O .data 00000004 static_var.1201
00000000 l    d  .note.GNU-stack 00000000 .note.GNU-stack
00000000 l    d  .comment 00000000 .comment
00000000 g     O .data 00000004 global_init_var
00000000 g     F .text 0000001b func1
00000000         *UND* 00000000 printf
0000001b g     F .text 00000040 main
00000004       O *COM* 00000004 global_uninit_var
只有static_var2被存放在了.bss段,而global_uninit_var却没有被存放在任何段,只是一个未定义的*COM*。

小的测试
static int x1 = 0;
static int x2 = 1;
x1,x2分别存放在什么段呢?
x1.bss,x2.data

其他段
1 .rodata1
Read only Data,这种段里存放的是只读数据,比如字符串常量、全局const变量。跟“.rodata”一样
2 .comment
存放的是编译器版本信息
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520342e  .GCC: (Ubuntu 4.
 0010 332e342d 31307562 756e7475 31292034  3.4-10ubuntu1) 4
 0020 2e332e34 00                          .3.4.          
例如474343对应的ASCII码值即为GCC
3 .debug
调试信息
4 .dynamic
动态链接信息
5 .hash
符号哈希表
6 .line
调试时的行号表,即源代码行号与编译后指令的对应表
7 .note
额外的编译器信息.比如程序的公司名\发布版本号等
8 .strtab
String Table.字符串表,用于存储ELF文件中用到的各种字符串
9 .symtab
Symbol Table.符号表
10 .shstrtab
Section String Table.段名表
11 .plt .got
动态链接的跳转表和全局入口表
12 .init .fini
程序初始化与终结代码段

扩展:
1.将一个图片转为一个object文件
$ objcopy -I binary -O elf32-i386 -B i386 image.jpg image.o
image.jpg为源图片,执行该语句后当前文件夹下会生成image.o
可是怎么应用呢??????没想清楚......有待查找
2.自定义段
我们在全局变量或函数之前加上"__attribute__((section("name")))"属性就可以把相应的变量或函数放到以"name"作为段名的段中。
例如程序里我添加了这么一句
__attribute__((section("FOO"))) int global = 42;
重新生成.o文件后查看
zhy@desktop:~/doublemint/factory$ objdump -h SimpleSection.o

SimpleSection.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000005b  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  00000000  00000000  00000090  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000004  00000000  00000000  00000098  2**2
                  ALLOC
  3 FOO           00000004  00000000  00000000  00000098  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .rodata       00000004  00000000  00000000  0000009c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .comment      00000025  00000000  00000000  000000a0  2**0
                  CONTENTS, READONLY
  6 .note.GNU-stack 00000000  00000000  00000000  000000c5  2**0
                  CONTENTS, READONLY
可见多了一个FOO段
注意该属性需要应用在全局变量上,如果是局部的,编译时会提示
zhy@desktop:~/doublemint/factory$ gcc -c SimpleSection.c
SimpleSection.c: In function ‘main’:
SimpleSection.c:25: error: section attribute cannot be specified for local variables