5050# define IMAGE_FILE_MACHINE 0x01C0
5151# define RSRC_RELTYPE 7 /* ??? (not tested) */
5252
53+ #elif defined TCC_TARGET_ARM64
54+ # define ADDR3264 ULONGLONG
55+ # define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
56+ # define REL_TYPE_DIRECT R_AARCH64_ABS64
57+ # define R_XXX_THUNKFIX R_AARCH64_ABS64
58+ # define R_XXX_RELATIVE R_AARCH64_RELATIVE
59+ # define R_XXX_FUNCCALL R_AARCH64_CALL26
60+ # define IMAGE_FILE_MACHINE 0xAA64
61+ # define RSRC_RELTYPE 3
62+
5363#elif defined TCC_TARGET_I386
5464# define ADDR3264 DWORD
5565# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
@@ -261,7 +271,7 @@ struct pe_header
261271 BYTE dosstub [0x40 ];
262272 DWORD nt_sig ;
263273 IMAGE_FILE_HEADER filehdr ;
264- #ifdef TCC_TARGET_X86_64
274+ #if defined( TCC_TARGET_X86_64 ) || defined( TCC_TARGET_ARM64 )
265275 IMAGE_OPTIONAL_HEADER64 opthdr ;
266276#else
267277#ifdef _WIN64
@@ -605,11 +615,15 @@ static int pe_write(struct pe_info *pe)
605615 0x00E0 , /*WORD SizeOfOptionalHeader; */
606616 0x010F , /*WORD Characteristics; */
607617#define CHARACTERISTICS_DLL 0x230F
618+ #elif defined(TCC_TARGET_ARM64 )
619+ 0x00F0 , /*WORD SizeOfOptionalHeader; */
620+ 0x022F /*WORD Characteristics; */
621+ #define CHARACTERISTICS_DLL 0x222E
608622#endif
609623},{
610624 /* IMAGE_OPTIONAL_HEADER opthdr */
611625 /* Standard fields. */
612- #ifdef TCC_TARGET_X86_64
626+ #if defined( TCC_TARGET_X86_64 ) || defined ( TCC_TARGET_ARM64 )
613627 0x020B , /*WORD Magic; */
614628#else
615629 0x010B , /*WORD Magic; */
@@ -621,7 +635,7 @@ static int pe_write(struct pe_info *pe)
621635 0x00000000 , /*DWORD SizeOfUninitializedData; */
622636 0x00000000 , /*DWORD AddressOfEntryPoint; */
623637 0x00000000 , /*DWORD BaseOfCode; */
624- #ifndef TCC_TARGET_X86_64
638+ #if ! defined ( TCC_TARGET_X86_64 ) && ! defined ( TCC_TARGET_ARM64 )
625639 0x00000000 , /*DWORD BaseOfData; */
626640#endif
627641 /* NT additional fields. */
@@ -702,7 +716,7 @@ static int pe_write(struct pe_info *pe)
702716 break ;
703717
704718 case sec_data :
705- #ifndef TCC_TARGET_X86_64
719+ #if !defined( TCC_TARGET_X86_64 ) && !defined( TCC_TARGET_ARM64 )
706720 if (!pe_header .opthdr .BaseOfData )
707721 pe_header .opthdr .BaseOfData = addr ;
708722#endif
@@ -1380,13 +1394,21 @@ static int pe_check_symbols(struct pe_info *pe)
13801394 write32le (p + 4 , 0xE59CF000 ); // arm code ldr pc, [ip]
13811395 put_elf_reloc (symtab_section , text_section ,
13821396 offset + 8 , R_XXX_THUNKFIX , is -> iat_index ); // offset to IAT position
1397+ #elif defined TCC_TARGET_ARM64
1398+ p = section_ptr_add (text_section , 16 );
1399+ /* ldr x16, [pc, #8] */
1400+ write32le (p + 0 , 0x58000050 );
1401+ /* br x16 */
1402+ write32le (p + 4 , 0xd61f0200 );
1403+ put_elf_reloc (symtab_section , text_section ,
1404+ offset + 8 , R_XXX_THUNKFIX , is -> iat_index );
13831405#else
13841406 p = section_ptr_add (text_section , 8 );
13851407 write16le (p , 0x25FF );
13861408#ifdef TCC_TARGET_X86_64
13871409 write32le (p + 2 , (DWORD )- 4 );
13881410#endif
1389- put_elf_reloc (symtab_section , text_section ,
1411+ put_elf_reloc (symtab_section , text_section ,
13901412 offset + 2 , R_XXX_THUNKFIX , is -> iat_index );
13911413#endif
13921414 }
@@ -1893,9 +1915,75 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
18931915 for (n = o + sizeof * p ; o < n ; o += sizeof p -> BeginAddress )
18941916 put_elf_reloc (symtab_section , pd , o , R_XXX_RELATIVE , s1 -> uw_sym );
18951917}
1918+ #elif defined TCC_TARGET_ARM64
1919+ /* ARM64 unwind codes:
1920+ save_fplr_x: 10iiiiii - stp x29,lr,[sp,#-(i+1)*8]!
1921+ set_fp: 11100001 - mov x29,sp
1922+ alloc_s: 000iiiii - sub sp,sp,#i*16 (up to 496 bytes)
1923+ alloc_m: 11000iii xxxxxxxx - sub sp,sp,#X*16 (up to 32KB)
1924+ end: 11100100 - end of unwind codes
1925+ */
1926+ static unsigned pe_add_uwwind_info (TCCState * s1 )
1927+ {
1928+ if (NULL == s1 -> uw_pdata ) {
1929+ s1 -> uw_pdata = find_section (s1 , ".pdata" );
1930+ s1 -> uw_pdata -> sh_addralign = 4 ;
1931+ }
1932+ if (0 == s1 -> uw_sym )
1933+ s1 -> uw_sym = put_elf_sym (symtab_section , 0 , 0 , 0 , 0 ,
1934+ text_section -> sh_num , ".uw_base" );
1935+ if (0 == s1 -> uw_offs ) {
1936+ /* TCC ARM64 prolog: stp x29,lr,[sp,#-224]!; mov x29,sp; sub sp,sp,#N
1937+ Unwind codes (reverse order): alloc_s, set_fp, save_fplr_x, end */
1938+ static const unsigned char uw_info [] = {
1939+ /* .xdata header word 0:
1940+ FunctionLength[17:0]=0 (patched), Vers[1:0]=0, X=0, E=1,
1941+ EpilogCount[4:0]=0, CodeWords[4:0]=1 */
1942+ 0x00 , 0x00 , 0x00 , 0x01 ,
1943+ /* Unwind codes (4 bytes, padded): */
1944+ 0xE1 , /* set_fp: mov x29,sp */
1945+ 0x9B , /* save_fplr_x: stp x29,lr,[sp,#-224]! (224/8-1=27=0x1B) */
1946+ 0xE4 , /* end */
1947+ 0xE3 , /* nop (padding) */
1948+ };
1949+
1950+ Section * s = text_section ;
1951+ unsigned char * p ;
1952+
1953+ section_ptr_add (s , - s -> data_offset & 3 ); /* align */
1954+ s1 -> uw_offs = s -> data_offset ;
1955+ p = section_ptr_add (s , sizeof uw_info );
1956+ memcpy (p , uw_info , sizeof uw_info );
1957+ }
1958+ return s1 -> uw_offs ;
1959+ }
1960+
1961+ ST_FUNC void pe_add_unwind_data (unsigned start , unsigned end , unsigned stack )
1962+ {
1963+ TCCState * s1 = tcc_state ;
1964+ Section * pd ;
1965+ unsigned o , n , d ;
1966+ struct {
1967+ DWORD BeginAddress ;
1968+ DWORD EndAddress ;
1969+ DWORD UnwindData ;
1970+ } * p ;
1971+
1972+ d = pe_add_uwwind_info (s1 );
1973+ pd = s1 -> uw_pdata ;
1974+ o = pd -> data_offset ;
1975+ p = section_ptr_add (pd , sizeof * p );
1976+
1977+ p -> BeginAddress = start ;
1978+ p -> EndAddress = end ;
1979+ p -> UnwindData = d ;
1980+
1981+ for (n = o + sizeof * p ; o < n ; o += sizeof p -> BeginAddress )
1982+ put_elf_reloc (symtab_section , pd , o , R_XXX_RELATIVE , s1 -> uw_sym );
1983+ }
18961984#endif
18971985/* ------------------------------------------------------------- */
1898- #ifdef TCC_TARGET_X86_64
1986+ #if defined( TCC_TARGET_X86_64 ) || defined( TCC_TARGET_ARM64 )
18991987#define PE_STDSYM (n ,s ) n
19001988#else
19011989#define PE_STDSYM (n ,s ) "_" n s
@@ -1991,7 +2079,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
19912079ST_FUNC int pe_setsubsy (TCCState * s1 , const char * arg )
19922080{
19932081 static const struct subsy { const char * p ; int v ; } x [] = {
1994- #if defined(TCC_TARGET_I386 ) || defined (TCC_TARGET_X86_64 )
2082+ #if defined(TCC_TARGET_I386 ) || defined (TCC_TARGET_X86_64 ) || defined ( TCC_TARGET_ARM64 )
19952083 { "native" , 1 },
19962084 { "gui" , 2 },
19972085 { "windows" , 2 },
@@ -2098,7 +2186,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
20982186 pe .thunk = data_section ;
20992187 pe_build_imports (& pe );
21002188 s1 -> run_main = pe .start_symbol ;
2101- #ifdef TCC_TARGET_X86_64
2189+ #if defined( TCC_TARGET_X86_64 ) || defined( TCC_TARGET_ARM64 )
21022190 s1 -> uw_pdata = find_section (s1 , ".pdata" );
21032191#endif
21042192#endif
0 commit comments