COFF: Difference between revisions

5,997 bytes added ,  14 years ago
Added details to Symbol table. Corrected PE link. Added Example section.
[unchecked revision][unchecked revision]
(First draft. Added File Format section with information on each table in the COFF. Symbol Table is unfinished.)
 
(Added details to Symbol table. Corrected PE link. Added Example section.)
Line 15:
Microsoft's Portable Executable (PE/COFF) standard is largely compatible with the COFF specification with a few notable exceptions.
 
Firstly, the COFF File Header is not placed at the beginning of the file if the file is an image (executable) file. In brief, a PE/COFF Image contains a pointer at offset 0x3C which points to the PE header. The COFF File Header immediately follows this PE signature. More information can be found in the [[PE]] article.
 
Secondly, the PE/COFF format also changes some of the COFF magic values (including the File Header one) and assigns them special meanings.
Line 248:
short n_scnum; /* Section Number */
unsigned short n_type; /* Symbol Type */
char n_scalssn_sclass; /* Storage Class */
char n_numaux; /* Auxiliary Count */
}
Line 255:
The Symbol name field stores the name of this symbol if it is eight characters or fewer, otherwise this field contains a pointer into the String table. See the entry on the String table below.
 
Each symbol in the Symbol table can be followed by zero or more Auxiliary entries which provide further information about the symbol. Each of these entries is the same length as the Symbol table entry, but has a different structure depending on the parent Symbol.
The remaining fields in the table need to be considered together because they are interlinked. However, reliable and consistent information on this part of the COFF specification is slightly hard to find.
 
The Section number field n_scnum indicates the Section to which this Symbol belongs. If this value is greater than zero, it refers to a Section in the Section table (hence why the Section table is one-based). I can also take one of the following special values:
 
{| {{wikitable}}
|-
! n_scnum Value
! Meaning
|-
| N_DEBUG (2)
| A debugging symbol. In the example below, information about the file has been put into a symbol like this.
|-
| N_ABS (1)
| An absolute symbol. This means that the value of the n_value field is an absolute value.
|-
| N_UNDEF (0)
| An undefined external symbol
|}
 
The n_value, n_scnum and n_sclass fields in the table need to be considered together because they are interlinked. A number of the more common combinations of these fields is given in the following table. ''(Much of the information in the following table is from observation and not from referenced sources. It is incomplete and may not be accurate.)''
 
{| {{wikitable}}
|-
! n_sclass
! n_scnum
! n_value
! Meaning of n_value
! Typical use
|-
| rowspan="4"| C_EXT (2)
| 0
| 0
|
| Unresolved external Symbol
|-
| 0
| >0
| Size of variable
| Uninitialised global variable (not included in BSS)
|-
| .text
| Any
| Offset into Section
| Function entry point
|-
| .data
| Any
| Offset into Section
| Initialised global variable
|-
| rowspan="3"| C_STAT (3)
| .text, .data, .bss
| 0
|
| Section Symbol indicating start of Section
|-
| .data
| Any
| Offset into Section
| Initialised static variable
|-
| .bss
| Any
| Offset into Section
| Unitialised static variable
|}
 
 
As noted in the table, uninitialised global variables do not seem to be included in the size of the BSS section, only unitialised static variables. If you are loading a COFF file into memory, it may be required to allocate space in addition to the BSS section size to cover these symbols.
 
{{stub}}
Line 270 ⟶ 336:
= File Header.f_symptr + File Header.f_symptr * 18
</pre>
 
Each of the strings in the table are null terminated.
 
The first four bytes of the string table are an integer indicating the overall size in bytes of the string table. Each of the strings in the table are null terminated.
Line 293 ⟶ 357:
 
If the name is more than eight characters, the "zeroes" field (the first four bytes of "name") will be zero. In this case the "offset" field should be used as an offset value into the String table to locate the Symbol or Section name.
 
==Example==
 
This is an example of a Symbol table and the source code to help illustrate some of the information above. (This was compiled with DJGPP.)
 
