@ -2830,12 +2830,186 @@ static int8_t getModstate() { return Core::getInstance().getModstate(); }
 
		
	
		
			
				static  std : : string  internal_strerror ( int  n )  {  return  strerror ( n ) ;  }  
		
	
		
			
				static  std : : string  internal_md5 ( std : : string  s )  {  return  md5_wrap . getHashFromString ( s ) ;  }  
		
	
		
			
				
 
		
	
		
			
				struct  heap_pointer_info  
		
	
		
			
				{  
		
	
		
			
				    size_t  address  =  0 ; 
 
		
	
		
			
				    size_t  size  =  0 ; 
 
		
	
		
			
				    int  status  =  0 ; 
 
		
	
		
			
				} ;  
		
	
		
			
				
 
		
	
		
			
				//fixed sized, sorted
  
		
	
		
			
				static  std : : vector < heap_pointer_info >  heap_data ;  
		
	
		
			
				
 
		
	
		
			
				//when dfhack upgrades to c++17, this would do well as a std::optional
  
		
	
		
			
				static  std : : pair < bool ,  heap_pointer_info >  heap_find ( uintptr_t  address )  
		
	
		
			
				{  
		
	
		
			
				    auto  it  =  std : : lower_bound ( heap_data . begin ( ) ,  heap_data . end ( ) ,  address , 
 
		
	
		
			
				    [ ] ( heap_pointer_info  t ,  uintptr_t  address ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				        return  t . address  <  address ; 
 
		
	
		
			
				    } ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( it  = =  heap_data . end ( )  | |  it - > address  ! =  address ) 
 
		
	
		
			
				        return  { false ,  heap_pointer_info ( ) } ; 
 
		
	
		
			
				
 
		
	
		
			
				    return  { true ,  * it } ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				//this function only allocates the first time it is called
  
		
	
		
			
				static  int  heap_take_snapshot ( )  
		
	
		
			
				{  
		
	
		
			
				    # ifdef _WIN32 
 
		
	
		
			
				    size_t  max_entries  =  256  *  1024  *  1024  /  sizeof ( heap_pointer_info ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    //clearing the vector is guaranteed not to deallocate the memory
 
 
		
	
		
			
				    heap_data . clear ( ) ; 
 
		
	
		
			
				    heap_data . reserve ( max_entries ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    _HEAPINFO  hinfo ; 
 
		
	
		
			
				    hinfo . _pentry  =  nullptr ; 
 
		
	
		
			
				    int  heap_status  =  0 ; 
 
		
	
		
			
				
 
		
	
		
			
				    while  ( ( heap_status  =  _heapwalk ( & hinfo ) )  = =  _HEAPOK  & &  heap_data . size ( )  <  max_entries ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				        heap_pointer_info  inf ; 
 
		
	
		
			
				        inf . address  =  reinterpret_cast < uintptr_t > ( hinfo . _pentry ) ; 
 
		
	
		
			
				        inf . size  =  hinfo . _size ; 
 
		
	
		
			
				        inf . status  =  hinfo . _useflag ;  //0 == _FREEENTRY, 1 == _USEDENTRY
 
 
		
	
		
			
				
 
		
	
		
			
				        heap_data . push_back ( inf ) ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    //sort by address
 
 
		
	
		
			
				    std : : sort ( heap_data . begin ( ) ,  heap_data . end ( ) , 
 
		
	
		
			
				    [ ] ( heap_pointer_info  t1 ,  heap_pointer_info  t2 ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				        return  t1 . address  <  t2 . address ; 
 
		
	
		
			
				    } ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPEMPTY  | |  heap_status  = =  _HEAPEND ) 
 
		
	
		
			
				        return  0 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADPTR ) 
 
		
	
		
			
				        return  1 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADBEGIN ) 
 
		
	
		
			
				        return  2 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADNODE ) 
 
		
	
		
			
				        return  3 ; 
 
		
	
		
			
				    # endif 
 
		
	
		
			
				
 
		
	
		
			
				    return  0 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  int  get_heap_state ( )  
		
	
		
			
				{  
		
	
		
			
				    # ifdef _WIN32 
 
		
	
		
			
				    int  heap_status  =  _heapchk ( ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPEMPTY  | |  heap_status  = =  _HEAPOK ) 
 
		
	
		
			
				        return  0 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADPTR ) 
 
		
	
		
			
				        return  1 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADBEGIN ) 
 
		
	
		
			
				        return  2 ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( heap_status  = =  _HEAPBADNODE ) 
 
		
	
		
			
				        return  3 ; 
 
		
	
		
			
				    # endif 
 
		
	
		
			
				
 
		
	
		
			
				    return  0 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  bool  is_address_in_heap ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    return  heap_find ( ptr ) . first ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  bool  is_address_active_in_heap ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    std : : pair < bool ,  heap_pointer_info >  inf  =  heap_find ( ptr ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( ! inf . first ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    return  inf . second . status  = =  1 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  bool  is_address_used_after_free_in_heap ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    std : : pair < bool ,  heap_pointer_info >  inf  =  heap_find ( ptr ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( ! inf . first ) 
 
		
	
		
			
				        return  false ; 
 
		
	
		
			
				
 
		
	
		
			
				    return  inf . second . status  ! =  1 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  int  get_address_size_in_heap ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    std : : pair < bool ,  heap_pointer_info >  inf  =  heap_find ( ptr ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( ! inf . first ) 
 
		
	
		
			
				        return  - 1 ; 
 
		
	
		
			
				
 
		
	
		
			
				    return  inf . second . size ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				//eg if I have a struct, does any address lie within the struct?
  
		
	
		
			
				static  uintptr_t  get_root_address_of_heap_object ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    //find the first element strictly greater than our pointer
 
 
		
	
		
			
				    auto  it  =  std : : upper_bound ( heap_data . begin ( ) ,  heap_data . end ( ) ,  ptr ,  [ ] ( uintptr_t  ptr ,  heap_pointer_info  t1 ) 
 
		
	
		
			
				    { 
 
		
	
		
			
				        return  ptr  <  t1 . address ; 
 
		
	
		
			
				    } ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    //if we're at the start of the snapshot, no elements are less than our pointer
 
 
		
	
		
			
				    //therefore it is invalid
 
 
		
	
		
			
				    if  ( it  = =  heap_data . begin ( ) ) 
 
		
	
		
			
				        return  0 ; 
 
		
	
		
			
				
 
		
	
		
			
				    //get the first element less than or equal to ours
 
 
		
	
		
			
				    it - - ; 
 
		
	
		
			
				
 
		
	
		
			
				    //our pointer is only valid if we lie in the first pointer lower in memory than it
 
 
		
	
		
			
				    if  ( ptr  > =  it - > address  & &  ptr  <  it - > address  +  it - > size ) 
 
		
	
		
			
				        return  it - > address ; 
 
		
	
		
			
				
 
		
	
		
			
				    return  0 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				//msize crashes if you pass an invalid pointer to it, only use it if you *know* the thing you're looking at
  
		
	
		
			
				//is in the heap/valid
  
		
	
		
			
				static  int  msize_address ( uintptr_t  ptr )  
		
	
		
			
				{  
		
	
		
			
				    # ifdef _WIN32 
 
		
	
		
			
				    void *  vptr  =  reinterpret_cast < void * > ( ptr ) ; 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( vptr ) 
 
		
	
		
			
				        return  _msize ( vptr ) ; 
 
		
	
		
			
				    # endif 
 
		
	
		
			
				
 
		
	
		
			
				    return  - 1 ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				static  const  LuaWrapper : : FunctionReg  dfhack_internal_module [ ]  =  {  
		
	
		
			
				    WRAP ( getImageBase ) , 
 
		
	
		
			
				    WRAP ( getRebaseDelta ) , 
 
		
	
		
			
				    WRAP ( getModstate ) , 
 
		
	
		
			
				    WRAPN ( strerror ,  internal_strerror ) , 
 
		
	
		
			
				    WRAPN ( md5 ,  internal_md5 ) , 
 
		
	
		
			
				    WRAPN ( heapTakeSnapshot ,  heap_take_snapshot ) , 
 
		
	
		
			
				    WRAPN ( getHeapState ,  get_heap_state ) , 
 
		
	
		
			
				    WRAPN ( isAddressInHeap ,  is_address_in_heap ) , 
 
		
	
		
			
				    WRAPN ( isAddressActiveInHeap ,  is_address_active_in_heap ) , 
 
		
	
		
			
				    WRAPN ( isAddressUsedAfterFreeInHeap ,  is_address_used_after_free_in_heap ) , 
 
		
	
		
			
				    WRAPN ( getAddressSizeInHeap ,  get_address_size_in_heap ) , 
 
		
	
		
			
				    WRAPN ( getRootAddressOfHeapObject ,  get_root_address_of_heap_object ) , 
 
		
	
		
			
				    WRAPN ( msizeAddress ,  msize_address ) , 
 
		
	
		
			
				    {  NULL ,  NULL  } 
 
		
	
		
			
				} ;