NIPS VM added to the SPOT distribution.
2008-05-29 Guillaume SADEGH <sadegh@lrde.epita.fr> * iface/nips/nips.cc, iface/nips/nips.hh, iface/nips/common.cc, iface/nips/common.hh, iface/nips/Makefile.am: TGBA implementation with the NIPS library. * iface/nips/emptiness_check.cc: Emptiness check on a Promela interface. * iface/nips/dottynips.cc: Dot printer on the NIPS interface. * iface/nips/compile.sh: Add. Wrapper around nips compiler to compile Promela to NIPS bytecode. * iface/nips/nips_vm,iface/nips/nips_vm/bytecode.h, iface/nips/nips_vm/ChangeLog, iface/nips/nips_vm/COPYING, iface/nips/nips_vm/hashtab.c, iface/nips/nips_vm/hashtab.h, iface/nips/nips_vm/INSTALL, iface/nips/nips_vm/instr.c, iface/nips/nips_vm/instr.h, iface/nips/nips_vm/instr_step.c, iface/nips/nips_vm/instr_step.h, iface/nips/nips_vm/instr_tools.c, iface/nips/nips_vm/instr_tools.h, iface/nips/nips_vm/instr_wrap.c, iface/nips/nips_vm/instr_wrap.h, iface/nips/nips_vm/interactive.c, iface/nips/nips_vm/interactive.h, iface/nips/nips_vm/main.c, iface/nips/nips_vm/Makefile, iface/nips/nips_vm/Makefile.am, iface/nips/nips_vm/nips_asm_help.pl, iface/nips/nips_vm/nips_asm_instr.pl, iface/nips/nips_vm/nips_asm.pl, iface/nips/nips_vm/nips_disasm.pl, iface/nips/nips_vm/nipsvm.c, iface/nips/nips_vm/nipsvm.h, iface/nips/nips_vm/README, iface/nips/nips_vm/rt_err.c, iface/nips/nips_vm/rt_err.h, iface/nips/nips_vm/search.c, iface/nips/nips_vm/search.h, iface/nips/nips_vm/split.c, iface/nips/nips_vm/split.h, iface/nips/nips_vm/state.c, iface/nips/nips_vm/state.h, iface/nips/nips_vm/state_inline.h, iface/nips/nips_vm/state_parts.c, iface/nips/nips_vm/state_parts.h, iface/nips/nips_vm/timeval.h, iface/nips/nips_vm/tools.h: NIPS VM added to the SPOT distribution. * configure.ac, iface/Makefile.am: Build system updated for the NIPS front-end.
This commit is contained in:
parent
543190f2bc
commit
bc5f13bb4e
57 changed files with 11464 additions and 3 deletions
610
iface/nips/nips_vm/bytecode.c
Normal file
610
iface/nips/nips_vm/bytecode.c
Normal file
|
|
@ -0,0 +1,610 @@
|
|||
/* NIPS VM - New Implementation of Promela Semantics Virtual Machine
|
||||
* Copyright (C) 2005: Stefan Schuermans <stefan@schuermans.info>
|
||||
* Michael Weber <michaelw@i2.informatik.rwth-aachen.de>
|
||||
* Lehrstuhl fuer Informatik II, RWTH Aachen
|
||||
* Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bytecode.h"
|
||||
#include "tools.h"
|
||||
|
||||
|
||||
#ifdef EPROTO
|
||||
# define E_BC_INV_FMT EPROTO
|
||||
#else
|
||||
# define E_BC_INV_FMT EINVAL
|
||||
#endif
|
||||
|
||||
|
||||
// load bytecode module from file - check module name
|
||||
// returns -1 of error, 0 if not equal, 1 if equal
|
||||
static int bytecode_load_from_file_check_module( FILE *file, const char *module )
|
||||
{
|
||||
// read size of module name
|
||||
uint16_t mod_name_sz;
|
||||
if( fread( &mod_name_sz, 1, sizeof( mod_name_sz ), file ) != sizeof( mod_name_sz ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return -1;
|
||||
}
|
||||
mod_name_sz = be2h_16( mod_name_sz );
|
||||
if( mod_name_sz == 0 )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// read module name
|
||||
char mod_name[mod_name_sz];
|
||||
if( fread( mod_name, 1, mod_name_sz, file ) != mod_name_sz )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return -1;
|
||||
}
|
||||
mod_name[mod_name_sz - 1] = 0; // terminate string (should already be terminated there)
|
||||
|
||||
// compare module name (NULL matches any name)
|
||||
return module == NULL || strcmp( mod_name, module ) == 0;
|
||||
}
|
||||
|
||||
|
||||
// load bytecode module from file - read a string
|
||||
static char * bytecode_load_from_file_string( FILE *file )
|
||||
{
|
||||
// read size of string
|
||||
uint16_t str_sz;
|
||||
if( fread( &str_sz, 1, sizeof( str_sz ), file ) != sizeof( str_sz ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
str_sz = be2h_16( str_sz );
|
||||
if( str_sz == 0 )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// allocate memory
|
||||
char *str = (char *)malloc( str_sz );
|
||||
if( str == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read string
|
||||
if( fread( str, 1, str_sz, file ) != str_sz )
|
||||
{
|
||||
free( str );
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
str[str_sz - 1] = 0; // terminate string (should already be terminated there)
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
// load bytecode module from file - process module
|
||||
static st_bytecode * bytecode_load_from_file_module( FILE *file )
|
||||
{
|
||||
// read number of parts
|
||||
uint16_t part_cnt;
|
||||
if( fread( &part_cnt, 1, sizeof( part_cnt ), file ) != sizeof( part_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
part_cnt = be2h_16( part_cnt );
|
||||
|
||||
// allocate structure
|
||||
st_bytecode *bytecode = (st_bytecode *)malloc( sizeof( st_bytecode ) );
|
||||
if( bytecode == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
// initialize structure
|
||||
bytecode->modflags = 0;
|
||||
bytecode->size = 0;
|
||||
bytecode->ptr = NULL;
|
||||
bytecode->flag_cnt = 0;
|
||||
bytecode->flags = NULL;
|
||||
bytecode->string_cnt = 0;
|
||||
bytecode->strings = NULL;
|
||||
bytecode->src_loc_cnt = 0;
|
||||
bytecode->src_locs = NULL;
|
||||
bytecode->str_inf_cnt = 0;
|
||||
bytecode->str_infs = NULL;
|
||||
|
||||
uint16_t part_no;
|
||||
for( part_no = 0; part_no < part_cnt; part_no++ )
|
||||
{
|
||||
// read part type and part size
|
||||
char part_type[4];
|
||||
uint32_t part_sz;
|
||||
if( fread( &part_type, 1, sizeof( part_type ), file ) != sizeof( part_type ) ||
|
||||
fread( &part_sz, 1, sizeof( part_sz ), file ) != sizeof( part_sz ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
part_sz = be2h_32( part_sz );
|
||||
|
||||
// module flags
|
||||
if( memcmp( part_type, "modf", 4 ) == 0 )
|
||||
{
|
||||
uint32_t modflags;
|
||||
if( fread( &modflags, 1, sizeof( modflags ), file ) != sizeof( modflags ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->modflags |= be2h_32( modflags );
|
||||
}
|
||||
|
||||
// bytecode
|
||||
else if( memcmp( part_type, "bc ", 4 ) == 0 )
|
||||
{
|
||||
// two bytecodes in one module are invalid
|
||||
if( bytecode->ptr != NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
// allocate memory
|
||||
bytecode->size = part_sz;
|
||||
bytecode->ptr = (uint8_t *)malloc( bytecode->size == 0 ? 1 : bytecode->size );
|
||||
if( bytecode->ptr == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
// read bytecode
|
||||
if( fread( bytecode->ptr, 1, bytecode->size, file ) != bytecode->size )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// flag table
|
||||
else if( memcmp( part_type, "flag", 4 ) == 0 )
|
||||
{
|
||||
// two flag tables in one module are invalid
|
||||
if( bytecode->flags != NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
// read flag count
|
||||
uint16_t flag_cnt;
|
||||
if( fread( &flag_cnt, 1, sizeof( flag_cnt ), file ) != sizeof( flag_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->flag_cnt = be2h_16( flag_cnt );
|
||||
// allocate memory
|
||||
bytecode->flags = (st_bc_flag *)malloc( bytecode->flag_cnt == 0 ? 1 : bytecode->flag_cnt * sizeof( st_bc_flag ) );
|
||||
if( bytecode->flags == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
// read flag entries
|
||||
uint16_t i;
|
||||
for( i = 0; i < bytecode->flag_cnt; i++ )
|
||||
{
|
||||
uint32_t addr, flags;
|
||||
if( fread( &addr, 1, sizeof( addr ), file ) != sizeof( addr ) ||
|
||||
fread( &flags, 1, sizeof( flags ), file ) != sizeof( flags ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->flags[i].addr = be2h_32( addr );
|
||||
bytecode->flags[i].flags = be2h_32( flags );
|
||||
}
|
||||
if( i < bytecode->flag_cnt )
|
||||
break;
|
||||
}
|
||||
|
||||
// string table
|
||||
else if( memcmp( part_type, "str ", 4 ) == 0 )
|
||||
{
|
||||
// two string tables in one module are invalid
|
||||
if( bytecode->strings != NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
// read string count
|
||||
uint16_t string_cnt;
|
||||
if( fread( &string_cnt, 1, sizeof( string_cnt ), file ) != sizeof( string_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->string_cnt = be2h_16( string_cnt );
|
||||
// allocate memory
|
||||
bytecode->strings = (char **)malloc( bytecode->string_cnt == 0 ? 1 : bytecode->string_cnt * sizeof( char * ) );
|
||||
if( bytecode->strings == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
uint16_t i;
|
||||
for( i = 0; i < bytecode->string_cnt; i++ )
|
||||
bytecode->strings[i] = NULL;
|
||||
|
||||
// read strings
|
||||
for( i = 0; i < bytecode->string_cnt; i++ )
|
||||
{
|
||||
bytecode->strings[i] = bytecode_load_from_file_string( file );
|
||||
if( bytecode->strings[i] == NULL )
|
||||
break;
|
||||
}
|
||||
if( i < bytecode->string_cnt )
|
||||
break;
|
||||
}
|
||||
|
||||
// source location table
|
||||
else if( memcmp( part_type, "sloc", 4 ) == 0 )
|
||||
{
|
||||
// two source location tables in one module are invalid
|
||||
if( bytecode->src_locs != NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
// read source location count
|
||||
uint16_t src_loc_cnt;
|
||||
if( fread( &src_loc_cnt, 1, sizeof( src_loc_cnt ), file ) != sizeof( src_loc_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->src_loc_cnt = be2h_16( src_loc_cnt );
|
||||
// allocate memory
|
||||
bytecode->src_locs = (st_src_loc *)malloc( bytecode->src_loc_cnt == 0 ? 1 : bytecode->src_loc_cnt * sizeof( st_src_loc ) );
|
||||
if( bytecode->src_locs == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
// read source locations
|
||||
uint16_t i;
|
||||
for( i = 0; i < bytecode->src_loc_cnt; i++ )
|
||||
{
|
||||
uint32_t addr, line, col;
|
||||
if( fread( &addr, 1, sizeof( addr ), file ) != sizeof( addr ) ||
|
||||
fread( &line, 1, sizeof( line ), file ) != sizeof( line ) ||
|
||||
fread( &col, 1, sizeof( col ), file ) != sizeof( col ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->src_locs[i].addr = be2h_32( addr );
|
||||
bytecode->src_locs[i].line = be2h_32( line );
|
||||
bytecode->src_locs[i].col = be2h_32( col );
|
||||
}
|
||||
if( i < bytecode->src_loc_cnt )
|
||||
break;
|
||||
}
|
||||
|
||||
// structure information table
|
||||
else if( memcmp( part_type, "stin", 4 ) == 0 )
|
||||
{
|
||||
// two source location tables in one module are invalid
|
||||
if( bytecode->str_infs != NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
|
||||
// read structure information count
|
||||
uint16_t str_inf_cnt;
|
||||
if( fread( &str_inf_cnt, 1, sizeof( str_inf_cnt ), file ) != sizeof( str_inf_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
bytecode->str_inf_cnt = be2h_16( str_inf_cnt );
|
||||
|
||||
// allocate memory
|
||||
bytecode->str_infs = (st_str_inf *)malloc( bytecode->str_inf_cnt == 0 ? 1 : bytecode->str_inf_cnt * sizeof( st_str_inf ) );
|
||||
if( bytecode->src_locs == NULL )
|
||||
{
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
// read structure information
|
||||
uint16_t i;
|
||||
for( i = 0; i < bytecode->str_inf_cnt; i++ )
|
||||
{
|
||||
uint32_t addr;
|
||||
uint8_t code;
|
||||
if ( fread( &addr, 1, sizeof( addr ), file ) != sizeof( addr ) ||
|
||||
fread( &code, 1, sizeof( code ), file ) != sizeof( code ))
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
|
||||
// read type
|
||||
char *type = bytecode_load_from_file_string( file );
|
||||
if( type == NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
|
||||
// read name
|
||||
char *name = bytecode_load_from_file_string( file );
|
||||
if( name == NULL )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
break;
|
||||
}
|
||||
|
||||
bytecode->str_infs[i].addr = be2h_32( addr );
|
||||
bytecode->str_infs[i].code = code;
|
||||
bytecode->str_infs[i].type = type;
|
||||
bytecode->str_infs[i].name = name;
|
||||
}
|
||||
if( i < bytecode->str_inf_cnt )
|
||||
break;
|
||||
}
|
||||
|
||||
// unknown part
|
||||
else
|
||||
fseek( file, part_sz, SEEK_CUR );
|
||||
|
||||
} // for( part_no ...
|
||||
|
||||
// no bytecode found
|
||||
if( bytecode->ptr == NULL )
|
||||
{
|
||||
errno = ESRCH;
|
||||
// mark as error
|
||||
part_no = 0;
|
||||
part_cnt = 0;
|
||||
}
|
||||
|
||||
// some error occured in loop
|
||||
if( part_no < part_cnt || part_cnt == 0 )
|
||||
{
|
||||
// cleanup and return NULL (errno is already set)
|
||||
if( bytecode->ptr != NULL )
|
||||
free( bytecode->ptr );
|
||||
if( bytecode->flags != NULL )
|
||||
free( bytecode->flags );
|
||||
if( bytecode->strings != NULL )
|
||||
{
|
||||
uint16_t i;
|
||||
for( i = 0; i < bytecode->string_cnt; i++ )
|
||||
if( bytecode->strings[i] != NULL )
|
||||
free( bytecode->strings[i] );
|
||||
free( bytecode->strings );
|
||||
}
|
||||
if( bytecode->src_locs != NULL )
|
||||
free( bytecode->src_locs );
|
||||
free( bytecode );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bytecode;
|
||||
}
|
||||
|
||||
|
||||
// load bytecode module from file - process sections
|
||||
static st_bytecode * bytecode_load_from_file_sections( FILE *file, const char *module )
|
||||
{
|
||||
// get number of sections in file
|
||||
uint16_t sec_cnt;
|
||||
if( fread( &sec_cnt, 1, sizeof( sec_cnt ), file ) != sizeof( sec_cnt ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
sec_cnt = be2h_16( sec_cnt );
|
||||
|
||||
// read sections
|
||||
uint16_t sec_no;
|
||||
for( sec_no = 0; sec_no < sec_cnt; sec_no++ )
|
||||
{
|
||||
|
||||
// read section type and section size
|
||||
char sec_type[4];
|
||||
uint32_t sec_sz;
|
||||
if( fread( &sec_type, 1, sizeof( sec_type ), file ) != sizeof( sec_type ) ||
|
||||
fread( &sec_sz, 1, sizeof( sec_sz ), file ) != sizeof( sec_sz ) )
|
||||
{
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
sec_sz = be2h_32( sec_sz );
|
||||
|
||||
// module section
|
||||
if( memcmp( sec_type, "mod ", 4 ) == 0 )
|
||||
{
|
||||
// remember position in file
|
||||
long pos = ftell( file );
|
||||
|
||||
// check if module name matches
|
||||
int result = bytecode_load_from_file_check_module( file, module );
|
||||
if( result < 0 ) // error
|
||||
return NULL;
|
||||
if( result > 0 ) // module name matches
|
||||
return bytecode_load_from_file_module( file );
|
||||
|
||||
// skip module
|
||||
fseek( file, pos + sec_sz, SEEK_SET );
|
||||
}
|
||||
|
||||
// unknown section
|
||||
else
|
||||
fseek( file, sec_sz, SEEK_CUR );
|
||||
|
||||
} // for( sec_no ...
|
||||
|
||||
errno = ESRCH;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// load bytecode module from file
|
||||
// if module == NULL the first module is loaded
|
||||
// returns NULL on error (errno ist set in this case)
|
||||
st_bytecode * bytecode_load_from_file( const char *filename, const char *module ) // extern
|
||||
{
|
||||
// open bytecode file for reading
|
||||
FILE *file = fopen( filename, "rb" );
|
||||
if( file == NULL )
|
||||
return NULL;
|
||||
|
||||
// magic to check at beginning of bytecode
|
||||
static char bc_magic[8] = "NIPS v2 ";
|
||||
|
||||
// read magic
|
||||
char magic[sizeof( bc_magic )];
|
||||
if( fread( magic, 1, sizeof( magic ), file ) != sizeof( magic ) )
|
||||
{
|
||||
fclose( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check magic
|
||||
if( memcmp( bc_magic, magic, sizeof( bc_magic ) ) != 0 )
|
||||
{
|
||||
fclose( file );
|
||||
errno = E_BC_INV_FMT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// process sections
|
||||
st_bytecode *bytecode = bytecode_load_from_file_sections( file, module );
|
||||
fclose( file );
|
||||
return bytecode;
|
||||
}
|
||||
|
||||
|
||||
// unload bytecode
|
||||
void bytecode_unload( st_bytecode *bytecode ) // extern
|
||||
{
|
||||
free( bytecode->ptr );
|
||||
uint16_t i;
|
||||
if( bytecode->flags != NULL )
|
||||
free( bytecode->flags );
|
||||
if( bytecode->strings != NULL )
|
||||
{
|
||||
for( i = 0; i < bytecode->string_cnt; i++ )
|
||||
free( bytecode->strings[i] );
|
||||
free( bytecode->strings );
|
||||
}
|
||||
if( bytecode->src_locs != NULL )
|
||||
free( bytecode->src_locs );
|
||||
if (bytecode->str_infs != NULL)
|
||||
free(bytecode->str_infs);
|
||||
free( bytecode );
|
||||
}
|
||||
|
||||
|
||||
// check if a monitor process exists in bytecode
|
||||
int bytecode_monitor_present( st_bytecode *bytecode ) // extern
|
||||
{
|
||||
return (bytecode->modflags & BC_MODFLAG_MONITOR) != 0;
|
||||
}
|
||||
|
||||
|
||||
// get flags at address (e.g. program counter)
|
||||
uint32_t bytecode_flags( st_bytecode *bytecode, uint32_t addr ) // extern
|
||||
{
|
||||
int start, end, i;
|
||||
|
||||
start = 0;
|
||||
end = bytecode->flag_cnt - 1;
|
||||
while( start <= end )
|
||||
{
|
||||
i = (start + end) / 2;
|
||||
if( addr < bytecode->flags[i].addr )
|
||||
end = i - 1;
|
||||
else if( addr > bytecode->flags[i].addr )
|
||||
start = i + 1;
|
||||
else
|
||||
return bytecode->flags[i].flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// get source location from address (e.g. program counter)
|
||||
// TODO: change to same interface as bytecode_str_inf
|
||||
st_src_loc bytecode_src_loc( st_bytecode *bytecode, uint32_t addr ) // extern
|
||||
{
|
||||
int start, end, i;
|
||||
|
||||
if( bytecode->src_loc_cnt < 1 )
|
||||
return (st_src_loc){ .addr = addr, .line = -1, .col = -1 };
|
||||
|
||||
start = 0;
|
||||
end = bytecode->src_loc_cnt - 1;
|
||||
for( ; ; )
|
||||
{
|
||||
i = (start + end) / 2;
|
||||
if( addr < bytecode->src_locs[i].addr )
|
||||
{
|
||||
if( i - 1 < start )
|
||||
return bytecode->src_locs[i > 0 ? i - 1 : 0];
|
||||
end = i - 1;
|
||||
}
|
||||
else if( addr > bytecode->src_locs[i].addr )
|
||||
{
|
||||
if( i + 1 > end )
|
||||
return bytecode->src_locs[end];
|
||||
start = i + 1;
|
||||
}
|
||||
else
|
||||
return bytecode->src_locs[i];
|
||||
}
|
||||
}
|
||||
|
||||
// get structure information from address (e.g. program counter), NULL if not found
|
||||
|
||||
// *start denotes where to start search, and if found, is modified to
|
||||
// the next valid start position. Multiple records can be retrieved like this:
|
||||
// unsigned int seq = 0;
|
||||
// while ((s_inf = bytecode_str_inf (bc, addr, &seq)) != NULL) {
|
||||
// /* stuff with *s_inf */
|
||||
// }
|
||||
|
||||
// ASSUMES str_infs sorted by addr field
|
||||
// TODO: replace linear search with binary search
|
||||
extern st_str_inf *
|
||||
bytecode_str_inf( st_bytecode *bytecode, uint32_t addr, unsigned int *start)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = *start; i < bytecode->str_inf_cnt; ++i)
|
||||
{
|
||||
if (bytecode->str_infs[i].addr == addr) {
|
||||
*start = i+1;
|
||||
return &bytecode->str_infs[i];
|
||||
} else if (bytecode->str_infs[i].addr > addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue