@@ -262,18 +262,29 @@ public override bool Equals(object? obj)
262262 return false ;
263263
264264 if ( _identifier != other . _identifier )
265+ {
266+ Debug . WriteLine ( $ "Identifiers differ: '{ _identifier } ' vs '{ other . _identifier } '") ;
267+ Debug . WriteLine ( $ "Expected (codesign):\n { other . ToCodesignString ( ) } ") ;
268+ Debug . WriteLine ( $ "Actual (managed):\n { ToCodesignString ( ) } ") ;
265269 return false ;
270+ }
266271
267272 CodeDirectoryHeader thisHeader = _cdHeader ;
268273 CodeDirectoryHeader otherHeader = other . _cdHeader ;
269274 if ( ! CodeDirectoryHeader . AreEqual ( thisHeader , otherHeader ) )
270275 {
276+ Debug . WriteLine ( "CodeDirectory headers differ" ) ;
277+ Debug . WriteLine ( $ "Expected (codesign):\n { other . ToCodesignString ( ) } ") ;
278+ Debug . WriteLine ( $ "Actual (managed):\n { ToCodesignString ( ) } ") ;
271279 return false ;
272280 }
273281 for ( int i = 0 ; i < _specialSlotHashes . Length ; i ++ )
274282 {
275283 if ( ! _specialSlotHashes [ i ] . SequenceEqual ( other . _specialSlotHashes [ i ] ) )
276284 {
285+ Debug . WriteLine ( $ "Special slot hash { - ( int ) SpecialSlotCount + i } differs") ;
286+ Debug . WriteLine ( $ "Expected (codesign):\n { other . ToCodesignString ( ) } ") ;
287+ Debug . WriteLine ( $ "Actual (managed):\n { ToCodesignString ( ) } ") ;
277288 return false ;
278289 }
279290 }
@@ -282,6 +293,9 @@ public override bool Equals(object? obj)
282293 {
283294 if ( ! _codeHashes [ i ] . SequenceEqual ( other . _codeHashes [ i ] ) )
284295 {
296+ Debug . WriteLine ( $ "Code hash { i } differs") ;
297+ Debug . WriteLine ( $ "Expected (codesign):\n { other . ToCodesignString ( ) } ") ;
298+ Debug . WriteLine ( $ "Actual (managed):\n { ToCodesignString ( ) } ") ;
285299 return false ;
286300 }
287301 }
@@ -328,4 +342,43 @@ public int Write(IMachOFileWriter accessor, long offset)
328342 }
329343 return ( int ) Size ;
330344 }
345+
346+ /// <summary>
347+ /// Formats the CodeDirectory information in a style similar to codesign's output
348+ /// </summary>
349+ internal string ToCodesignString ( )
350+ {
351+ var sb = new StringBuilder ( ) ;
352+ sb . AppendLine ( $ "Identifier={ _identifier } ") ;
353+ sb . AppendLine ( $ "CodeDirectory v={ ( uint ) _cdHeader . Version : X} size={ Size } flags=0x{ ( uint ) _cdHeader . Flags : X} ({ _cdHeader . Flags . ToString ( ) . ToLower ( System . Globalization . CultureInfo . InvariantCulture ) } ) hashes={ CodeSlotCount } +{ SpecialSlotCount } location=embedded") ;
354+ sb . AppendLine ( $ "Hash type={ _cdHeader . HashType . ToString ( ) . ToLower ( System . Globalization . CultureInfo . InvariantCulture ) } size={ HashSize } ") ;
355+ sb . AppendLine ( $ "Executable Segment base={ _cdHeader . ExecSegmentBase } ") ;
356+ sb . AppendLine ( $ "Executable Segment limit={ _cdHeader . ExecSegmentLimit } ") ;
357+ sb . AppendLine ( $ "Executable Segment flags=0x{ ( ulong ) _cdHeader . ExecSegmentFlags : X} ") ;
358+ sb . AppendLine ( $ "Page size={ ( 1 << _cdHeader . Log2PageSize ) } ") ;
359+
360+ // Print special slot hashes (numbered from -SpecialSlotCount to -1)
361+ for ( int i = 0 ; i < SpecialSlotCount ; i ++ )
362+ {
363+ int slotNumber = - ( int ) SpecialSlotCount + i ;
364+ sb . AppendLine ( $ " { slotNumber , 3 } ={ ToHexStringLower ( _specialSlotHashes [ i ] ) } ") ;
365+ }
366+
367+ // Print code hashes (numbered from 0 to CodeSlotCount-1)
368+ for ( int i = 0 ; i < CodeSlotCount ; i ++ )
369+ {
370+ sb . AppendLine ( $ " { i , 3 } ={ ToHexStringLower ( _codeHashes [ i ] ) } ") ;
371+ }
372+
373+ return sb . ToString ( ) ;
374+ }
375+
376+ private static string ToHexStringLower ( byte [ ] bytes )
377+ {
378+ #if NET
379+ return Convert . ToHexStringLower ( bytes ) ;
380+ #else
381+ return BitConverter . ToString ( bytes ) . Replace ( "-" , "" ) . ToLower ( System . Globalization . CultureInfo . InvariantCulture ) ;
382+ #endif
383+ }
331384}
0 commit comments