3030import java .util .Set ;
3131import java .util .TreeMap ;
3232
33+ import org .graalvm .compiler .core .common .NumUtil ;
34+
3335import com .oracle .objectfile .BuildDependency ;
3436import com .oracle .objectfile .LayoutDecisionMap ;
3537import com .oracle .objectfile .ObjectFile ;
4749class MachORelocationElement extends MachOObjectFile .LinkEditElement {
4850 /*
4951 * We are a bunch of RelocationInfo.Structs grouped by relocated section, ordered by the offset
50- * within the section.
52+ * within the section. Note also that, when present, an explicit addend for a given offset must
53+ * be stored immediately before its corresponding record.
5154 */
5255
5356 private static int compareSectionThenOffset (MachORelocationInfo p , MachORelocationInfo q ) {
5457 if (!p .getRelocatedSection ().equals (q .getRelocatedSection ())) {
5558 return p .getRelocatedSection ().hashCode () - q .getRelocatedSection ().hashCode ();
5659 }
57- return Math .toIntExact (p .getOffset () - q .getOffset ());
60+ if (p .getOffset () != q .getOffset ()) {
61+ return Math .toIntExact (p .getOffset () - q .getOffset ());
62+ }
63+
64+ assert !(p .isAddendKind () && q .isAddendKind ()) : "two addends for same relocation" ;
65+ // reverse arguments since want the addend kind first
66+ return Boolean .compare (q .isAddendKind (), p .isAddendKind ());
5867 }
5968
6069 private Map <MachORelocationInfo , MachORelocationInfo > infos = new TreeMap <>(MachORelocationElement ::compareSectionThenOffset );
@@ -116,68 +125,113 @@ public int countFor(MachOSection s) {
116125 }
117126}
118127
128+ interface MachORelocationType {
129+ boolean isPCRelative ();
130+
131+ int getValue ();
132+ }
133+
119134/**
120- * These are defined as an enum in
121- * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173
135+ * These are defined as an enum in <a href=
136+ * " https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173">EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173</a>
122137 * which we reproduce. Of course, take care to preserve the order!
123138 *
124- * For examples of how these symbols are used, see the linked file above and
125- * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h.
139+ * For examples of how these symbols are used, see the linked file above and <a href=
140+ * " https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h">EXTERNAL_HEADERS/mach-o/reloc.h</a> .
126141 */
127- enum X86_64Reloc {
128- UNSIGNED , // for absolute addresses
129- SIGNED , // for signed 32-bit displacement
130- BRANCH , // a CALL/JMP instruction with 32-bit displacement
131- GOT_LOAD , // a MOVQ load of a GOT entry
132- GOT , // other GOT references
133- SUBTRACTOR , // must be followed by a X86_64_RELOC_UNSIGNED
134- SIGNED_1 , // for signed 32-bit displacement with a -1 addend
135- SIGNED_2 , // for signed 32-bit displacement with a -2 addend
136- SIGNED_4 , // for signed 32-bit displacement with a -4 addend
137- TLV ; // for thread local variables
142+ enum X86_64Reloc implements MachORelocationType {
143+ UNSIGNED (0 ), // for absolute addresses
144+ SIGNED (1 , true ), // for signed 32-bit displacement
145+ BRANCH (2 ), // a CALL/JMP instruction with 32-bit displacement
146+ GOT_LOAD (3 ), // a MOVQ load of a GOT entry
147+ GOT (4 ), // other GOT references
148+ SUBTRACTOR (5 ), // must be followed by a X86_64_RELOC_UNSIGNED
149+ SIGNED_1 (6 , true ), // for signed 32-bit displacement with a -1 addend
150+ SIGNED_2 (7 , true ), // for signed 32-bit displacement with a -2 addend
151+ SIGNED_4 (8 , true ), // for signed 32-bit displacement with a -4 addend
152+ TLV (9 ); // for thread local variables
153+
154+ private final boolean pcRelative ;
155+ private final int value ;
138156
157+ X86_64Reloc (int value ) {
158+ this .value = value ;
159+ pcRelative = false ;
160+ }
161+
162+ X86_64Reloc (int value , boolean pcRelative ) {
163+ this .value = value ;
164+ this .pcRelative = pcRelative ;
165+ }
166+
167+ @ Override
168+ public boolean isPCRelative () {
169+ return pcRelative ;
170+ }
171+
172+ @ Override
139173 public int getValue () {
140- return ordinal () ;
174+ return value ;
141175 }
142176}
143177
144178/**
145- * These are defined as an enum in
146- * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26,
179+ * These are defined as an enum in <a href=
180+ * " https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26">EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26</a> ,
147181 * which we reproduce. Of course, take care to preserve the order!
148182 *
149- * For examples of how these symbols are used, see
150- * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm/reloc.h
151- * (for AArch32 information, but does provide some insight) and
152- * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h.
183+ * For examples of how these symbols are used, see <a href=
184+ * " https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm/reloc.h">EXTERNAL_HEADERS/mach-o/arm/reloc.h</a>
185+ * (for AArch32 information, but does provide some insight) and <a href=
186+ * " https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h">EXTERNAL_HEADERS/mach-o/reloc.h</a> .
153187 */
154- enum ARM64Reloc {
155- UNSIGNED , // for pointers
156- SUBTRACTOR , // must be followed by a ARM64_RELOC_UNSIGNED
157- BRANCH26 , // a B/BL instruction with 26-bit displacement
158- PAGE21 , // pc-rel distance to page of target
159- PAGEOFF12 , // offset within page, scaled by r_length
160- GOT_LOAD_PAGE21 , // pc-rel distance to page of GOT slot
161- GOT_LOAD_PAGEOFF12 , // offset within page of GOT slot, scaled by r_length
162- POINTER_TO_GOT , // for pointers to GOT slots
163- TLVP_LOAD_PAGE21 , // pc-rel distance to page of TLVP slot
164- TLVP_LOAD_PAGEOFF12 , // offset within page of TLVP slot, scaled by r_length
165- ADDEND ; // must be followed by PAGE21 or PAGEOFF12
188+ enum ARM64Reloc implements MachORelocationType {
189+ UNSIGNED (0 ), // for pointers
190+ SUBTRACTOR (1 ), // must be followed by a ARM64_RELOC_UNSIGNED
191+ BRANCH26 (2 ), // a B/BL instruction with 26-bit displacement
192+ PAGE21 (3 , true ), // pc-rel distance to page of target
193+ PAGEOFF12 (4 ), // offset within page, scaled by r_length
194+ GOT_LOAD_PAGE21 (5 , true ), // pc-rel distance to page of GOT slot
195+ GOT_LOAD_PAGEOFF12 (6 ), // offset within page of GOT slot, scaled by r_length
196+ POINTER_TO_GOT (7 ), // for pointers to GOT slots
197+ TLVP_LOAD_PAGE21 (8 , true ), // pc-rel distance to page of TLVP slot
198+ TLVP_LOAD_PAGEOFF12 (9 ), // offset within page of TLVP slot, scaled by r_length
199+ ADDEND (10 ); // must be followed by PAGE21 or PAGEOFF12
200+
201+ private final boolean pcRelative ;
202+ private final int value ;
203+
204+ ARM64Reloc (int value ) {
205+ this .value = value ;
206+ pcRelative = false ;
207+ }
208+
209+ ARM64Reloc (int value , boolean pcRelative ) {
210+ this .value = value ;
211+ this .pcRelative = pcRelative ;
212+ }
166213
214+ @ Override
215+ public boolean isPCRelative () {
216+ return pcRelative ;
217+ }
218+
219+ @ Override
167220 public int getValue () {
168- return ordinal () ;
221+ return value ;
169222 }
170223}
171224
172225final class MachORelocationInfo implements RelocationRecord , RelocationMethod {
173226
174227 private final MachORelocationElement containingElement ;
175228 private final MachOSection relocatedSection ;
176- private final RelocationKind kind ;
229+ private final MachORelocationType kind ;
177230 private final int sectionOffset ;
178231 private final Symbol sym ;
179232 private final MachOSection targetSection ;
180233 private final byte log2length ;
234+ private final int addend ;
181235
182236 /**
183237 * Construct a relocation record.
@@ -189,7 +243,8 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod {
189243 * @param kind the kind of relocation to perform at the relocation site
190244 * @param symbolName the symbol against which to relocate
191245 */
192- MachORelocationInfo (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , int requestedLength , RelocationKind kind , String symbolName , boolean asLocalReloc ) {
246+ private MachORelocationInfo (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , int requestedLength , MachORelocationType kind , String symbolName ,
247+ boolean asLocalReloc , int addend ) {
193248 this .containingElement = containingElement ;
194249 this .relocatedSection = relocatedSection ;
195250 this .sectionOffset = offset ; // gets turned into a vaddr on write-out
@@ -215,6 +270,20 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod {
215270 // if the symbol is defined in the same file, i.e. locally, we have a target section
216271 assert !asLocalReloc || this .sym .isDefined ();
217272 this .targetSection = asLocalReloc ? (MachOSection ) this .sym .getDefinedSection () : null ;
273+ this .addend = addend ;
274+ }
275+
276+ /* Creates an ARM64_RELOC_ADDEND relocation type. */
277+ static MachORelocationInfo createARM64RelocAddend (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , String symbolName , long addend ) {
278+ int length = 4 ; // This relocation record holds the addend for a 4-byte AArch64 instruction
279+ return new MachORelocationInfo (containingElement , relocatedSection , offset , length , ARM64Reloc .ADDEND , symbolName , false , Math .toIntExact (addend ));
280+ }
281+
282+ static MachORelocationInfo createRelocation (MachORelocationElement containingElement , MachOSection relocatedSection , int offset , RelocationKind kind , String symbolName ) {
283+ int length = ObjectFile .RelocationKind .getRelocationSize (kind );
284+ MachORelocationType type = getMachORelocationType (relocatedSection , kind );
285+ return new MachORelocationInfo (containingElement , relocatedSection , offset , length , type , symbolName , false , 0 );
286+
218287 }
219288
220289 public static int getEncodedSize () {
@@ -225,7 +294,12 @@ public void write(OutputAssembler oa, @SuppressWarnings("unused") Map<Element, L
225294 /* We need to convert in-section offsets to vaddrs if we are writing dynamic object. */
226295 // "extern" means symbolNum is a symbol not a section number
227296 int symbolNum ;
228- if (isExtern ()) {
297+ if (isAddendKind ()) {
298+ assert !isExtern () : "addend must be encoded as a local" ;
299+ assert NumUtil .isSignedNbit (24 , addend );
300+ // store addend as symbolnum
301+ symbolNum = addend ;
302+ } else if (isExtern ()) {
229303 // we're non-local, so use a symbol
230304 symbolNum = relocatedSection .getOwner ().getSymbolTable ().indexOf (sym );
231305 } else {
@@ -249,11 +323,11 @@ public void write(OutputAssembler oa, @SuppressWarnings("unused") Map<Element, L
249323 */
250324 int remainingWord = 0 ;
251325 //@formatter:off
252- remainingWord |= symbolNum & 0x00ffffff ;
253- remainingWord |= isPCRelative () ? ( 1 << 24 ) : 0 ;
254- remainingWord |= (log2length & 0x3 ) << 25 ;
255- remainingWord |= isExtern () ? ( 1 << 27 ) : 0 ;
256- remainingWord |= ( getMachORelocationType () & 0xf ) << 28 ;
326+ remainingWord |= symbolNum & 0x00ffffff ;
327+ remainingWord |= ( kind . isPCRelative () ? 1 : 0 ) << 24 ;
328+ remainingWord |= (log2length & 0x3 ) << 25 ;
329+ remainingWord |= ( isExtern () ? 1 : 0 ) << 27 ;
330+ remainingWord |= ( kind . getValue () & 0xf ) << 28 ;
257331 //@formatter:on
258332 oa .write4Byte (remainingWord );
259333 assert oa .pos () - startPos == 8 ; // check we wrote how much we expected
@@ -271,42 +345,41 @@ public Symbol getReferencedSymbol() {
271345 return sym ;
272346 }
273347
348+ public boolean isAddendKind () {
349+ return kind == ARM64Reloc .ADDEND ;
350+ }
351+
352+ public long getAddend () {
353+ return addend ;
354+ }
355+
274356 public MachOSection getRelocatedSection () {
275357 return relocatedSection ;
276358 }
277359
278360 private boolean isExtern () {
279- // we record localness by grabbing the target section (see constructor)
280- return targetSection == null ;
281- }
282-
283- private boolean isPCRelative () {
284- switch (kind ) {
285- case PC_RELATIVE_1 :
286- case PC_RELATIVE_2 :
287- case PC_RELATIVE_4 :
288- case PC_RELATIVE_8 :
289- case AARCH64_R_AARCH64_ADR_PREL_PG_HI21 :
290- return true ;
291- default :
292- return false ;
293- }
361+ /*
362+ * We record localness by grabbing the target section (see constructor). Note that the
363+ * addend kind is not considered an extern.
364+ */
365+
366+ return targetSection == null && !isAddendKind ();
294367 }
295368
296- private int getMachORelocationType () {
297- switch (getRelocatedSection () .getOwner ().cpuType ) {
369+ private static MachORelocationType getMachORelocationType (MachOSection relocatedSection , RelocationKind kind ) {
370+ switch (relocatedSection .getOwner ().cpuType ) {
298371 case X86_64 :
299372 switch (kind ) {
300373 case DIRECT_1 :
301374 case DIRECT_2 :
302375 case DIRECT_4 :
303376 case DIRECT_8 :
304- return X86_64Reloc .UNSIGNED . getValue () ;
377+ return X86_64Reloc .UNSIGNED ;
305378 case PC_RELATIVE_1 :
306379 case PC_RELATIVE_2 :
307380 case PC_RELATIVE_4 :
308381 case PC_RELATIVE_8 :
309- return X86_64Reloc .SIGNED . getValue () ;
382+ return X86_64Reloc .SIGNED ;
310383 default :
311384 case UNKNOWN :
312385 throw new IllegalArgumentException ("unknown relocation kind: " + kind );
@@ -317,15 +390,15 @@ private int getMachORelocationType() {
317390 case DIRECT_2 :
318391 case DIRECT_4 :
319392 case DIRECT_8 :
320- return ARM64Reloc .UNSIGNED . getValue () ;
393+ return ARM64Reloc .UNSIGNED ;
321394 case AARCH64_R_AARCH64_ADR_PREL_PG_HI21 :
322- return ARM64Reloc .PAGE21 . getValue () ;
395+ return ARM64Reloc .PAGE21 ;
323396 case AARCH64_R_AARCH64_LDST64_ABS_LO12_NC :
324397 case AARCH64_R_AARCH64_LDST32_ABS_LO12_NC :
325398 case AARCH64_R_AARCH64_LDST16_ABS_LO12_NC :
326399 case AARCH64_R_AARCH64_LDST8_ABS_LO12_NC :
327400 case AARCH64_R_AARCH64_ADD_ABS_LO12_NC :
328- return ARM64Reloc .PAGEOFF12 . getValue () ;
401+ return ARM64Reloc .PAGEOFF12 ;
329402 default :
330403 case UNKNOWN :
331404 throw new IllegalArgumentException ("unknown relocation kind: " + kind );
@@ -342,7 +415,7 @@ public boolean equals(Object obj) {
342415 }
343416 if (obj != null && getClass () == obj .getClass ()) {
344417 MachORelocationInfo other = (MachORelocationInfo ) obj ;
345- return sectionOffset == other .sectionOffset && log2length == other .log2length && Objects .equals (containingElement , other .containingElement ) &&
418+ return sectionOffset == other .sectionOffset && log2length == other .log2length && Objects .equals (containingElement , other .containingElement ) && addend == other . addend &&
346419 Objects .equals (getRelocatedSection (), other .getRelocatedSection ()) && kind == other .kind &&
347420 Objects .equals (sym , other .sym ) && Objects .equals (targetSection , other .targetSection );
348421 }
@@ -351,7 +424,6 @@ public boolean equals(Object obj) {
351424
352425 @ Override
353426 public int hashCode () {
354- return (((((containingElement .hashCode () * 31 + relocatedSection .hashCode ()) * 31 + kind .hashCode ()) * 31 +
355- sectionOffset ) * 31 + sym .hashCode ()) * 31 + targetSection .hashCode ()) * 31 + log2length ;
427+ return Objects .hash (containingElement , relocatedSection , kind , sectionOffset , sym , targetSection , log2length , addend );
356428 }
357429}
0 commit comments