asm_dip/toolchain/fasmg.kl0e/examples/x86/include/format/coff.inc
2024-11-24 23:13:28 -05:00

471 lines
10 KiB
C++

macro struct? name
macro end?.struct?!
end namespace
esc end struc
virtual at 0
name name
sizeof.name = $
end virtual
purge end?.struct?
end macro
esc struc name
label . : sizeof.name
namespace .
end macro
struct SCNHDR
s_name db 8 dup ?
s_paddr dd ?
s_vaddr dd ?
s_size dd ?
s_scnptr dd ?
s_relptr dd ?
s_lnnoptr dd ?
s_nreloc dw ?
s_nlnno dw ?
s_flags dd ?
end struct
SCNHSZ = sizeof SCNHDR
struct RELOC
r_vaddr dd ?
r_symndx dd ?
r_type dw ?
end struct
RELSZ = sizeof RELOC
struct SYMENT
e_name db 8 dup ?
virtual at e_name
e_zeroes dd ?
e_offset dd ?
end virtual
e_value dd ?
e_scnum dw ?
e_type dw ?
e_sclass db ?
e_numaux db ?
end struct
SYMESZ = sizeof SYMENT
I386MAGIC = 0x14c
F_RELFLG = 0x0001
F_EXEC = 0x0002
F_LNNO = 0x0004
F_LSYMS = 0x0008
F_AR32WR = 0x0100
STYP_TEXT = 0x0020
STYP_DATA = 0x0040
STYP_BSS = 0x0080
N_UNDEF = 0
N_ABS = -1
N_DEBUG = -2
T_NULL = 0000b
T_VOID = 0001b
T_CHAR = 0010b
T_SHORT = 0011b
T_INT = 0100b
T_LONG = 0101b
T_FLOAT = 0110b
T_DOUBLE = 0111b
T_STRUCT = 1000b
T_UNION = 1001b
T_ENUM = 1010b
T_MOE = 1011b
T_UCHAR = 1100b
T_USHORT = 1101b
T_UINT = 1110b
T_ULONG = 1111b
T_LNGDBL = 01_0000b
DT_NON = 00b
DT_PTR = 01b
DT_FCN = 10b
DT_ARY = 11b
C_NULL = 0
C_AUTO = 1
C_EXT = 2
C_STAT = 3
C_REG = 4
C_EXTDEF = 5
C_LABEL = 6
C_ULABEL = 7
C_MOS = 8
C_ARG = 9
C_STRTAG = 10
C_MOU = 11
C_UNTAG = 12
C_TPDEF = 13
C_USTATIC = 14
C_ENTAG = 15
C_MOE = 16
C_REGPARM = 17
C_FIELD = 18
C_AUTOARG = 19
C_LASTENT = 20
C_BLOCK = 100
C_FCN = 101
C_EOS = 102
C_FILE = 103
C_LINE = 104
C_ALIAS = 105
C_HIDDEN = 106
C_EFCN = 255
RELOC_ADDR32 = 6
RELOC_REL32 = 20
COFF::
namespace COFF
Header:
f_magic dw I386MAGIC
f_nscns dw NUMBER_OF_SECTIONS
f_timdat dd __TIME__
f_symptr dd SYMBOL_TABLE_OFFSET
f_nsyms dd NUMBER_OF_SYMBOLS
f_opthdr dw 0
f_flags dw F_AR32WR + F_LNNO
Sections: db NUMBER_OF_SECTIONS * SCNHSZ dup 0
virtual at 0
symbol_table:: rb NUMBER_OF_SYMBOLS * SYMESZ
end virtual
virtual at 0
string_table:: dd STRING_TABLE_SIZE
STRING_POSITION = $
rb STRING_TABLE_SIZE - $
end virtual
virtual at 0
relocations:: rb NUMBER_OF_RELOCATIONS * RELSZ
end virtual
element relocatable?
macro section_start
local sym
element sym : relocatable * (1+SECTION_INDEX) + SYMBOL_INDEX
SECTION_BASE = sym
org sym
if DEFINED_SECTION | defined DEFAULT_SECTION
store SECTION_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
store C_STAT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
store 1+SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum
SYMBOL_INDEX = SYMBOL_INDEX + 1
end if
end macro
RELOCATION_INDEX = 0
SECTION_INDEX = 0
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
SYMBOL_INDEX = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
SECTION_NAME = '.flat'
SECTION_FLAGS = STYP_TEXT + STYP_DATA
DEFINED_SECTION = 0
section_start
end namespace
macro section?
namespace COFF
SECTION_SIZE = $% - SECTION_OFFSET
if DEFINED_SECTION | SECTION_SIZE > 0
if ~ DEFINED_SECTION
DEFAULT_SECTION := 1
end if
if $%% = SECTION_OFFSET
SECTION_FLAGS = SECTION_FLAGS or STYP_BSS
SECTION_OFFSET = 0
section $
else
UNINITIALIZED_LENGTH = $% - $%%
section $
db UNINITIALIZED_LENGTH dup 0
end if
store SECTION_NAME : 8 at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_name
store SECTION_OFFSET at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_scnptr
store SECTION_SIZE at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_size
store SECTION_FLAGS at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_flags
if RELOCATION_INDEX > SECTION_RELOCATION_INDEX
store RELOCATION_INDEX - SECTION_RELOCATION_INDEX at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_nreloc
store RELOCATIONS_OFFSET + SECTION_RELOCATION_INDEX * RELSZ at COFF:Sections + SECTION_INDEX * SCNHSZ + SCNHDR.s_relptr
end if
SECTION_INDEX = SECTION_INDEX + 1
end if
end namespace
end macro
macro section? declaration*
namespace COFF
section
DEFINED_SECTION = 1
SECTION_FLAGS = 0
SECTION_OFFSET = $%
SECTION_ALIGN = 4
match name attributes, declaration
SECTION_NAME = name
local seq,list
define seq attributes
while 1
match car cdr, seq
define list car
define seq cdr
else
match any, seq
define list any
end match
break
end match
end while
irpv attribute, list
match =code?, attribute
SECTION_FLAGS = SECTION_FLAGS or STYP_TEXT
else match =data?, attribute
SECTION_FLAGS = SECTION_FLAGS or STYP_DATA
else
err 'unknown attribute "',`attribute,'"'
end match
end irpv
else
SECTION_NAME = declaration
end match
section_start
SECTION_RELOCATION_INDEX = RELOCATION_INDEX
end namespace
end macro
calminstruction align? boundary,value:?
check COFF.SECTION_ALIGN mod (boundary) = 0
jyes allowed
err 'section not aligned enough'
exit
allowed:
compute boundary, (boundary-1)-($-COFF.SECTION_BASE+boundary-1) mod boundary
arrange value, =db boundary =dup value
assemble value
end calminstruction
macro public? declaration*
namespace COFF
match =static? value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = C_STAT
else match value =as? str, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = string str
SYMBOL_CLASS = C_EXT
else match =static? value, declaration
SYMBOL_VALUE = value
SYMBOL_NAME = `value
SYMBOL_CLASS = C_STAT
else
SYMBOL_VALUE = declaration
SYMBOL_NAME = `declaration
SYMBOL_CLASS = C_EXT
end match
if SYMBOL_VALUE relativeto 1 elementof SYMBOL_VALUE & 1 elementof (1 metadataof SYMBOL_VALUE) relativeto relocatable & 1 scaleof (1 metadataof SYMBOL_VALUE) > 0
SYMBOL_SECTION_INDEX = 1 scaleof (1 metadataof SYMBOL_VALUE)
SYMBOL_VALUE = SYMBOL_VALUE - 1 elementof SYMBOL_VALUE
else
SYMBOL_SECTION_INDEX = N_ABS
end if
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
end if
store SYMBOL_VALUE at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_value
store SYMBOL_SECTION_INDEX at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_scnum
store SYMBOL_CLASS at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
macro extrn? declaration*
namespace COFF
local sym,psym
element sym : relocatable * (-1) + SYMBOL_INDEX
match str =as? name:size, declaration
label name:size at sym
SYMBOL_NAME = string str
else match name:size, declaration
label name:size at sym
SYMBOL_NAME = `name
else match str =as? name, declaration
label name at sym
SYMBOL_NAME = string str
else
label declaration at sym
SYMBOL_NAME = `declaration
end match
if lengthof SYMBOL_NAME > 8
store 0 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_zeroes
store STRING_POSITION at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_offset
store SYMBOL_NAME : lengthof SYMBOL_NAME at string_table:STRING_POSITION
STRING_POSITION = STRING_POSITION + lengthof SYMBOL_NAME + 1
else
store SYMBOL_NAME : 8 at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_name
end if
store C_EXT at symbol_table : SYMBOL_INDEX * SYMESZ + SYMENT.e_sclass
SYMBOL_INDEX = SYMBOL_INDEX + 1
end namespace
end macro
calminstruction calminstruction?.initsym? var*, val&
publish var, val
end calminstruction
calminstruction calminstruction?.asm? line&
local name, i
initsym name, name.0
match name.i, name
compute i, i+1
arrange name, name.i
publish name, line
arrange line, =assemble name
assemble line
end calminstruction
calminstruction dword? value
compute value, value
check ~ value relativeto 0 & value relativeto 1 elementof value & 1 elementof (1 metadataof value) relativeto COFF.relocatable
jyes addr32
check ~ value relativeto 0 & (value + COFF.SECTION_BASE) relativeto 1 elementof (value + COFF.SECTION_BASE)
jno plain
check 1 elementof (1 metadataof (value + COFF.SECTION_BASE)) relativeto COFF.relocatable
jyes rel32
plain:
emit 4, value
exit
local offset, symndx, type
addr32:
compute symndx, 0 scaleof (1 metadataof value)
compute type, RELOC_ADDR32
jump add_relocation
rel32:
compute value, value + COFF.SECTION_BASE
compute symndx, 0 scaleof (1 metadataof value)
compute type, RELOC_REL32
jump add_relocation
add_relocation:
compute offset, $%
emit 4, 0 scaleof value
check $% > offset
jno done
compute offset, offset - COFF.SECTION_OFFSET
local reloc
compute reloc, COFF.RELOCATION_INDEX * RELSZ
asm store offset at COFF.relocations : reloc + RELOC.r_vaddr
asm store symndx at COFF.relocations : reloc + RELOC.r_symndx
asm store type at COFF.relocations : reloc + RELOC.r_type
compute COFF.RELOCATION_INDEX, COFF.RELOCATION_INDEX + 1
done:
end calminstruction
calminstruction dd? definitions&
local value, n
start:
match value=,definitions, definitions, ()
jyes recognize
match value, definitions
arrange definitions,
recognize:
match n =dup? value, value, ()
jyes duplicate
match ?, value
jyes reserve
call dword, value
next:
match , definitions
jno start
take , definitions
take definitions, definitions
jyes next
exit
reserve:
emit dword
jump next
duplicate:
match (value), value
stack:
check n
jno next
take definitions, value
arrange value, definitions
compute n, n - 1
jump stack
end calminstruction
calminstruction (label) dd? definitions&
local cmd
arrange cmd, =label label : =dword
assemble cmd
arrange cmd, =dd definitions
assemble cmd
end calminstruction
postpone
purge section?
section
namespace COFF
NUMBER_OF_SECTIONS := SECTION_INDEX
STRING_TABLE_SIZE := STRING_POSITION
NUMBER_OF_SYMBOLS := SYMBOL_INDEX
NUMBER_OF_RELOCATIONS := RELOCATION_INDEX
RELOCATIONS_OFFSET = $%
load byte_sequence : NUMBER_OF_RELOCATIONS * RELSZ from relocations:0
db byte_sequence
SYMBOL_TABLE_OFFSET = $%
load byte_sequence : NUMBER_OF_SYMBOLS * SYMESZ from symbol_table:0
db byte_sequence
load byte_sequence : STRING_TABLE_SIZE from string_table:0
db byte_sequence
end namespace
end postpone