@ -470,9 +470,9 @@ ctf_symtypetab_sect_sizes (ctf_dict_t *fp, emit_symtypetab_state_t *s,
filter out reported symbols from the variable section , and filter out all
other symbols from the symtypetab sections . ( If we are not linking , the
symbols are sorted ; if we are linking , don ' t bother sorting if we are not
filtering out reported symbols : this is almost certaily an ld - r and only
filtering out reported symbols : this is almost certain ly an ld - r and only
the linker is likely to consume these symtypetabs again . The linker
doesn ' t care what order the symtypetab entries is in , since it only
doesn ' t care what order the symtypetab entries are in , since it only
iterates over symbols and does not use the ctf_lookup_by_symbol * API . ) */
s - > sort_syms = 1 ;
@ -718,8 +718,8 @@ symerr:
/* Type section. */
/* Iterate through the dynamic type definition list and compute the
size of the CTF type section . */
/* Iterate through the static types and the dynamic type definition list and
compute the size of the CTF type section . */
static size_t
ctf_type_sect_size ( ctf_dict_t * fp )
@ -778,7 +778,7 @@ ctf_type_sect_size (ctf_dict_t *fp)
}
}
return type_size ;
return type_size + fp - > ctf_header - > cth_stroff - fp - > ctf_header - > cth_typeoff ;
}
/* Take a final lap through the dynamic type definition list and copy the
@ -933,30 +933,22 @@ ctf_sort_var (const void *one_, const void *two_, void *arg_)
/* Overall serialization. */
/* If the specified CTF dict is writable and has been modified, reload this dict
with the updated type definitions , ready for serialization . In order to make
this code and the rest of libctf as simple as possible , we perform updates by
taking the dynamic type definitions and creating an in - memory CTF dict
containing the definitions , and then call ctf_simple_open_internal ( ) on it .
We perform one extra trick here for the benefit of callers and to keep our
code simple : ctf_simple_open_internal ( ) will return a new ctf_dict_t , but we
want to keep the fp constant for the caller , so after
ctf_simple_open_internal ( ) returns , we use memcpy to swap the interior of the
old and new ctf_dict_t ' s , and then free the old .
We do not currently support serializing a dict that has already been
serialized in the past : but all the tables support it except for the types
table . */
/* Emit a new CTF dict which is a serialized copy of this one: also reify
the string table and update all offsets in the current dict suitably .
( This simplifies ctf - string . c a little , at the cost of storing a second
copy of the strtab if this dict was originally read in via ctf_open . )
int
ctf_serialize ( ctf_dict_t * fp )
Other aspects of the existing dict are unchanged , although some
static entries may be duplicated in the dynamic state ( which should
have no effect on visible operation ) . */
static unsigned char *
ctf_serialize ( ctf_dict_t * fp , size_t * bufsiz )
{
ctf_dict_t ofp , * nfp ;
ctf_header_t hdr , * hdrp ;
ctf_dvdef_t * dvd ;
ctf_varent_t * dvarents ;
const ctf_strs_writable_t * strtab ;
int err ;
int sym_functions = 0 ;
unsigned char * t ;
@ -969,13 +961,6 @@ ctf_serialize (ctf_dict_t *fp)
emit_symtypetab_state_t symstate ;
memset ( & symstate , 0 , sizeof ( emit_symtypetab_state_t ) ) ;
/* This isn't a very nice error code, but it's close enough: it's what you
get if you try to modify a type loaded out of a serialized dict , so
it makes at least a little sense that it ' s what you get if you try to
reserialize the dict again . */
if ( fp - > ctf_stypes > 0 )
return ( ctf_set_errno ( fp , ECTF_RDONLY ) ) ;
/* Fill in an initial CTF header. We will leave the label, object,
and function sections empty and only output a header , type section ,
and string table . The type section begins at a 4 - byte aligned
@ -993,7 +978,7 @@ ctf_serialize (ctf_dict_t *fp)
/* Propagate all symbols in the symtypetabs into the dynamic state, so that
we can put them back in the right order . Symbols already in the dynamic
state are left as they are . */
state , likely due to repeated serialization , are left unchanged . */
do
{
ctf_next_t * it = NULL ;
@ -1004,17 +989,17 @@ ctf_serialize (ctf_dict_t *fp)
sym_functions ) ) ! = CTF_ERR )
if ( ( ctf_add_funcobjt_sym_forced ( fp , sym_functions , sym_name , sym ) ) < 0 )
if ( ctf_errno ( fp ) ! = ECTF_DUPLICATE )
return - 1 ; /* errno is set for us. */
return NULL ; /* errno is set for us. */
if ( ctf_errno ( fp ) ! = ECTF_NEXT_END )
return - 1 ; /* errno is set for us. */
return NULL ; /* errno is set for us. */
} while ( sym_functions + + < 1 ) ;
/* Figure out how big the symtypetabs are now. */
if ( ctf_symtypetab_sect_sizes ( fp , & symstate , & hdr , & objt_size , & func_size ,
& objtidx_size , & funcidx_size ) < 0 )
return - 1 ; /* errno is set for us. */
return NULL ; /* errno is set for us. */
/* Propagate all vars into the dynamic state, so we can put them back later.
Variables already in the dynamic state , likely due to repeated
@ -1026,7 +1011,7 @@ ctf_serialize (ctf_dict_t *fp)
if ( name ! = NULL & & ! ctf_dvd_lookup ( fp , name ) )
if ( ctf_add_variable_forced ( fp , name , fp - > ctf_vars [ i ] . ctv_type ) < 0 )
return - 1 ; /* errno is set for us. */
return NULL ; /* errno is set for us. */
}
for ( nvars = 0 , dvd = ctf_list_next ( & fp - > ctf_dvdefs ) ;
@ -1050,7 +1035,10 @@ ctf_serialize (ctf_dict_t *fp)
buf_size = sizeof ( ctf_header_t ) + hdr . cth_stroff + hdr . cth_strlen ;
if ( ( buf = malloc ( buf_size ) ) = = NULL )
return ( ctf_set_errno ( fp , EAGAIN ) ) ;
{
ctf_set_errno ( fp , EAGAIN ) ;
return NULL ;
}
memcpy ( buf , & hdr , sizeof ( ctf_header_t ) ) ;
t = ( unsigned char * ) buf + sizeof ( ctf_header_t ) + hdr . cth_objtoff ;
@ -1085,6 +1073,11 @@ ctf_serialize (ctf_dict_t *fp)
assert ( t = = ( unsigned char * ) buf + sizeof ( ctf_header_t ) + hdr . cth_typeoff ) ;
/* Copy in existing static types, then emit new dynamic types. */
memcpy ( t , fp - > ctf_buf + fp - > ctf_header - > cth_typeoff ,
fp - > ctf_header - > cth_stroff - fp - > ctf_header - > cth_typeoff ) ;
t + = fp - > ctf_header - > cth_stroff - fp - > ctf_header - > cth_typeoff ;
ctf_emit_type_sect ( fp , & t ) ;
assert ( t = = ( unsigned char * ) buf + sizeof ( ctf_header_t ) + hdr . cth_stroff ) ;
@ -1111,136 +1104,15 @@ ctf_serialize (ctf_dict_t *fp)
hdrp = ( ctf_header_t * ) buf ;
hdrp - > cth_strlen = strtab - > cts_len ;
buf_size + = hdrp - > cth_strlen ;
* bufsiz = buf_size ;
/* Finally, we are ready to ctf_simple_open() the new dict. If this is
successful , we then switch nfp and fp and free the old dict . */
if ( ( nfp = ctf_simple_open_internal ( ( char * ) buf , buf_size , NULL , 0 ,
0 , NULL , 0 , fp - > ctf_syn_ext_strtab ,
fp - > ctf_str_atoms , & err ) ) = = NULL )
{
free ( buf ) ;
return ( ctf_set_errno ( fp , err ) ) ;
}
( void ) ctf_setmodel ( nfp , ctf_getmodel ( fp ) ) ;
nfp - > ctf_parent = fp - > ctf_parent ;
nfp - > ctf_parent_unreffed = fp - > ctf_parent_unreffed ;
nfp - > ctf_refcnt = fp - > ctf_refcnt ;
if ( nfp - > ctf_dynbase = = NULL )
nfp - > ctf_dynbase = buf ; /* Make sure buf is freed on close. */
nfp - > ctf_dthash = fp - > ctf_dthash ;
nfp - > ctf_dtdefs = fp - > ctf_dtdefs ;
nfp - > ctf_dvhash = fp - > ctf_dvhash ;
nfp - > ctf_dvdefs = fp - > ctf_dvdefs ;
nfp - > ctf_dtoldid = fp - > ctf_dtoldid ;
nfp - > ctf_add_processing = fp - > ctf_add_processing ;
nfp - > ctf_snapshots = fp - > ctf_snapshots + 1 ;
nfp - > ctf_specific = fp - > ctf_specific ;
nfp - > ctf_nfuncidx = fp - > ctf_nfuncidx ;
nfp - > ctf_nobjtidx = fp - > ctf_nobjtidx ;
nfp - > ctf_objthash = fp - > ctf_objthash ;
nfp - > ctf_funchash = fp - > ctf_funchash ;
nfp - > ctf_dynsyms = fp - > ctf_dynsyms ;
nfp - > ctf_ptrtab = fp - > ctf_ptrtab ;
nfp - > ctf_pptrtab = fp - > ctf_pptrtab ;
nfp - > ctf_typemax = fp - > ctf_typemax ;
nfp - > ctf_stypes = fp - > ctf_stypes ;
nfp - > ctf_dynsymidx = fp - > ctf_dynsymidx ;
nfp - > ctf_dynsymmax = fp - > ctf_dynsymmax ;
nfp - > ctf_ptrtab_len = fp - > ctf_ptrtab_len ;
nfp - > ctf_pptrtab_len = fp - > ctf_pptrtab_len ;
nfp - > ctf_link_inputs = fp - > ctf_link_inputs ;
nfp - > ctf_link_outputs = fp - > ctf_link_outputs ;
nfp - > ctf_errs_warnings = fp - > ctf_errs_warnings ;
nfp - > ctf_funcidx_names = fp - > ctf_funcidx_names ;
nfp - > ctf_objtidx_names = fp - > ctf_objtidx_names ;
nfp - > ctf_funcidx_sxlate = fp - > ctf_funcidx_sxlate ;
nfp - > ctf_objtidx_sxlate = fp - > ctf_objtidx_sxlate ;
nfp - > ctf_str_prov_offset = fp - > ctf_str_prov_offset ;
nfp - > ctf_syn_ext_strtab = fp - > ctf_syn_ext_strtab ;
nfp - > ctf_pptrtab_typemax = fp - > ctf_pptrtab_typemax ;
nfp - > ctf_in_flight_dynsyms = fp - > ctf_in_flight_dynsyms ;
nfp - > ctf_link_in_cu_mapping = fp - > ctf_link_in_cu_mapping ;
nfp - > ctf_link_out_cu_mapping = fp - > ctf_link_out_cu_mapping ;
nfp - > ctf_link_type_mapping = fp - > ctf_link_type_mapping ;
nfp - > ctf_link_memb_name_changer = fp - > ctf_link_memb_name_changer ;
nfp - > ctf_link_memb_name_changer_arg = fp - > ctf_link_memb_name_changer_arg ;
nfp - > ctf_link_variable_filter = fp - > ctf_link_variable_filter ;
nfp - > ctf_link_variable_filter_arg = fp - > ctf_link_variable_filter_arg ;
nfp - > ctf_symsect_little_endian = fp - > ctf_symsect_little_endian ;
nfp - > ctf_link_flags = fp - > ctf_link_flags ;
nfp - > ctf_dedup_atoms = fp - > ctf_dedup_atoms ;
nfp - > ctf_dedup_atoms_alloc = fp - > ctf_dedup_atoms_alloc ;
memcpy ( & nfp - > ctf_dedup , & fp - > ctf_dedup , sizeof ( fp - > ctf_dedup ) ) ;
nfp - > ctf_snapshot_lu = fp - > ctf_snapshots ;
memcpy ( & nfp - > ctf_lookups , fp - > ctf_lookups , sizeof ( fp - > ctf_lookups ) ) ;
nfp - > ctf_structs = fp - > ctf_structs ;
nfp - > ctf_unions = fp - > ctf_unions ;
nfp - > ctf_enums = fp - > ctf_enums ;
nfp - > ctf_names = fp - > ctf_names ;
fp - > ctf_dthash = NULL ;
ctf_str_free_atoms ( nfp ) ;
nfp - > ctf_str_atoms = fp - > ctf_str_atoms ;
nfp - > ctf_prov_strtab = fp - > ctf_prov_strtab ;
nfp - > ctf_dynstrtab = fp - > ctf_dynstrtab ;
nfp - > ctf_str_movable_refs = fp - > ctf_str_movable_refs ;
fp - > ctf_str_atoms = NULL ;
fp - > ctf_prov_strtab = NULL ;
fp - > ctf_dynstrtab = NULL ;
fp - > ctf_str_movable_refs = NULL ;
memset ( & fp - > ctf_dtdefs , 0 , sizeof ( ctf_list_t ) ) ;
memset ( & fp - > ctf_errs_warnings , 0 , sizeof ( ctf_list_t ) ) ;
fp - > ctf_add_processing = NULL ;
fp - > ctf_ptrtab = NULL ;
fp - > ctf_pptrtab = NULL ;
fp - > ctf_funcidx_names = NULL ;
fp - > ctf_objtidx_names = NULL ;
fp - > ctf_funcidx_sxlate = NULL ;
fp - > ctf_objtidx_sxlate = NULL ;
fp - > ctf_objthash = NULL ;
fp - > ctf_funchash = NULL ;
fp - > ctf_dynsyms = NULL ;
fp - > ctf_dynsymidx = NULL ;
fp - > ctf_link_inputs = NULL ;
fp - > ctf_link_outputs = NULL ;
fp - > ctf_syn_ext_strtab = NULL ;
fp - > ctf_link_in_cu_mapping = NULL ;
fp - > ctf_link_out_cu_mapping = NULL ;
fp - > ctf_link_type_mapping = NULL ;
fp - > ctf_dedup_atoms = NULL ;
fp - > ctf_dedup_atoms_alloc = NULL ;
fp - > ctf_parent_unreffed = 1 ;
fp - > ctf_dvhash = NULL ;
memset ( & fp - > ctf_dvdefs , 0 , sizeof ( ctf_list_t ) ) ;
memset ( fp - > ctf_lookups , 0 , sizeof ( fp - > ctf_lookups ) ) ;
memset ( & fp - > ctf_in_flight_dynsyms , 0 , sizeof ( fp - > ctf_in_flight_dynsyms ) ) ;
memset ( & fp - > ctf_dedup , 0 , sizeof ( fp - > ctf_dedup ) ) ;
fp - > ctf_structs = NULL ;
fp - > ctf_unions = NULL ;
fp - > ctf_enums = NULL ;
fp - > ctf_names = NULL ;
memcpy ( & ofp , fp , sizeof ( ctf_dict_t ) ) ;
memcpy ( fp , nfp , sizeof ( ctf_dict_t ) ) ;
memcpy ( nfp , & ofp , sizeof ( ctf_dict_t ) ) ;
nfp - > ctf_refcnt = 1 ; /* Force nfp to be freed. */
ctf_dict_close ( nfp ) ;
return 0 ;
return buf ;
oom :
free ( buf ) ;
return ( ctf_set_errno ( fp , EAGAIN ) ) ;
ctf_set_errno ( fp , EAGAIN ) ;
err :
free ( buf ) ;
return - 1 ; /* errno is set for us. */
return NULL ; /* errno is set for us. */
}
/* File writing. */
@ -1255,30 +1127,27 @@ err:
int
ctf_gzwrite ( ctf_dict_t * fp , gzFile fd )
{
const unsigned char * buf ;
ssize_t resid ;
ssize_t len ;
unsigned char * buf ;
unsigned char * p ;
size_t bufsiz ;
size_t len , written = 0 ;
resid = sizeof ( ctf_header_t ) ;
buf = ( unsigned char * ) fp - > ctf_header ;
while ( resid ! = 0 )
{
if ( ( len = gzwrite ( fd , buf , resid ) ) < = 0 )
return ( ctf_set_errno ( fp , errno ) ) ;
resid - = len ;
buf + = len ;
}
if ( ( buf = ctf_serialize ( fp , & bufsiz ) ) = = NULL )
return - 1 ; /* errno is set for us. */
resid = fp - > ctf_size ;
buf = fp - > ctf_buf ;
while ( resid ! = 0 )
p = buf ;
while ( written < bufsiz )
{
if ( ( len = gzwrite ( fd , buf , resid ) ) < = 0 )
return ( ctf_set_errno ( fp , errno ) ) ;
resid - = len ;
buf + = len ;
if ( ( len = gzwrite ( fd , p , bufsiz - written ) ) < = 0 )
{
free ( buf ) ;
return ( ctf_set_errno ( fp , errno ) ) ;
}
written + = len ;
p + = len ;
}
free ( buf ) ;
return 0 ;
}
@ -1288,88 +1157,95 @@ ctf_gzwrite (ctf_dict_t *fp, gzFile fd)
unsigned char *
ctf_write_mem ( ctf_dict_t * fp , size_t * size , size_t threshold )
{
unsigned char * buf ;
unsigned char * rawbuf ;
unsigned char * buf = NULL ;
unsigned char * bp ;
ctf_header_t * hp ;
unsigned char * flipped , * src ;
ssize_t header_len = sizeof ( ctf_header_t ) ;
ssize_t compress_len ;
ctf_header_t * rawhp , * hp ;
unsigned char * src ;
size_t rawbufsiz ;
size_t alloc_len = 0 ;
int uncompressed = 0 ;
int flip_endian ;
int uncompressed ;
int rc ;
flip_endian = getenv ( " LIBCTF_WRITE_FOREIGN_ENDIAN " ) ! = NULL ;
uncompressed = ( fp - > ctf_size < threshold ) ;
if ( ctf_serialize ( fp ) < 0 )
if ( ( rawbuf = ctf_serialize ( fp , & rawbufsiz ) ) = = NULL )
return NULL ; /* errno is set for us. */
compress_len = compressBound ( fp - > ctf_size ) ;
if ( fp - > ctf_size < threshold )
compress_len = fp - > ctf_size ;
if ( ( buf = malloc ( compress_len
+ sizeof ( struct ctf_header ) ) ) = = NULL )
if ( ! ctf_assert ( fp , rawbufsiz > = sizeof ( ctf_header_t ) ) )
goto err ;
if ( rawbufsiz > = threshold )
alloc_len = compressBound ( rawbufsiz - sizeof ( ctf_header_t ) )
+ sizeof ( ctf_header_t ) ;
/* Trivial operation if the buffer is incompressible or too small to bother
compressing , and we ' re not doing a forced write - time flip . */
if ( rawbufsiz < threshold | | rawbufsiz < alloc_len )
{
alloc_len = rawbufsiz ;
uncompressed = 1 ;
}
if ( ! flip_endian & & uncompressed )
{
* size = rawbufsiz ;
return rawbuf ;
}
if ( ( buf = malloc ( alloc_len ) ) = = NULL )
{
ctf_set_errno ( fp , ENOMEM ) ;
ctf_err_warn ( fp , 0 , 0 , _ ( " ctf_write_mem: cannot allocate %li bytes " ) ,
( unsigned long ) ( compress_len + sizeof ( struct ctf_header ) ) ) ;
return NULL ;
( unsigned long ) ( alloc_len ) ) ;
goto err ;
}
rawhp = ( ctf_header_t * ) rawbuf ;
hp = ( ctf_header_t * ) buf ;
memcpy ( hp , fp - > ctf_header , header_len ) ;
bp = buf + sizeof ( struct ctf_header ) ;
* size = sizeof ( struct ctf_header ) ;
memcpy ( hp , rawbuf , sizeof ( ctf_header_t ) ) ;
bp = buf + sizeof ( ctf_header_t ) ;
* size = sizeof ( ctf_header_t ) ;
if ( uncompressed )
hp - > cth_flags & = ~ CTF_F_COMPRESS ;
else
if ( ! uncompressed )
hp - > cth_flags | = CTF_F_COMPRESS ;
src = fp - > ctf_buf ;
flipped = NULL ;
src = rawbuf + sizeof ( ctf_header_t ) ;
if ( flip_endian )
{
if ( ( flipped = malloc ( fp - > ctf_size ) ) = = NULL )
{
ctf_set_errno ( fp , ENOMEM ) ;
ctf_err_warn ( fp , 0 , 0 , _ ( " ctf_write_mem: cannot allocate %li bytes " ) ,
( unsigned long ) ( fp - > ctf_size + sizeof ( struct ctf_header ) ) ) ;
return NULL ;
}
ctf_flip_header ( hp ) ;
memcpy ( flipped , fp - > ctf_buf , fp - > ctf_size ) ;
if ( ctf_flip ( fp , fp - > ctf_header , flipped , 1 ) < 0 )
{
free ( buf ) ;
free ( flipped ) ;
return NULL ; /* errno is set for us. */
}
src = flipped ;
if ( ctf_flip ( fp , rawhp , src , 1 ) < 0 )
goto err ; /* errno is set for us. */
}
if ( uncompressed )
{
memcpy ( bp , src , fp - > ctf_size ) ;
* size + = fp - > ctf_size ;
}
else
if ( ! uncompressed )
{
size_t compress_len = alloc_len - sizeof ( ctf_header_t ) ;
if ( ( rc = compress ( bp , ( uLongf * ) & compress_len ,
src , fp - > ctf_size ) ) ! = Z_OK )
src , rawbufsiz - sizeof ( ctf_header_t ) ) ) ! = Z_OK )
{
ctf_set_errno ( fp , ECTF_COMPRESS ) ;
ctf_err_warn ( fp , 0 , 0 , _ ( " zlib deflate err: %s " ) , zError ( rc ) ) ;
free ( buf ) ;
return NULL ;
goto err ;
}
* size + = compress_len ;
}
else
{
memcpy ( bp , src , rawbufsiz - sizeof ( ctf_header_t ) ) ;
* size + = rawbufsiz - sizeof ( ctf_header_t ) ;
}
free ( flipped ) ;
free ( rawbuf ) ;
return buf ;
err :
free ( buf ) ;
free ( rawbuf ) ;
return NULL ;
}
/* Compress the specified CTF data stream and write it to the specified file