一个coff文件格式的观察 
                                      -- 2008-10-4 ljhhh0123

    我采用自底向上的方法来学习coff文件格式,并体会汇编器的行为,
这是一个好方法.用vc6.0sp6编译的lcc将hello1.c
编译成汇编语言,再用masm32v8的汇编器得到的.obj文件,倾印下来,
本文的二进制字节序为little-endlian.

    基本工具:  记事本+WinHex+ida+各种pe&coff学习资料

    基本方法是: 选用winhex打开.obj文件,将内容以二进制方式复制到
记事本,然后就是边看资料,边从winhex上找到位置,边在记事本里断行和加
注释,另外还动用了masm32v8自带的工具dumpbin.exe和ida来找到各部分之
间的分界点.最后的结果如下.

-----可选文件头----

4C01           CPU识别码
0200           段数
43C5E548 日期戳
A6000000    符号表指针
0E000000    符号个数
0000           可选头大小
0000           标志 

----段表--2项--

2E74657874000000 .text\0\0\0\0
00000000               第一个段的位置
00000000               在obj中总为0
2E000000               段大小
64000000               段的起始位置,相对于obj文件
92000000               重定位信息的位置
00000000               行号表的位置
0200                      重定位项目数
0000                      行号个数
20005060               段标志字   IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
                                 | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_CNT_CODE  

2E64617461000000 .data\0\0\0
2E000000               第二个段的位置(第一个段起址加上第一个段的大小)
00000000
00000000
00000000
00000000
00000000
0000
0000
400050C0             IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE  
                     | IMAGE_SCN_ALIGN_16BYTES 
                     | E_SCN_CNT_INITIALIZED_DATA 

----具体的段.text 长度0x2E----

535657558BEC8D3D0000000057E80000
000083C404B8000000008BE55D5F5E5B
C348656C6C6F20576F726C642100

----重定位表----2项----

08000000              段内偏移
0C000000              在符号表内的索引
0600                  属性  重定位目标的32位虚拟地址

0E000000
0B000000              在符号表内的索引
1400                  属性  重定位目标的32位相对偏移
                            

----符号表--0xe项--

2E66696C65000000".file\0\0\0"
00000000
FEFF                     只是个调试符号
0000
67                       源文件符号记录。后面跟着给出文件名的辅助符号表记录。
03                       附加记录数,就是下面三项数据不作具体的符号用.

433A5C444F43554D
457E315C6C6A685C4C4F
43414C537E315C54
656D705C6C6363313435
32312E61736D0000
00000000000000000000

40636F6D702E6964        "@comp.id"
FC201200
FFFF                    这个符号值是个常量.
0000
03                      存储类型为static
00

2E74657874000000       ".text\0\0\0"
00000000
0100                   属于第一个段
0000
03
01                     附加记录1项
2E00000002000000
00000000000000000000

2E64617461000000        ".data\0\0\0"
00000000
0200                   段号,即第二个段
0000
03
01                     附加记录1个
0000000000000000
00000000000000000000

00000000
04000000                以字符串表为开始,偏移四的位置取出.
00000000
0000
2000                    函数类型
02                      external
00

5F5F66746F6C0000   "__ftol\0\0"
00000000
0000
2000                函数类型
02                  external
00
5F70757473000000   "_puts\0\0\0"
00000000
0000
2000                        
02                   external
00
4C33000000000000   "L3"
21000000
0100                 符号所在段的索引
0000
03                   static
00
5F6D61696E000000 "_main\0\0\0"
00000000
0100                 段号
2000                 函数类型
02                   external
00

----字符串表----

0E000000             总长度=本长度占的4字节+以0结尾的字符串的长度(包括0)
5F5F666C747573656400  "__fltused\0"

--------
附录A为开发环境所带的数据结构定义,
附录B为masm32v8下所执行的"dumpbin.exe /all hello1.obj"列印.
附录C为hello1.c文件和lcc生成的汇编语言文件倾印.

