COFF line numbers indicate the relationship between code and line-numbers in source files. The Microsoft format for COFF line numbers is similar to standard COFF, but it has been extended to allow a single section to relate to line numbers in multiple source files.
COFF line numbers consist of an array of fixed-length records. The location (file offset) and size of the array are specified in the section header. Each line-number record is of the following format:
Offset | Size | Field | Description |
0 | 4 | Type (*) | Union of two fields: Symbol Table Index and RVA. Whether Symbol Table Index or RVA is used depends on the value of Linenumber. |
4 | 2 | Linenumber | When nonzero, this field specifies a one-based line number. When zero, the Type field is interpreted as a Symbol Table Index for a function. |
The Type field is a union of two four-byte fields, Symbol Table Index, and RVA:
Offset | Size | Field | Description |
0 | 4 | SymbolTableIndex | Used when Linenumber is 0: index to symbol table entry for a function. This format is used to indicate the function that a group of line-number records refer to. |
0 | 4 | VirtualAddress | Used when Linenumber is non-zero: relative virtual address of the executable code that corresponds to the source line indicated. In an object file, this contains the virtual address within the section. |
A line-number record, then, can either set the Linenumber field to 0 and point to a function definition in the Symbol Table, or else it can work as a standard line-number entry by giving a positive integer (line number) and the corresponding address in the object code.
A group of line-number entries always begins with the first format: the index of a function symbol. If this is the first line-number record in the section, then it is also the COMDAT symbol name for the function if the section's COMDAT flag is set. (See Section 5.5.6, "COMDAT Sections.") The function's auxiliary record in the Symbol Table has a Pointer to Linenumbers field that points to this same line-number record.
A record identifying a function is followed by any number of line-number entries that give actual line-number information (Linenumber greater than zero). These entries are one-based, relative to the beginning of the function, and represent every source line in the function except for the first one.
For example, the first line-number record for the following example would specify the ReverseSign function (Symbol Table Index of ReverseSign, Linenumber set to 0). Then records with Linenumber values of 1, 2, and 3 would follow, corresponding to source lines as shown:
// some code precedes ReverseSign function
intReverseSign(int i)
1:{
2:return -1 * i;
3:}