<pre>
Symbols
e_zeroes e_offset e_value e_scnum e_sclass
e_type e_numaux
[00] 2E 66 69 6C 65 00 00 00 00 00 00 00 FE FF 00 00 67 01 .file.......þÿ..g.
[01] 74 65 73 74 2E 6C 69 62 72 61 72 79 2E 63 00 00 00 00 test.library.c....
[02] 00 00 00 00 04 00 00 00 08 00 00 00 02 00 00 00 03 00 .................. _mStaticIntInit
[03] 00 00 00 00 14 00 00 00 0C 00 00 00 02 00 00 00 03 00 .................. _mStaticShortInit
[04] 00 00 00 00 26 00 00 00 0E 00 00 00 02 00 00 00 03 00 ....&............. _mStaticCharInit
[05] 00 00 00 00 37 00 00 00 00 00 00 00 03 00 00 00 03 00 ....7............. _mStaticInt
[06] 00 00 00 00 43 00 00 00 10 00 00 00 03 00 00 00 03 00 ....C............. _mStaticShort
[07] 00 00 00 00 51 00 00 00 20 00 00 00 03 00 00 00 03 00 ....Q... ......... _mStaticChar
[08] 2E 74 65 78 74 00 00 00 00 00 00 00 01 00 00 00 03 01 .text.............
[09] 33 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 3.................
[0A] 2E 64 61 74 61 00 00 00 00 00 00 00 02 00 00 00 03 01 .data.............
[0B] 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
[0C] 2E 62 73 73 00 00 00 00 00 00 00 00 03 00 00 00 03 01 .bss..............
[0D] 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0.................
[0E] 2E 63 6F 6D 6D 65 6E 74 00 00 00 00 04 00 00 00 03 01 .comment..........
[0F] 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
[10] 00 00 00 00 5E 00 00 00 00 00 00 00 02 00 00 00 02 00 ....^............. _mGlobalIntInit
[11] 00 00 00 00 6E 00 00 00 04 00 00 00 02 00 00 00 02 00 ....n............. _mGlobalShortInit
[12] 00 00 00 00 80 00 00 00 06 00 00 00 02 00 00 00 02 00 ....€............. _mGlobalCharInit
[13] 00 00 00 00 91 00 00 00 00 00 00 00 01 00 00 00 02 00 ....‘............. _TestCall
[14] 5F 54 65 73 74 41 64 64 0A 00 00 00 01 00 00 00 02 00 _TestAdd..........
[15] 00 00 00 00 9B 00 00 00 17 00 00 00 01 00 00 00 02 00 ....›............. _TestSetValue
[16] 00 00 00 00 A9 00 00 00 10 00 00 00 00 00 00 00 02 00 ....©............. _mTestValue
[17] 00 00 00 00 B5 00 00 00 29 00 00 00 01 00 00 00 02 00 ....µ...)......... _TestGetValue
[18] 00 00 00 00 C3 00 00 00 10 00 00 00 00 00 00 00 02 00 ....Ã............. _mGlobalInt
[19] 00 00 00 00 CF 00 00 00 10 00 00 00 00 00 00 00 02 00 ....Ï............. _mGlobalShort
[1A] 00 00 00 00 DD 00 00 00 10 00 00 00 00 00 00 00 02 00 ....Ý............. _mGlobalChar
</pre>
 
<pre>
int mGlobalInt;
short mGlobalShort;
char mGlobalChar;
 
static int mStaticInt;
static short mStaticShort;
static char mStaticChar;
 
unsigned int mGlobalIntInit = 1;
unsigned short mGlobalShortInit = 1;
unsigned char mGlobalCharInit = 1;
 
unsigned static int mStaticIntInit = 1;
unsigned static short mStaticShortInit = 1;
unsigned static char mStaticCharInit = 1;
 
int mTestValue;
 
int TestCall()
{
return 1;
}
 
int TestAdd( int pA, int pB )
{
return pA + pB;
}
 
int TestSetValue( int pValue )
{
mTestValue = pValue;
return mTestValue;
}
 
int TestGetValue()
{
return mTestValue;
}
</pre>
 
As you can see, the static global variables are defined in either section 2 (.data) for the initialised ones, or section 3 (.bss) for the uninitialised, with n_value being an offset into the relevant section. The initialised global variables are also defined in section 2 (.data) with offsets.
 
Note that the uninitialised global variables have a Section number of N_UNDEF (0) and as such are undefined, but as we a non-zero n_value field, we are being told the amount of space that we need to allocate for each symbol (16 bytes for each one in a slightly wasteful overallocation).
 
 
33

edits