注:将些文章内的二进制数据复制到winhex内即可还原成hello1.obj文件.大小为0x1b0.

附录A:
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

typedef struct _IMAGE_RELOCATION {
    union {
        DWORD   VirtualAddress;
        DWORD   RelocCount;             
    };
    DWORD   SymbolTableIndex;
    WORD    Type;
} IMAGE_RELOCATION;

typedef struct _IMAGE_SYMBOL {
    union {
        BYTE    ShortName[8];
        struct {
            DWORD   Short;     // if 0, use LongName
            DWORD   Long;      // offset into string table
        } Name;
        PBYTE   LongName[2];
    } N;
    DWORD   Value;
    SHORT   SectionNumber;
    WORD    Type;
    BYTE    StorageClass;
    BYTE    NumberOfAuxSymbols;
} IMAGE_SYMBOL;

附录B:
Microsoft (R) COFF Binary File Dumper Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file hello1.obj

File Type: COFF OBJECT

FILE HEADER VALUES
             14C machine (i386)
               2 number of sections
        48E5C543 time date stamp Fri Oct 03 15:09:55 2008
              A6 file pointer to symbol table
               E number of symbols
               0 size of optional header
               0 characteristics

SECTION HEADER #1
   .text name
       0 physical address
       0 virtual address
      2E size of raw data
      64 file pointer to raw data
      92 file pointer to relocation table
       0 file pointer to line numbers
       2 number of relocations
       0 number of line numbers
60500020 flags
         Code
         16 byte align
         Execute Read

RAW DATA #1
  00000000: 53 56 57 55 8B EC 8D 3D 00 00 00 00 57 E8 00 00  SVWU...=....W...
  00000010: 00 00 83 C4 04 B8 00 00 00 00 8B E5 5D 5F 5E 5B  ............]_^[
  00000020: C3 48 65 6C 6C 6F 20 57 6F 72 6C 64 21 00        .Hello World!.

RELOCATIONS #1
                                                Symbol    Symbol
 Offset    Type              Applied To         Index     Name
 --------  ----------------  -----------------  --------  ------
 00000008  DIR32                      00000000         C  L3
 0000000E  REL32                      00000000         B  _puts

SECTION HEADER #2
   .data name
      2E physical address
       0 virtual address
       0 size of raw data
       0 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0500040 flags
         Initialized Data
         16 byte align
         Read Write

COFF SYMBOL TABLE
000 00000000 DEBUG  notype       Filename     | .file
    C:\DOCUME~1\ljh\LOCALS~1\Temp\lcc14521.asm
004 001220FC ABS    notype       Static       | @comp.id
005 00000000 SECT1  notype       Static       | .text
    Section length   2E, #relocs    2, #linenums    0, checksum        0
007 00000000 SECT2  notype       Static       | .data
    Section length    0, #relocs    0, #linenums    0, checksum        0
009 00000000 UNDEF  notype ()    External     | __fltused
00A 00000000 UNDEF  notype ()    External     | __ftol
00B 00000000 UNDEF  notype ()    External     | _puts
00C 00000021 SECT1  notype       Static       | L3
00D 00000000 SECT1  notype ()    External     | _main

String Table Size = 0xE bytes

Summary
          0 .data
        2e .text

附录C: hello1.c and hello1.asm

#include "stdio.h" /*借用djgpp的include目录.*/
main()
{puts("Hello World!");
}

.486
.model flat
extrn __fltused:near
extrn __ftol:near
public _main
_TEXT segment
_main:
push ebx
push esi
push edi
push ebp
mov ebp,esp
lea edi,(L3)
push edi
call _puts
add esp,4
mov eax,0
L2:
mov esp,ebp
pop ebp
pop edi
pop esi
pop ebx
ret
_TEXT ends
extrn _puts:near
_TEXT segment
_TEXT ends
_TEXT segment
align 1
L3 label byte
db 72
db 101
db 108
db 108
db 111
db 32
db 87
db 111
db 114
db 108
db 100
db 33
db 0
_TEXT ends
end

----本文完毕----