flat assembler
Message board for the users of flat assembler.

flat assembler > Non-x86 architectures > aarch64 includes for fasmg

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
tthsqe wrote:
The problem is that the interpreter still doesn't like elf_exe_dylink. The first load command needs to start at the file offset zero, otherwise the interpreter blows up. I tried starting before the interpreter path but after the start of the file, and blew up just the same.
Please try with this variant then:
Code:
ELFCLASSNONE = 0 ELFCLASS32 = 1 ELFCLASS64 = 2 ELFDATANONE = 0 ELFDATA2LSB = 1 ELFDATA2MSB = 2 ELFOSABI_NONE = 0 ELFOSABI_HPUX = 1 ELFOSABI_NETBSD = 2 ELFOSABI_GNU = 3 ELFOSABI_LINUX = 3 ELFOSABI_SOLARIS = 6 ELFOSABI_AIX = 7 ELFOSABI_IRIX = 8 ELFOSABI_FREEBSD = 9 ELFOSABI_TRU64 = 10 ELFOSABI_MODESTO = 11 ELFOSABI_OPENBSD = 12 ELFOSABI_OPENVMS = 13 ELFOSABI_NSK = 14 ELFOSABI_AROS = 15 ELFOSABI_FENIXOS = 16 ELFOSABI_CLOUDABI = 17 ELFOSABI_OPENVOS = 18 ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 ET_LOPROC = 0xff00 ET_HIPROC = 0xffff EM_NONE = 0 EM_M32 = 1 EM_SPARC = 2 EM_386 = 3 EM_68K = 4 EM_88K = 5 EM_860 = 7 EM_MIPS = 8 EM_X86_64 = 62 EV_NONE = 0 EV_CURRENT = 1 PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_GNU_EH_FRAME = 0x6474e550 PT_GNU_STACK = 0x6474e551 PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff PF_X = 1 PF_W = 2 PF_R = 4 PF_MASKOS = 0x0ff00000 PF_MASKPROC = 0xf0000000 macro align boundary,value:? db (boundary-1)-($+boundary-1) mod boundary dup value end macro ELF:: namespace ELF if defined Settings.Class CLASS := Settings.Class else CLASS := ELFCLASS32 end if if defined Settings.Machine MACHINE := Settings.Machine else MACHINE := EM_386 end if if defined Settings.ABI ABI := Settings.ABI else ABI := ELFOSABI_NONE end if if defined Settings.BaseAddress BASE_ADDRESS := Settings.BaseAddress else BASE_ADDRESS := 8048000h end if if defined Settings.LoadHeaders LOAD_HEADERS := Settings.LoadHeaders else LOAD_HEADERS := 0 end if Header: e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 e_type dw ET_EXEC e_machine dw MACHINE e_version dd EV_CURRENT if CLASS <> ELFCLASS64 e_entry dd start e_phoff dd ProgramHeader e_shoff dd 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 28h e_shnum dw 0 e_shstrndx dw 0 else e_entry dq start e_phoff dq ProgramHeader e_shoff dq 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 40h e_shnum dw 0 e_shstrndx dw 0 end if ProgramHeader: if CLASS <> ELFCLASS64 p_type dd PT_LOAD p_offset dd 0 p_vaddr dd BASE_ADDRESS p_paddr dd BASE_ADDRESS p_filesz dd 0 p_memsz dd 0 p_flags dd PF_R+PF_W+PF_X p_align dd 1000h else p_type dd PT_LOAD p_flags dd PF_R+PF_W+PF_X p_offset dq 0 p_vaddr dq BASE_ADDRESS p_paddr dq BASE_ADDRESS p_filesz dq 0 p_memsz dq 0 p_align dq 1000h end if SEGMENT_HEADER_LENGTH = $ - ProgramHeader db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0 SEGMENT_INDEX = 0 NEXT_SEGMENT_INDEX = 0 SEGMENT_TYPE = PT_LOAD if LOAD_HEADERS FILE_OFFSET = 0 SEGMENT_BASE = BASE_ADDRESS org SEGMENT_BASE + $% else FILE_OFFSET = $% SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh org SEGMENT_BASE store SEGMENT_BASE at ELF:p_vaddr store SEGMENT_BASE at ELF:p_paddr store FILE_OFFSET at ELF:p_offset end if start: end namespace macro segment? namespace ELF if NEXT_SEGMENT_INDEX = 0 & $ > start NEXT_SEGMENT_INDEX = 1 end if if SEGMENT_TYPE = PT_LOAD RAW_DATA_SIZE = $%% - FILE_OFFSET SEGMENT_SIZE = $ - SEGMENT_BASE store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if NEXT_SEGMENT_INDEX > 0 FILE_OFFSET = $%% align 1000h SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh section SEGMENT_BASE end if else FILE_OFFSET = $% SEGMENT_SIZE = $ - SEGMENT_BASE store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH SEGMENT_BASE = SEGMENT_BASE and not 0FFFh + FILE_OFFSET and 0FFFh if $% > $%% store 0:byte at $-1 end if org SEGMENT_BASE end if end namespace end macro macro segment? attributes* namespace ELF match }, attributes segment restore SEGMENT_TYPE,SEGMENT_FLAGS,SEGMENT_INDEX,SEGMENT_BASE,FILE_OFFSET org SEGMENT_BASE + $% - FILE_OFFSET else local seq,list match { _attributes, attributes define seq _attributes SEGMENT_TYPE =: PT_NULL SEGMENT_FLAGS =: 0 SEGMENT_INDEX =: SEGMENT_INDEX SEGMENT_BASE =: $ FILE_OFFSET =: $% CLOSE_PREVIOUS_SEGMENT = 0 else segment define seq attributes SEGMENT_TYPE = PT_LOAD SEGMENT_FLAGS = 0 CLOSE_PREVIOUS_SEGMENT = 1 end match 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 =readable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R else match =writeable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W else match =executable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X else match =interpreter?, attribute SEGMENT_TYPE = PT_INTERP else match =dynamic?, attribute SEGMENT_TYPE = PT_DYNAMIC else match =note?, attribute SEGMENT_TYPE = PT_NOTE else match =gnustack?, attribute SEGMENT_TYPE = PT_GNU_STACK else match =gnuehframe?, attribute SEGMENT_TYPE = PT_GNU_EH_FRAME else err 'invalid argument' end match end irpv if NEXT_SEGMENT_INDEX = 0 & ( LOAD_HEADERS & SEGMENT_TYPE <> PT_LOAD ) NEXT_SEGMENT_INDEX = 1 FILE_OFFSET = $%% align 1000h SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh section SEGMENT_BASE end if SEGMENT_INDEX = NEXT_SEGMENT_INDEX NEXT_SEGMENT_INDEX = NEXT_SEGMENT_INDEX + 1 store SEGMENT_BASE at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_BASE at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH else store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH end if end match end namespace end macro macro entry? address* namespace ELF store address at ELF:e_entry end namespace end macro postpone purge segment? segment namespace ELF NUMBER_OF_SEGMENTS := NEXT_SEGMENT_INDEX end namespace end postpone
Post 19 Sep 2017, 20:53
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
I have edited the above code, because it had some bugs. I also changed it so it now uses this option:
Code:
ELF.Settings.LoadHeaders = 1
to enable variant where all headers are mapped in a PT_LOAD segment. When this option is not enabled, macros are still fully compatible with fasm 1.

Please let me know if this works.
Post 23 Sep 2017, 21:14
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 714
Alright! works fine now. Would it be correct to say that these changes to the formatting macro are due to bugs in the interpreter (i.e. that none of these requirements are dictated by the elf standard)?
Post 24 Sep 2017, 11:15
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
tthsqe wrote:
Alright! works fine now. Would it be correct to say that these changes to the formatting macro are due to bugs in the interpreter (i.e. that none of these requirements are dictated by the elf standard)?
Yes, these requirements are not dictated by the ELF specification, though the interpreter is free to have an additional assumptions and requirements.

There is, however, an additional problem. The way I implemented subsegments above causes their entries to follow the entry of their "parent" segment in program headers. But the specification states this:
ELF Specification wrote:
PT_INTERP
The array element specifies the location and size of a null-terminated path name to invoke as an interpreter. This segment type is meaningful only for executable files (though it may occur for shared objects); it may not occur more than once in a file. If it is present, it must precede any loadable segment entry.
So the "interpreter" segment, even if mapped as a part of loadable segment, should be defined in headers earlier than its "parent". So I think I should still scrap this variant and work on a different approach. I may get rid of the "subsegment" syntax and instead make the "LoadHeaders" option affect "interpreter" and "dynamic" segments in such way the they overlap the loadable segment that follows.
Post 24 Sep 2017, 13:15
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
Please test this variant. It uses no "subsegment" syntax, only the "LoadHeaders" setting, but the setting automatically overlays "interpreter" and "dynamic" segments onto loadable ones, just like the program headers. And this time it should not violate the ELF specification as long as you ensure that "segment interpreter" is the first one defined.
Code:
ELFCLASSNONE = 0 ELFCLASS32 = 1 ELFCLASS64 = 2 ELFDATANONE = 0 ELFDATA2LSB = 1 ELFDATA2MSB = 2 ELFOSABI_NONE = 0 ELFOSABI_HPUX = 1 ELFOSABI_NETBSD = 2 ELFOSABI_GNU = 3 ELFOSABI_LINUX = 3 ELFOSABI_SOLARIS = 6 ELFOSABI_AIX = 7 ELFOSABI_IRIX = 8 ELFOSABI_FREEBSD = 9 ELFOSABI_TRU64 = 10 ELFOSABI_MODESTO = 11 ELFOSABI_OPENBSD = 12 ELFOSABI_OPENVMS = 13 ELFOSABI_NSK = 14 ELFOSABI_AROS = 15 ELFOSABI_FENIXOS = 16 ELFOSABI_CLOUDABI = 17 ELFOSABI_OPENVOS = 18 ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 ET_LOPROC = 0xff00 ET_HIPROC = 0xffff EM_NONE = 0 EM_M32 = 1 EM_SPARC = 2 EM_386 = 3 EM_68K = 4 EM_88K = 5 EM_860 = 7 EM_MIPS = 8 EM_X86_64 = 62 EV_NONE = 0 EV_CURRENT = 1 PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_GNU_EH_FRAME = 0x6474e550 PT_GNU_STACK = 0x6474e551 PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff PF_X = 1 PF_W = 2 PF_R = 4 PF_MASKOS = 0x0ff00000 PF_MASKPROC = 0xf0000000 macro align boundary,value:? db (boundary-1)-($+boundary-1) mod boundary dup value end macro ELF:: namespace ELF if defined Settings.Class CLASS := Settings.Class else CLASS := ELFCLASS32 end if if defined Settings.Machine MACHINE := Settings.Machine else MACHINE := EM_386 end if if defined Settings.ABI ABI := Settings.ABI else ABI := ELFOSABI_NONE end if if defined Settings.BaseAddress BASE_ADDRESS := Settings.BaseAddress else BASE_ADDRESS := 8048000h end if if defined Settings.LoadHeaders LOAD_HEADERS := Settings.LoadHeaders else LOAD_HEADERS := 0 end if Header: e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 e_type dw ET_EXEC e_machine dw MACHINE e_version dd EV_CURRENT if CLASS <> ELFCLASS64 e_entry dd start e_phoff dd ProgramHeader e_shoff dd 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 28h e_shnum dw 0 e_shstrndx dw 0 else e_entry dq start e_phoff dq ProgramHeader e_shoff dq 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 40h e_shnum dw 0 e_shstrndx dw 0 end if ProgramHeader: if CLASS <> ELFCLASS64 p_type dd PT_LOAD p_offset dd 0 p_vaddr dd BASE_ADDRESS p_paddr dd BASE_ADDRESS p_filesz dd 0 p_memsz dd 0 p_flags dd PF_R+PF_W+PF_X p_align dd 1000h else p_type dd PT_LOAD p_flags dd PF_R+PF_W+PF_X p_offset dq 0 p_vaddr dq BASE_ADDRESS p_paddr dq BASE_ADDRESS p_filesz dq 0 p_memsz dq 0 p_align dq 1000h end if SEGMENT_HEADER_LENGTH = $ - ProgramHeader db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0 HEADERS_OFFSET = 0 HEADERS_BASE = BASE_ADDRESS OVERLAY_HEADERS = LOAD_HEADERS SEGMENT_INDEX = 0 DEFINED_SEGMENT = 0 SEGMENT_TYPE = PT_LOAD FILE_OFFSET = $% SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh org SEGMENT_BASE start: end namespace macro entry? address* namespace ELF store address at ELF:e_entry end namespace end macro macro segment? namespace ELF DEFINED_SEGMENT_SIZE = $ - SEGMENT_BASE if (DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0) & SEGMENT_TYPE = PT_LOAD & OVERLAY_HEADERS FILE_OFFSET = HEADERS_OFFSET SEGMENT_BASE = HEADERS_BASE OVERLAY_HEADERS = 0 end if store SEGMENT_BASE at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_BASE at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD RAW_DATA_SIZE = $%% - FILE_OFFSET SEGMENT_SIZE = $ - SEGMENT_BASE store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 FILE_OFFSET = $%% align 1000h SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh end if section SEGMENT_BASE else if LOAD_HEADERS & OVERLAY_HEADERS = 0 & ( SEGMENT_TYPE = PT_INTERP | SEGMENT_TYPE = PT_DYNAMIC ) OVERLAY_HEADERS = 1 HEADERS_OFFSET = FILE_OFFSET HEADERS_BASE = SEGMENT_BASE end if FILE_OFFSET = $% SEGMENT_SIZE = $ - SEGMENT_BASE store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if OVERLAY_HEADERS = 0 SEGMENT_BASE = SEGMENT_BASE and not 0FFFh + FILE_OFFSET and 0FFFh else SEGMENT_BASE = $ end if if $% > $%% store 0:byte at $-1 end if org SEGMENT_BASE end if if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 SEGMENT_INDEX = SEGMENT_INDEX + 1 end if end namespace end macro macro segment? attributes* namespace ELF segment SEGMENT_TYPE = PT_LOAD SEGMENT_FLAGS = 0 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 =readable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R else match =writeable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W else match =executable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X else match =interpreter?, attribute SEGMENT_TYPE = PT_INTERP else match =dynamic?, attribute SEGMENT_TYPE = PT_DYNAMIC else match =note?, attribute SEGMENT_TYPE = PT_NOTE else match =gnustack?, attribute SEGMENT_TYPE = PT_GNU_STACK else match =gnuehframe?, attribute SEGMENT_TYPE = PT_GNU_EH_FRAME else err 'invalid argument' end match end irpv DEFINED_SEGMENT = 1 store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH else store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH end if end namespace end macro postpone purge segment? segment namespace ELF NUMBER_OF_SEGMENTS := SEGMENT_INDEX end namespace end postpone
Post 24 Sep 2017, 15:00
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
One bug-fix later, I have I included the above in the standard fasmg package. Without "LoadHeaders" set it works in "fasm 1 compatibility" mode still, and with the option set I believe it produces specification-compliant executables that should fulfill these loader requiremenets. But please confirm.
Post 25 Sep 2017, 13:16
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 714
Of course it works.[/code]
Post 28 Sep 2017, 14:58
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
How did the macros turn out? Perhaps I could be of assistance still to solve any problems (like bringing more syntactical compatibility with other ARM assemblers)?

Also, if you would allow this, I would gladly use your macros as a basis to get some ARM examples packaged officially with fasmg (with the original authorship credited in the source).
Post 15 Apr 2018, 16:32
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 714
The macros seem to be fine, and are for the most part compatible with gas syntax. I only developed them to a point were they could create a working exe on my phone. For example, I know of a case of an instruction that does not assemble correctly, so I avoided using this instruction. Smile Also, a majority of invalid instructions are reported as an error, but I cannot guarantee that they all are. I simply have not had the time to test it very thoroughly, and my cross compiler installation just got hosed. The github repo is not going anywhere - why not simply put a link to it?
Post 17 Apr 2018, 08:02
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6876
Location: Kraków, Poland
I have already included a link to it in the official list of fasmg-related resources, but what I had in mind is to make a set of macros that would basically bring the functionality of FASMARM to the new engine, just like my main x86 macros bring compatibility with the original assembler. It seems I have to work on this myself anyway, but what you have already done could serve as a starting point.
Post 17 Apr 2018, 16:43
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 714
Sure, I think you will find the macros to be a good starting point for a more polished assembler for aarch64. I will try to document better how they work and the ones I know to be buggy. I did pass the list of instructions provided by revolution through fasmg and gas and observed a match.

I have no idea about 32bit ARM.
Post 17 Apr 2018, 20:35
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.