Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
pub
frama-c
Commits
9e6a5430
Commit
9e6a5430
authored
Sep 28, 2017
by
Kostyantyn Vorobyov
Committed by
Julien Signoles
Feb 20, 2018
Browse files
allocated and writeable in RTL as functions instead of macros
parent
0c0b039c
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
View file @
9e6a5430
...
...
@@ -29,6 +29,9 @@
# include "e_acsl_bittree_api.h"
# include "e_acsl_bittree.h"
static
inline
int
allocated
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
);
static
inline
int
writeable
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
);
/* Public API {{{ */
/* Debug */
#ifdef E_ACSL_DEBUG
...
...
@@ -43,18 +46,19 @@
#define E_ACSL_MMODEL_DESC "patricia trie"
/* Assertions in debug mode */
#define ALLOCATED(_ptr,_size, _base) \
((allocated(_ptr, _size, _base) == NULL) ? 0 : 1)
#ifdef E_ACSL_DEBUG
#define DVALIDATE_ALLOCATED(_ptr, _size, _base) \
vassert(ALLOCATED(_ptr, _size, _base), \
"Not allocated [%a, %a + %lu]", (uintptr_t)_ptr, _size)
#define DVALIDATE_WRITEABLE(_ptr, _size, _base) { \
DVALIDATE_ALLOCATED(_ptr, _size, _base); \
vassert(!readonly(_ptr), "Location %a is read-only", (uintptr_t)_ptr); \
}
/* Assert that memory block [_addr, _addr + _size] is allocated */
# define DVALIDATE_ALLOCATED(_addr, _size, _base) \
vassert(allocated((uintptr_t)_addr, _size, (uintptr_t)_base), \
"Operation on unallocated block [%a + %lu] with base %a\n", \
_addr, _size, _base);
/* Assert that memory block [_addr, _addr + _size] is allocated
* and can be written to */
# define DVALIDATE_WRITEABLE(_addr, _size, _base) \
vassert(writeable((uintptr_t)_addr, _size, (uintptr_t)_base), \
"Operation on unallocated block [%a + %lu] with base %a\n", \
_addr, _size, _base);
#else
#define DVALIDATE_ALLOCATED(_ptr, _size, _base)
#define DVALIDATE_WRITEABLE(_ptr, _size, _base)
...
...
@@ -80,7 +84,7 @@ static const int nbr_bits_to_1[256] = {
/* }}} */
/**************************/
/*
DEBUG
{{{ */
/*
LOCATION (DEBUG MODE)
{{{ */
/**************************/
#ifdef E_ACSL_DEBUG
/* Notion of current location for debugging purposes */
...
...
@@ -215,7 +219,7 @@ int initialized(void * ptr, size_t size) {
return
1
;
}
/*
return the length (in bytes) of the block containing ptr */
/*
* \brief \
return the length (in bytes) of the block containing ptr */
size_t
block_length
(
void
*
ptr
)
{
bt_block
*
blk
=
bt_find
(
ptr
);
/* Hard failure when un-allocated memory is used */
...
...
@@ -223,7 +227,11 @@ size_t block_length(void* ptr) {
return
blk
->
size
;
}
static
bt_block
*
allocated
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
)
{
/** \brief check whether a memory block containing address given via `ptr`
of length `size` and with base address `ptr_base` belongs to tracked
allocation and return corresponding `bt_block` if so. Return NULL
otherwise. */
static
bt_block
*
lookup_allocated
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
)
{
bt_block
*
blk
=
bt_find
(
ptr
);
if
(
blk
==
NULL
)
return
NULL
;
...
...
@@ -235,6 +243,14 @@ static bt_block* allocated(void* ptr, size_t size, void *ptr_base) {
return
(
blk
->
size
-
((
size_t
)
ptr
-
blk
->
ptr
)
>=
size
)
?
blk
:
NULL
;
}
/** \brief same as ::lookup_allocated but return either `1` or `0` depending
on whether the memory block described by this function's arguments is
allocated or not.
NOTE: Should have same signature in all models. */
static
inline
int
allocated
(
uintptr_t
addr
,
long
size
,
uintptr_t
base
)
{
return
lookup_allocated
((
void
*
)
addr
,
size
,
(
void
*
)
base
)
==
NULL
?
0
:
1
;
}
/** \brief Return 1 if a given memory location is read-only and 0 otherwise */
static
int
readonly
(
void
*
ptr
)
{
bt_block
*
blk
=
bt_find
(
ptr
);
...
...
@@ -242,9 +258,15 @@ static int readonly (void *ptr) {
return
blk
->
is_readonly
;
}
/** \brief same as ::allocated but returns `0` if the memory block described
by the arguments cannot be written to */
static
inline
int
writeable
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
)
{
return
allocated
(
addr
,
size
,
base_ptr
)
&&
!
readonly
((
void
*
)
addr
);
}
/* return whether the size bytes of ptr are readable/writable */
int
valid
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
bt_block
*
blk
=
allocated
(
ptr
,
size
,
ptr_base
);
bt_block
*
blk
=
lookup_
allocated
(
ptr
,
size
,
ptr_base
);
return
blk
!=
NULL
&&
!
blk
->
is_readonly
#ifdef E_ACSL_TEMPORAL
&&
temporal_valid
(
ptr_base
,
addrof_base
)
...
...
@@ -254,7 +276,7 @@ int valid(void* ptr, size_t size, void *ptr_base, void *addrof_base) {
/* return whether the size bytes of ptr are readable */
int
valid_read
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
bt_block
*
blk
=
allocated
(
ptr
,
size
,
ptr_base
);
bt_block
*
blk
=
lookup_
allocated
(
ptr
,
size
,
ptr_base
);
return
blk
!=
NULL
#ifdef E_ACSL_TEMPORAL
&&
temporal_valid
(
ptr_base
,
addrof_base
)
...
...
@@ -284,13 +306,13 @@ size_t offset(void* ptr) {
/* STACK ALLOCATION {{{ */
/* store the block of size bytes starting at ptr, the new block is returned.
* Warning: the return type is implicitly (bt_block*). */
void
*
store_block
(
void
*
ptr
,
size_t
size
)
{
void
*
store_block
(
void
*
ptr
,
size_t
size
)
{
#ifdef E_ACSL_DEBUG
if
(
ptr
==
NULL
)
vabort
(
"Attempt to record NULL block"
);
else
{
char
*
check
=
(
char
*
)
ptr
;
bt_block
*
exitsing_block
=
bt_find
(
ptr
);
bt_block
*
exitsing_block
=
bt_find
(
ptr
);
if
(
exitsing_block
)
{
vabort
(
"
\n
Recording %a [%lu] at %s:%d failed."
" Overlapping block %a [%lu] found at %s:%d
\n
"
,
...
...
@@ -307,7 +329,7 @@ void* store_block(void* ptr, size_t size) {
}
}
#endif
bt_block
*
tmp
=
NULL
;
bt_block
*
tmp
=
NULL
;
if
(
ptr
)
{
tmp
=
private_malloc
(
sizeof
(
bt_block
));
tmp
->
ptr
=
(
uintptr_t
)
ptr
;
...
...
@@ -333,7 +355,7 @@ void* store_block(void* ptr, size_t size) {
/* Track a heap block. This is a wrapper for all memory allocation functions
that create new bittree nodes. It applies to all memory allocating functions
but realloc that modifies nodes rather than create them */
static
void
*
store_freeable_block
(
void
*
ptr
,
size_t
size
,
int
init_bytes
)
{
static
void
*
store_freeable_block
(
void
*
ptr
,
size_t
size
,
int
init_bytes
)
{
bt_block
*
blk
=
NULL
;
if
(
ptr
)
{
blk
=
store_block
(
ptr
,
size
);
...
...
@@ -346,14 +368,14 @@ static void* store_freeable_block(void* ptr, size_t size, int init_bytes) {
}
/* remove the block starting at ptr */
void
delete_block
(
void
*
ptr
)
{
void
delete_block
(
void
*
ptr
)
{
#ifdef E_ACSL_DEBUG
/* Make sure the recorded block is not NULL */
if
(
!
ptr
)
vabort
(
"Attempt to delete NULL block"
);
#endif
if
(
ptr
!=
NULL
)
{
bt_block
*
tmp
=
bt_lookup
(
ptr
);
bt_block
*
tmp
=
bt_lookup
(
ptr
);
#ifdef E_ACSL_DEBUG
/* Make sure the removed block exists in the tracked allocation */
if
(
!
tmp
)
...
...
@@ -415,9 +437,9 @@ void* calloc(size_t nbr_block, size_t size_block) {
/*! \brief Replacement for `aligned_alloc` with memory tracking */
void
*
aligned_alloc
(
size_t
alignment
,
size_t
size
)
{
/* Check if:
*
- size and alignment are greater than zero
*
- alignment is a power of 2
*
- size is a multiple of alignment */
- size and alignment are greater than zero
- alignment is a power of 2
- size is a multiple of alignment */
if
(
!
size
||
!
alignment
||
!
powof2
(
alignment
)
||
(
size
%
alignment
))
return
NULL
;
...
...
@@ -435,7 +457,7 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) {
return
-
1
;
/* Make sure that the first argument to posix memalign is indeed allocated */
DVALIDATE_WRITEABLE
(
(
void
*
)
memptr
,
sizeof
(
void
*
),
(
void
*
)
memptr
);
DVALIDATE_WRITEABLE
(
memptr
,
sizeof
(
void
*
),
memptr
);
int
res
=
public_posix_memalign
(
memptr
,
alignment
,
size
);
if
(
!
res
)
...
...
@@ -444,7 +466,7 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) {
}
/*! \brief Replacement for `realloc` with memory tracking */
void
*
realloc
(
void
*
ptr
,
size_t
size
)
{
void
*
realloc
(
void
*
ptr
,
size_t
size
)
{
bt_block
*
tmp
;
void
*
new_ptr
;
/* ptr is NULL - malloc */
...
...
@@ -512,7 +534,7 @@ void* realloc(void* ptr, size_t size) {
}
/*! \brief Replacement for `free` with memory tracking */
void
free
(
void
*
ptr
)
{
void
free
(
void
*
ptr
)
{
if
(
ptr
==
NULL
)
{
/* Fail if instructed to treat NULL input to free as invalid. */
#ifdef E_ACSL_FREE_VALID_ADDRESS
...
...
@@ -520,7 +542,7 @@ void free(void* ptr) {
#endif
return
;
}
bt_block
*
res
=
bt_lookup
(
ptr
);
bt_block
*
res
=
bt_lookup
(
ptr
);
if
(
!
res
)
{
vabort
(
"Not a start of block (%a) in free
\n
"
,
ptr
);
}
else
{
...
...
@@ -606,8 +628,11 @@ void memory_init(int *argc_ref, char ***argv_ref, size_t ptr_size) {
}
/* }}} */
#ifdef E_ACSL_DEBUG
/******************************/
/* DEBUG PRINT {{{ */
/******************************/
#ifdef E_ACSL_DEBUG
/* Debug version of store block with location tracking. This function is aimed
* at manual debugging. While there is no easy way of traking file/line numbers
* recorded memory blocks with the use of the following macros placed after the
...
...
@@ -650,6 +675,7 @@ void block_info(char *p) {
}
}
#endif
/* }}} */
/* Local operations on temporal timestamps {{{ */
/* Remaining functionality (shared between all models) is located in e_acsl_temporal.h */
...
...
@@ -660,7 +686,7 @@ static uint32_t origin_timestamp(void *ptr) {
}
static
uintptr_t
temporal_referent_shadow
(
void
*
ptr
)
{
bt_block
*
blk
=
bt_find
(
ptr
);
bt_block
*
blk
=
bt_find
(
ptr
);
vassert
(
blk
!=
NULL
,
"referent timestamp on unallocated memory address %a"
,
(
uintptr_t
)
ptr
);
vassert
(
blk
->
temporal_shadow
!=
NULL
,
...
...
src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
View file @
9e6a5430
...
...
@@ -33,23 +33,21 @@
#define E_ACSL_MMODEL_DESC "shadow memory"
#define ALLOCATED(_ptr,_size) allocated((uintptr_t)_ptr, _size, (uintptr_t)_ptr)
void
*
store_block
(
void
*
ptr
,
size_t
size
)
{
void
*
store_block
(
void
*
ptr
,
size_t
size
)
{
/* Only stack-global memory blocks are recorded explicitly via this function.
*
Heap blocks should be tracked internally using memory allocation functions
*
such as malloc or calloc. */
Heap blocks should be tracked internally using memory allocation functions
such as malloc or calloc. */
shadow_alloca
(
ptr
,
size
);
return
ptr
;
}
void
delete_block
(
void
*
ptr
)
{
void
delete_block
(
void
*
ptr
)
{
/* Block deletion should be performed on stack/global addresses only,
* heap blocks should be deallocated manually via free/cfree/realloc. */
shadow_freea
(
ptr
);
}
void
*
store_block_duplicate
(
void
*
ptr
,
size_t
size
)
{
void
*
store_block_duplicate
(
void
*
ptr
,
size_t
size
)
{
if
(
allocated
((
uintptr_t
)
ptr
,
size
,
(
uintptr_t
)
ptr
))
delete_block
(
ptr
);
shadow_alloca
(
ptr
,
size
);
...
...
@@ -66,11 +64,11 @@ void initialize(void *ptr, size_t n) {
)
}
void
full_init
(
void
*
ptr
)
{
void
full_init
(
void
*
ptr
)
{
initialize
(
ptr
,
_block_length
(
ptr
));
}
void
mark_readonly
(
void
*
ptr
)
{
void
mark_readonly
(
void
*
ptr
)
{
mark_readonly_region
((
uintptr_t
)
ptr
,
_block_length
(
ptr
));
}
...
...
@@ -78,13 +76,7 @@ void mark_readonly(void * ptr) {
/* E-ACSL annotations {{{ */
/* ********************** */
/** \brief Return 1 if a given memory location is read-only and 0 otherwise */
static
int
readonly
(
void
*
ptr
)
{
uintptr_t
addr
=
(
uintptr_t
)
ptr
;
return
IS_ON_GLOBAL
(
addr
)
&&
global_readonly
(
addr
)
?
1
:
0
;
}
int
valid
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
int
valid
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
return
allocated
((
uintptr_t
)
ptr
,
size
,
(
uintptr_t
)
ptr_base
)
&&
!
readonly
(
ptr
)
...
...
@@ -94,19 +86,18 @@ int valid(void * ptr, size_t size, void *ptr_base, void *addrof_base) {
;
}
int
valid_read
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
int
valid_read
(
void
*
ptr
,
size_t
size
,
void
*
ptr_base
,
void
*
addrof_base
)
{
return
allocated
((
uintptr_t
)
ptr
,
size
,
(
uintptr_t
)
ptr_base
)
#ifdef E_ACSL_TEMPORAL
&&
temporal_valid
(
ptr_base
,
addrof_base
)
#endif
;
}
/*! NB: The implementation for this function can also be specified via
*
\p _base_addr macro that will eventually call ::TRY_SEGMENT. The following
*
implementation is preferred for performance reasons. */
void
*
base_addr
(
void
*
ptr
)
{
\p _base_addr macro that will eventually call ::TRY_SEGMENT. The following
implementation is preferred for performance reasons. */
void
*
base_addr
(
void
*
ptr
)
{
TRY_SEGMENT
(
ptr
,
return
(
void
*
)
heap_info
((
uintptr_t
)
ptr
,
'B'
),
return
(
void
*
)
static_info
((
uintptr_t
)
ptr
,
'B'
));
...
...
@@ -114,9 +105,9 @@ void * base_addr(void * ptr) {
}
/*! NB: Implementation of the following function can also be specified
*
via \p _block_length macro. A more direct approach via ::TRY_SEGMENT
*
is preferred for performance reasons. */
size_t
block_length
(
void
*
ptr
)
{
via \p _block_length macro. A more direct approach via ::TRY_SEGMENT
is preferred for performance reasons. */
size_t
block_length
(
void
*
ptr
)
{
TRY_SEGMENT
(
ptr
,
return
heap_info
((
uintptr_t
)
ptr
,
'L'
),
return
static_info
((
uintptr_t
)
ptr
,
'L'
))
...
...
@@ -130,7 +121,7 @@ size_t offset(void *ptr) {
return
0
;
}
int
initialized
(
void
*
ptr
,
size_t
size
)
{
int
initialized
(
void
*
ptr
,
size_t
size
)
{
uintptr_t
addr
=
(
uintptr_t
)
ptr
;
TRY_SEGMENT_WEAK
(
addr
,
return
heap_initialized
(
addr
,
size
),
...
...
@@ -168,9 +159,9 @@ static void argv_alloca(int *argc_ref, char *** argv_ref) {
therefore more than welcome. */
*
argv
=
shadow_copy
(
*
argv
,
arglen
,
1
);
/* TODO: These heap allocations are never freed in fact. Not super
*
important, but for completeness purposes it may be feasible to define
*
a buffer of implicitly allocated memory locations which need to be
*
freed before a program exists. */
important, but for completeness purposes it may be feasible to define
a buffer of implicitly allocated memory locations which need to be
freed before a program exists. */
#else
shadow_alloca
(
*
argv
,
arglen
);
initialize_static_region
((
uintptr_t
)
*
argv
,
arglen
);
...
...
src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_tracking.h
View file @
9e6a5430
...
...
@@ -383,18 +383,16 @@ static void validate_shadow_layout() {
/* Assert that memory block [_addr, _addr + _size] is allocated */
# define DVALIDATE_ALLOCATED(_addr, _size, _base) \
DVASSERT
(allocated((uintptr_t)_addr, _size, (uintptr_t)_base), \
vassert
(allocated((uintptr_t)_addr, _size, (uintptr_t)_base), \
"Operation on unallocated block [%a + %lu] with base %a\n", \
_addr, _size, _base)
_addr, _size, _base)
;
/* Assert that memory block [_addr, _addr + _size] is allocated
* and can be written to */
# define DVALIDATE_WRITEABLE(_addr, _size, _base) { \
DVALIDATE_ALLOCATED((uintptr_t)_addr, _size, (uintptr_t)_base); \
DVASSERT(!readonly((void*)_addr), \
"Unexpected readonly address: %lu\n", _addr); \
}
# define DVALIDATE_WRITEABLE(_addr, _size, _base) \
vassert(writeable((uintptr_t)_addr, _size, (uintptr_t)_base), \
"Operation on unallocated block [%a + %lu] with base %a\n", \
_addr, _size, _base);
#else
/*! \cond exclude from doxygen */
# define DVALIDATE_MEMORY_INIT
...
...
@@ -428,6 +426,8 @@ static uintptr_t static_info(uintptr_t addr, char type);
static
int
heap_allocated
(
uintptr_t
addr
,
size_t
size
,
uintptr_t
base_ptr
);
static
int
static_allocated
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
);
static
int
allocated
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
);
static
int
writeable
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
);
static
int
readonly
(
void
*
ptr
);
/*! \brief Quick test to check if a static location belongs to allocation.
* This macro really belongs where static_allocated is defined, but
...
...
@@ -1303,6 +1303,16 @@ static int allocated(uintptr_t addr, long size, uintptr_t base) {
return
0
;
return
0
;
}
/** \brief Return 1 if a given memory location is read-only and 0 otherwise */
static
inline
int
readonly
(
void
*
ptr
)
{
uintptr_t
addr
=
(
uintptr_t
)
ptr
;
return
IS_ON_GLOBAL
(
addr
)
&&
global_readonly
(
addr
)
?
1
:
0
;
}
static
inline
int
writeable
(
uintptr_t
addr
,
long
size
,
uintptr_t
base_ptr
)
{
return
allocated
(
addr
,
size
,
base_ptr
)
&&
!
readonly
((
void
*
)
addr
);
}
/* }}} */
/* Internal state print (debug mode) {{{ */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment