@@ -3839,6 +3839,173 @@ erts_max_heap_size(Eterm arg, Uint *max_heap_size, Uint *max_heap_flags)
38393839 return 1 ;
38403840}
38413841
3842+ typedef struct debug_binary {
3843+ BinRef * bin_ref ;
3844+ ErtsDynamicWStack ws ;
3845+ } DebugBinary ;
3846+
3847+ static void gather_binaries (DebugBinary * bins , Uint count , Eterm * start , Eterm * stop ) {
3848+ Eterm * tp = start ;
3849+ while (tp < stop ) {
3850+ Eterm val = * tp ++ ;
3851+
3852+ switch (primary_tag (val )) {
3853+ case TAG_PRIMARY_IMMED1 :
3854+ case TAG_PRIMARY_LIST :
3855+ case TAG_PRIMARY_BOXED :
3856+ break ;
3857+ case TAG_PRIMARY_HEADER :
3858+ if (header_is_transparent (val )) {
3859+ continue ;
3860+ }
3861+ switch (thing_subtag (val )) {
3862+ case SUB_BITS_SUBTAG :
3863+ {
3864+ const ErlSubBits * sb = (ErlSubBits * )(tp - 1 );
3865+ const BinRef * underlying = (BinRef * )boxed_val (sb -> orig );
3866+ if (thing_subtag (underlying -> thing_word ) != HEAP_BITS_SUBTAG ) {
3867+ for (Uint i = 0 ; i < count ; i ++ ) {
3868+ DebugBinary * b = & bins [i ];
3869+ if (b -> bin_ref == underlying ) {
3870+ WSTACK_PUSH2 (b -> ws .ws , sb -> start , sb -> end );
3871+ break ;
3872+ }
3873+ }
3874+ }
3875+ }
3876+ ERTS_FALLTHROUGH ();
3877+ default :
3878+ {
3879+ tp += header_arity (val );
3880+ }
3881+ break ;
3882+ }
3883+ break ;
3884+ }
3885+ }
3886+ }
3887+
3888+ Eterm
3889+ erts_gather_binaries (ErtsHeapFactory * hfact , Process * rp ) {
3890+ #define PSTACK_TYPE DebugBinary
3891+ PSTACK_DECLARE (binaries , 16 );
3892+
3893+ union erl_off_heap_ptr u ;
3894+ Eterm res = NIL ;
3895+ Eterm tuple ;
3896+ union erts_tmp_aligned_offheap tmp ;
3897+ Uint binaries_count ;
3898+ DebugBinary * binariesp ;
3899+
3900+ ErlHeapFragment * bp ;
3901+ ErtsMessage * mp ;
3902+ Eterm * htop , * heap ;
3903+ Uint sz = 0 ;
3904+ Eterm * hp ;
3905+
3906+ for (u .hdr = MSO (rp ).first ; u .hdr ; u .hdr = u .hdr -> next ) {
3907+ erts_align_offheap (& u , & tmp );
3908+ if (u .hdr -> thing_word == HEADER_BIN_REF ) {
3909+ DebugBinary * bin = PSTACK_PUSH (binaries );
3910+ bin -> bin_ref = u .br ;
3911+ WSTACK_INIT (& bin -> ws , ERTS_ALC_T_ESTACK );
3912+ }
3913+ }
3914+
3915+ for (u .hdr = rp -> wrt_bins ; u .hdr ; u .hdr = u .hdr -> next ) {
3916+ erts_align_offheap (& u , & tmp );
3917+ if (u .hdr -> thing_word == HEADER_BIN_REF ) {
3918+ DebugBinary * bin = PSTACK_PUSH (binaries );
3919+ bin -> bin_ref = u .br ;
3920+ WSTACK_INIT (& bin -> ws , ERTS_ALC_T_ESTACK );
3921+ }
3922+ }
3923+ binariesp = (DebugBinary * )binaries .pstart ;
3924+ binaries_count = PSTACK_COUNT (binaries );
3925+
3926+ if (rp -> abandoned_heap ) {
3927+ heap = get_orig_heap (rp , & htop , NULL );
3928+ gather_binaries (binariesp , binaries_count , heap , htop );
3929+ }
3930+
3931+ if (OLD_HEAP (rp ))
3932+ gather_binaries (binariesp , binaries_count , OLD_HEAP (rp ), OLD_HTOP (rp ) /*OLD_HEND(p)*/ );
3933+
3934+ gather_binaries (binariesp , binaries_count , HEAP_START (rp ), HEAP_TOP (rp ));
3935+
3936+ mp = rp -> msg_frag ;
3937+ bp = rp -> mbuf ;
3938+
3939+ if (bp )
3940+ goto search_heap_frags ;
3941+
3942+ while (mp ) {
3943+
3944+ bp = erts_message_to_heap_frag (mp );
3945+ mp = mp -> next ;
3946+
3947+ search_heap_frags :
3948+
3949+ while (bp ) {
3950+ gather_binaries (binariesp , binaries_count ,
3951+ bp -> mem , bp -> mem + bp -> used_size );
3952+ bp = bp -> next ;
3953+ }
3954+ }
3955+
3956+ for (Uint i = 0 ; i < binaries_count ; i ++ ) {
3957+ DebugBinary b = binariesp [i ];
3958+ sz += 2 /* cons */ + 6 /* tuple (ptr, sz, refc, binary, subs) */ ;
3959+ erts_bld_uword (NULL , & sz , (UWord ) b .bin_ref -> val );
3960+ erts_bld_uint (NULL , & sz , b .bin_ref -> val -> orig_size );
3961+ sz += ERL_REFC_BITS_SIZE ;
3962+ for (UWord * bits = b .ws .ws .wstart ; bits < b .ws .ws .wsp ; bits += 2 ) {
3963+ sz += 2 /* cons */ + 3 /* tuple*/ ;
3964+ erts_bld_uword (NULL , & sz , bits [0 ]);
3965+ erts_bld_uword (NULL , & sz , bits [1 ]);
3966+ }
3967+ }
3968+
3969+ hp = erts_produce_heap (hfact , sz , 2 );
3970+
3971+ for (Uint i = 0 ; i < binaries_count ; i ++ ) {
3972+ DebugBinary b = binariesp [i ];
3973+ Eterm bitslist = NIL ;
3974+ Eterm val = erts_bld_uword (& hp , NULL , (UWord )b .bin_ref -> val );
3975+ Eterm orig_size = erts_bld_uint (& hp , NULL , b .bin_ref -> val -> orig_size );
3976+ Eterm bitstring ;
3977+ for (UWord * bits = b .ws .ws .wstart ; bits < b .ws .ws .wsp ; bits += 2 ) {
3978+ Eterm offset = erts_bld_uword (& hp , NULL , bits [0 ]);
3979+ Eterm size = erts_bld_uword (& hp , NULL , bits [1 ]);
3980+ Eterm tuple = TUPLE2 (hp , offset , size );
3981+ hp += 3 ;
3982+ bitslist = CONS (hp , tuple , bitslist );
3983+ hp += 2 ;
3984+ }
3985+ erts_refc_inc (& b .bin_ref -> val -> intern .refc , 1 );
3986+ bitstring = erts_wrap_refc_bitstring (
3987+ & hfact -> off_heap -> first ,
3988+ & hfact -> off_heap -> overhead ,
3989+ & hp , b .bin_ref -> val , (byte * )b .bin_ref -> val -> orig_bytes ,
3990+ 0 , b .bin_ref -> val -> orig_size * 8 );
3991+ WSTACK_DESTROY (b .ws .ws );
3992+ tuple = TUPLE5 (hp , val ,
3993+ orig_size ,
3994+ /* We subtract the bump we did above when copying the binary */
3995+ make_small (erts_refc_read (& b .bin_ref -> val -> intern .refc , 1 ) - 1 ),
3996+ bitstring , bitslist );
3997+ hp += 6 ;
3998+ res = CONS (hp , tuple , res );
3999+ hp += 2 ;
4000+
4001+ }
4002+
4003+ PSTACK_DESTROY (binaries );
4004+ #undef PSTACK_TYPE
4005+
4006+ return res ;
4007+ }
4008+
38424009#if defined(DEBUG ) && defined(ERLANG_FRAME_POINTERS )
38434010void erts_validate_stack (Process * p , Eterm * frame_ptr , Eterm * stack_top ) {
38444011 Eterm * stack_bottom = HEAP_END (p );
0 commit comments