flat assembler
Message board for the users of flat assembler.

Index > Non-x86 architectures > aarch64 includes for fasmg

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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 19 Sep 2017, 20:53
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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 23 Sep 2017, 21:14
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: 767
tthsqe 24 Sep 2017, 11:15
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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 24 Sep 2017, 13:15
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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 24 Sep 2017, 15:00
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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 25 Sep 2017, 13:16
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: 767
tthsqe 28 Sep 2017, 14:58
Of course it works.[/code]
Post 28 Sep 2017, 14:58
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 15 Apr 2018, 16:32
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: 767
tthsqe 17 Apr 2018, 08:02
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



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 17 Apr 2018, 16:43
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: 767
tthsqe 17 Apr 2018, 20:35
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
alorent



Joined: 05 Dec 2005
Posts: 221
alorent 12 Apr 2023, 02:09
Hi,

First of all, thanks tthsq for the great support of arm64 on FASMG.

I'm trying to read the flags registers, so I use the following instruction:

Code:
mrs x0, NZCV    


But it looks like the instruction is not recognized. I have tried with upper/lowercases, etc.

Thanks!
Post 12 Apr 2023, 02:09
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8358
Location: Kraków, Poland
Tomasz Grysztar 12 Apr 2023, 11:23
Looking at the source, the implementation of this instruction seems to cover just a couple of cases:
Code:
macro mrs a*, b*
    aarch64.parse_operand @op0, a
    match =actlr_el1?, b
        dd 0xd5381020 + (@op0.data shl 0)
    else match =vttbr_el2?, b
        dd 0xd53c2100 + (@op0.data shl 0)
    else match =spsel?, b
        dd 0xd5384200 + (@op0.data shl 0)
    else match =s3_2_c3_c4_5?, b
        dd 0xd53a34a0 + (@op0.data shl 0)
    else
        err 'invalid operand'
    end match
end macro    
One of the intended advantages of having an instruction set implemented as a header set for fasmg is that at least you can more easily correct/expand it yourself when need arises. You could add another case there:
Code:
    else match =nzcv?, b
        dd 0xd53b4200 + (@op0.data shl 0)    
(I borrowed the opcode here from FASMARM.)
You could also change it into something faster and more expandable:
Code:
namespace aarch64.mrs
    actlr_el1? = 0xd5381020
    vttbr_el2? = 0xd53c2100
    spsel? = 0xd5384200
    s3_2_c3_c4_5? = 0xd53a34a0
    nzcv? = 0xd53b4200
end namespace

macro mrs a*, b*
    aarch64.parse_operand @op0, a
    if defined aarch64.mrs.b
       dd aarch64.mrs.b + (@op0.data shl 0)
    else
        err 'invalid operand'
    end if
end macro    
Of course the best would be to rewrite it with CALM, but that's a bit more work.

I had similarly encountered little issues with these headers, even when I was preparing the simplest example for Windows on ARM64, and I just quickly corrected them in the headers so that I could keep going (you can find that version of aarch64.inc in the package that comes with my executable formats tutorial, which now includes some ARM64 examples as well). Unfortunately I have not been able to get a response from tthsq with regards to further development of these includes, perhaps we need to take it from here.
Post 12 Apr 2023, 11:23
View user's profile Send private message Visit poster's website Reply with quote
alorent



Joined: 05 Dec 2005
Posts: 221
alorent 12 Apr 2023, 15:22
Thanks a lot Tomasz! I took your modified "aarch64.inc" with the LDP fix and also added the "nzcv" extension as you proposed.

It looks the same happens for the "msr" instruction. I have modified the aarch64.inc file:

Code:
macro msr a*, b*
    aarch64.parse_operand @op0, b
    match =actlr_el1?, a
        dd 0xd5181020 + (@op0.data shl 0)
    else match =vttbr_el2?, a
        dd 0xd51c2100 + (@op0.data shl 0)
    else match =spsel?, a
        dd 0xd5184200 + (@op0.data shl 0)
    else match =s3_2_c3_c4_5?, a
        dd 0xd51a34a0 + (@op0.data shl 0)
    else match =nzcv?, a
        dd 0xd51b4200 + (@op0.data shl 0)
    else
        err 'invalid operand'
    end match
end macro
    


Thanks!
Post 12 Apr 2023, 15:22
View user's profile Send private message Reply with quote
alorent



Joined: 05 Dec 2005
Posts: 221
alorent 13 Apr 2023, 14:33
Using the "aarch.inc" or FASMARM, I can assembly the following:

Code:
add x1, sp, x1    


but it produces error when I assemble:

Code:
add x1, x1, sp    


Is that a bug in the include or FASMARM? Or maybe I'm writing a wrong instruction? (though the two above should be equivalent)

Thanks!
Post 13 Apr 2023, 14:33
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20445
Location: In your JS exploiting you and your system
revolution 13 Apr 2023, 16:40
Technically "add x1, x1, sp" is not valid because sp can't be encoded as the third register, it would encode xzr instead.

But you are correct, the "add x1, sp, x1" is 100% equivalent. It would be good if fasmarm could swap the registers automatically, as it does for arm32.
Post 13 Apr 2023, 16:40
View user's profile Send private message Visit poster's website Reply with quote
alorent



Joined: 05 Dec 2005
Posts: 221
alorent 14 Apr 2023, 05:52
Thanks revolution! Appreciated!
Post 14 Apr 2023, 05:52
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 767
tthsqe 16 May 2023, 23:43
I should have given the green light. Let's see aarch64 in the official.
Post 16 May 2023, 23:43
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 © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.