471 lines
10 KiB
C++
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
|