@@ -943,13 +943,15 @@ void MachObj_term(const(char)[] objfilename)
943943 rel.r_length = 3 ;
944944 rel.r_extern = r.funcsym.Sclass == SC .locstat ? 0 : 1 ;
945945 if (rel.r_extern == 1 )
946- assert (s .Sxtrnnum < nsyms);
946+ assert (r.funcsym .Sxtrnnum < nsyms);
947947 machobj.fobjbuf.write(&rel, rel.sizeof);
948948 foffset += (rel).sizeof;
949949 ++ nreloc;
950950
951951 rel.r_type = ARM64_RELOC_UNSIGNED ;
952- rel.r_symbolnum = s.Sxtrnnum;
952+ if (rel.r_extern == 1 )
953+ rel.r_symbolnum = s.Sxtrnnum;
954+ assert (s.Sxtrnnum < nsyms);
953955 machobj.fobjbuf.write(&rel, rel.sizeof);
954956 foffset += rel.sizeof;
955957 ++ nreloc;
@@ -1735,6 +1737,7 @@ static if (0)
17351737 dysymtab_cmd.nindirectsyms += machobj.indirectsymbuf1.length() / (Symbol* ).sizeof;
17361738 for (int i = 0 ; i < dysymtab_cmd.nindirectsyms; i++ )
17371739 { Symbol* s = (cast (Symbol** )machobj.indirectsymbuf1.buf)[i];
1740+ assert (s.Sxtrnnum < symtab_cmd.nsyms);
17381741 machobj.fobjbuf.write32(s.Sxtrnnum);
17391742 }
17401743 }
@@ -1744,6 +1747,7 @@ static if (0)
17441747 dysymtab_cmd.nindirectsyms += n;
17451748 for (int i = 0 ; i < n; i++ )
17461749 { Symbol* s = (cast (Symbol** )machobj.indirectsymbuf2.buf)[i];
1750+ assert (s.Sxtrnnum < symtab_cmd.nsyms);
17471751 machobj.fobjbuf.write32(s.Sxtrnnum);
17481752 }
17491753 }
@@ -2017,21 +2021,54 @@ int MachObj_comdatsize(Symbol* s, targ_size_t symsize)
20172021@trusted
20182022int MachObj_comdat (Symbol* s)
20192023{
2020- const (char )* sectname;
2021- const (char )* segname;
2022- int p2align;
2023- int flags;
2024-
20252024 // printf("MachObj_comdat(Symbol* %s)\n",s.Sident.ptr);
20262025 // symbol_print(*s);
20272026 // symbol_debug(s);
20282027
2028+ int p2align;
2029+ if (config.target_cpu == TARGET_AArch64 && config.objfmt == OBJ_MACH )
2030+ {
2031+ /* write out the symbol with an n_desc of N_WEAK_DEF.
2032+ */
2033+ if (tyfunc(s.ty()))
2034+ {
2035+ p2align = 2 ; // 4 byte alignment
2036+ s.Sseg = cseg; // functions go into cseg
2037+ }
2038+ else if ((s.ty() & mTYLINK) == mTYweakLinkage)
2039+ {
2040+ s.Sfl = FL .data;
2041+ p2align = 4 ; // 16 byte alignment
2042+ MachObj_data_start(s, 1 << p2align, s.Sseg);
2043+ }
2044+ else if ((s.ty() & mTYLINK) == mTYthread)
2045+ {
2046+ s.Sfl = FL .tlsdata;
2047+ p2align = 4 ;
2048+ if (I64 )
2049+ s.Sseg = objmod.tlsseg().SDseg;
2050+ else
2051+ s.Sseg = getsegment2(machobj.seg_tlscoal_nt, " __tlscoal_nt" , " __DATA" , p2align, S_COALESCED );
2052+ MachObj_data_start(s, 1 << p2align, s.Sseg);
2053+ }
2054+ else
2055+ {
2056+ s.Sfl = FL .data;
2057+ const (char )* sectname = " __datacoal_nt" ;
2058+ const (char )* segname = " __DATA" ;
2059+ p2align = 4 ; // 16 byte alignment
2060+ s.Sseg = getsegment2(machobj.seg_datacoal_nt, sectname, segname, p2align, S_COALESCED );
2061+ MachObj_data_start(s, 1 << p2align, s.Sseg);
2062+ }
2063+ }
2064+ else
2065+ {
20292066 if (tyfunc(s.ty()))
20302067 {
2031- sectname = " __textcoal_nt" ;
2032- segname = " __TEXT" ;
2068+ const ( char ) * sectname = " __textcoal_nt" ;
2069+ const ( char ) * segname = " __TEXT" ;
20332070 p2align = 2 ; // 4 byte alignment
2034- flags = S_COALESCED | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS ;
2071+ int flags = S_COALESCED | S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS ;
20352072 s.Sseg = getsegment2(machobj.seg_textcoal_nt, sectname, segname, p2align, flags);
20362073 }
20372074 else if ((s.ty() & mTYLINK) == mTYweakLinkage)
@@ -2053,11 +2090,12 @@ int MachObj_comdat(Symbol* s)
20532090 else
20542091 {
20552092 s.Sfl = FL .data;
2056- sectname = " __datacoal_nt" ;
2057- segname = " __DATA" ;
2093+ const ( char ) * sectname = " __datacoal_nt" ;
2094+ const ( char ) * segname = " __DATA" ;
20582095 p2align = 4 ; // 16 byte alignment
20592096 s.Sseg = getsegment2(machobj.seg_datacoal_nt, sectname, segname, p2align, S_COALESCED );
20602097 MachObj_data_start(s, 1 << p2align, s.Sseg);
2098+ }
20612099 }
20622100 // find or create new segment
20632101 if (s.Salignment > (1 << p2align))
@@ -2076,6 +2114,37 @@ int MachObj_readonly_comdat(Symbol* s)
20762114 assert (0 );
20772115}
20782116
2117+ /* Arm64 __LD, __compact_unwind section
2118+ Layout:
2119+
2120+ struct compact_unwind_entry_64 {
2121+ uint64_t function_start; // address of function (or range start)
2122+ uint32_t function_length; // length of the function/range
2123+ uint32_t encoding; // 32-bit compact unwind encoding
2124+ uint64_t personality; // pointer to personality function (or 0)
2125+ uint64_t lsda; // pointer to LSDA (language-specific data area) or 0
2126+ };
2127+
2128+ Encoding:
2129+
2130+ Bits Meaning
2131+ 31 IS_NOT_FUNCTION_START
2132+ 30 HAS_LSDA
2133+ 29-28 Personality index (0-3)
2134+ 27-24 Mode
2135+
2136+ arm64 modes (most relevant today):
2137+ 0x02000000 - Frameless (leaf function)
2138+ 0x04000000 - Frame-based (standard stp x29,x30 prologue)
2139+ 0x03000000 - DWARF fallback (points into __eh_frame)
2140+
2141+ # See the raw compact unwind section in an object file
2142+ otool -s __LD __compact_unwind myfile.o -v
2143+
2144+ See the canonical reference for all bitfields in LLVM:
2145+ https://github.com/llvm/llvm-project/blob/main/libunwind/include/mach-o/compact_unwind_encoding.h
2146+ */
2147+
20792148/* **********************************
20802149 * Returns:
20812150 * jump table segment for function s
0 commit comments