mirror of
https://github.com/vtil-project/VTIL-Core
synced 2026-08-17 08:23:03 -04:00
Slight changes to symbolic::context/memory interface.
This commit is contained in:
parent
230c51470f
commit
d5a7ace029
5 changed files with 53 additions and 32 deletions
|
|
@ -30,9 +30,9 @@
|
|||
|
||||
namespace vtil::symbolic
|
||||
{
|
||||
// Checks if the symbolic context contains any writes to the given region described by the register desc.
|
||||
// Returns the absolute mask of known/unknown bits of the given register.
|
||||
//
|
||||
bool context::contains( const register_desc& desc ) const
|
||||
uint64_t context::known_mask( const register_desc& desc ) const
|
||||
{
|
||||
// If identifier is not in the store, return false.
|
||||
//
|
||||
|
|
@ -42,27 +42,35 @@ namespace vtil::symbolic
|
|||
|
||||
// Enumerate each bit set within (size+offset, 0]:
|
||||
//
|
||||
bool found = false;
|
||||
uint64_t known_mask = 0;
|
||||
math::bit_enum( it->second.bitmap & math::fill( desc.bit_count + desc.bit_offset ), [ & ] ( bitcnt_t i )
|
||||
{
|
||||
// If value extends into the region, declare found.
|
||||
// If value extends into the region, declare found, set known mask.
|
||||
//
|
||||
const expression::reference& value = it->second.linear_store[ i ];
|
||||
if ( ( value.size() + i ) > desc.bit_offset )
|
||||
found = true;
|
||||
known_mask |= math::fill( value.size(), i );
|
||||
} );
|
||||
return found;
|
||||
return known_mask & desc.get_mask();
|
||||
}
|
||||
uint64_t context::unknown_mask( const register_desc& desc ) const
|
||||
{
|
||||
return desc.get_mask() & ~known_mask( desc );
|
||||
}
|
||||
|
||||
// Reads the value of the given region described by the register desc.
|
||||
// - Will output the mask of bits contained in the state into contains.
|
||||
//
|
||||
expression::reference context::read( const register_desc& desc, const il_const_iterator& reference_iterator ) const
|
||||
expression::reference context::read( const register_desc& desc, const il_const_iterator& reference_iterator, uint64_t* contains ) const
|
||||
{
|
||||
uint64_t tmp;
|
||||
if ( !contains ) contains = &tmp;
|
||||
|
||||
// If identifier is not in the store, return default.
|
||||
//
|
||||
auto it = value_map.find( desc );
|
||||
if ( it == value_map.end() )
|
||||
return CTX( reference_iterator )[ desc ];
|
||||
return *contains = 0, CTX( reference_iterator )[ desc ];
|
||||
|
||||
// Allocate storage for result and create masks.
|
||||
//
|
||||
|
|
@ -99,7 +107,8 @@ namespace vtil::symbolic
|
|||
|
||||
// If no bits set in known mask, return default.
|
||||
//
|
||||
if ( !known_mask )
|
||||
*contains = known_mask & read_mask;
|
||||
if ( !*contains )
|
||||
return CTX( reference_iterator )[ desc ];
|
||||
|
||||
// If all bits set in known mask, return as is.
|
||||
|
|
|
|||
|
|
@ -65,13 +65,15 @@ namespace vtil::symbolic
|
|||
size_t size() const { return value_map.size(); }
|
||||
void reset() { value_map.clear(); }
|
||||
|
||||
// Checks if the symbolic context contains any writes to the given region described by the register desc.
|
||||
// Returns the absolute mask of known/unknown bits of the given register.
|
||||
//
|
||||
bool contains( const register_desc& desc ) const;
|
||||
uint64_t known_mask( const register_desc& desc ) const;
|
||||
uint64_t unknown_mask( const register_desc& desc ) const;
|
||||
|
||||
// Reads the value of the given region described by the register desc.
|
||||
// - Will output the mask of bits contained in the state into contains.
|
||||
//
|
||||
expression::reference read( const register_desc& desc, const il_const_iterator& reference_iterator = symbolic::free_form_iterator ) const;
|
||||
expression::reference read( const register_desc& desc, const il_const_iterator& reference_iterator = symbolic::free_form_iterator, uint64_t* contains = nullptr ) const;
|
||||
|
||||
// Writes the given value to the region described by the register desc.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -30,15 +30,22 @@
|
|||
|
||||
namespace vtil::symbolic
|
||||
{
|
||||
// Checks if the symbolic memory contains any writes to the given memory region.
|
||||
// Returns the mask of known/unknown bits of the given region, if alias failure occurs returns nullopt.
|
||||
//
|
||||
trilean memory::contains( const pointer& ptr, bitcnt_t size ) const
|
||||
std::optional<uint64_t> memory::known_mask( const pointer& ptr, bitcnt_t size ) const
|
||||
{
|
||||
uint64_t mask_value = math::fill( size );
|
||||
if ( auto value = unknown_mask( ptr, size ) )
|
||||
return math::fill( size ) & ~*value;
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<uint64_t> memory::unknown_mask( const pointer& ptr, bitcnt_t size ) const
|
||||
{
|
||||
uint64_t mask_pending = math::fill( size );
|
||||
|
||||
// For each entry, iterating backwards:
|
||||
//
|
||||
for ( auto it = value_map.rbegin(); it != value_map.rend(); it++ )
|
||||
for ( auto it = value_map.rbegin(); it != value_map.rend() && mask_pending; it++ )
|
||||
{
|
||||
// If pointer cannot overlap lookup, skip.
|
||||
//
|
||||
|
|
@ -49,25 +56,25 @@ namespace vtil::symbolic
|
|||
//
|
||||
std::optional byte_distance = it->first - ptr;
|
||||
if ( !byte_distance )
|
||||
return trilean::unknown;
|
||||
return std::nullopt;
|
||||
|
||||
// Calculate relative mask, return true if overlapping.
|
||||
// Calculate relative mask, clear pending mask.
|
||||
//
|
||||
bitcnt_t bit_distance = math::narrow_cast< bitcnt_t >( *byte_distance * 8 );
|
||||
bitcnt_t bit_distance = math::narrow_cast<bitcnt_t>( *byte_distance * 8 );
|
||||
uint64_t relative_mask = math::fill( it->second.size(), bit_distance );
|
||||
if ( relative_mask & mask_value )
|
||||
return true;
|
||||
mask_pending &= ~relative_mask;
|
||||
}
|
||||
|
||||
// None found, return false.
|
||||
//
|
||||
return false;
|
||||
return mask_pending;
|
||||
}
|
||||
|
||||
// Reads N bits from the given pointer, returns null reference if alias failure occurs.
|
||||
// - Will output the mask of bits contained in the state into contains if it does not fail.
|
||||
//
|
||||
expression::reference memory::read( const pointer& ptr, bitcnt_t size, const il_const_iterator& reference_iterator ) const
|
||||
expression::reference memory::read( const pointer& ptr, bitcnt_t size, const il_const_iterator& reference_iterator, uint64_t* contains ) const
|
||||
{
|
||||
uint64_t tmp;
|
||||
if ( !contains ) contains = &tmp;
|
||||
|
||||
uint64_t mask_pending = math::fill( size );
|
||||
stack_vector<std::pair<bitcnt_t, expression::reference>, 8> merge_list;
|
||||
|
||||
|
|
@ -111,7 +118,8 @@ namespace vtil::symbolic
|
|||
|
||||
// If no overlapping keys found, return default.
|
||||
//
|
||||
if ( merge_list.empty() )
|
||||
*contains = math::fill( size ) & ~mask_pending;
|
||||
if ( !*contains )
|
||||
return MEMORY( reference_iterator )( ptr, size );
|
||||
|
||||
// Declare common bit selector.
|
||||
|
|
|
|||
|
|
@ -67,13 +67,15 @@ namespace vtil::symbolic
|
|||
size_t size() const { return value_map.size(); }
|
||||
void reset() { value_map.clear(); }
|
||||
|
||||
// Checks if the symbolic memory contains any writes to the given memory region.
|
||||
//
|
||||
trilean contains( const pointer& ptr, bitcnt_t size ) const;
|
||||
// Returns the mask of known/unknown bits of the given region, if alias failure occurs returns nullopt.
|
||||
//
|
||||
std::optional<uint64_t> known_mask( const pointer& ptr, bitcnt_t size ) const;
|
||||
std::optional<uint64_t> unknown_mask( const pointer& ptr, bitcnt_t size ) const;
|
||||
|
||||
// Reads N bits from the given pointer, returns null reference if alias failure occurs.
|
||||
// - Will output the mask of bits contained in the state into contains if it does not fail.
|
||||
//
|
||||
expression::reference read( const pointer& ptr, bitcnt_t size, const il_const_iterator& reference_iterator = symbolic::free_form_iterator ) const;
|
||||
expression::reference read( const pointer& ptr, bitcnt_t size, const il_const_iterator& reference_iterator = symbolic::free_form_iterator, uint64_t* contains = nullptr ) const;
|
||||
|
||||
// Writes the given value to the pointer, returns null reference if alias failure occurs.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ namespace vtil
|
|||
//
|
||||
symbolic::expression::reference read_memory( const symbolic::expression::reference& pointer, size_t byte_count ) override
|
||||
{
|
||||
return memory_state.read( pointer, math::narrow_cast< bitcnt_t >( byte_count * 8 ), reference_iterator );
|
||||
return memory_state.read( pointer, math::narrow_cast<bitcnt_t>( byte_count * 8 ), reference_iterator );
|
||||
}
|
||||
|
||||
// Writes the given expression to the memory.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue