Compare commits

...

3 Commits

Author SHA1 Message Date
Rishi Raj
31ff5e249d lto: Fixed test(U*) used but never defined error.
This Patch fixes the error during bootstrapped build.

gcc/ChangeLog:

        * lto-object.cc:

gcc/lto/ChangeLog:

        * lto-lang.cc:

Signed-off-by: Rishi Raj <rishiraj45035@gmail.com>
2023-07-07 10:21:38 +05:30
Rishi Raj
48ef456a8e libiberty: lto: Addition of .symtab in elf file.
This patch is continutaion of previous patch (bypass-asm: Bypass assembler when
    generating LTO object files.).
    Now the emitted object file contains .symtab along with __gnu_lto_slim symbol.

gcc/ChangeLog:

        * lto-object.cc (lto_obj_file_close):

include/ChangeLog:

        * simple-object.h (simple_object_write_add_symbol):

libiberty/ChangeLog:

        * simple-object-common.h (struct simple_object_symbol_struct):
        * simple-object-elf.c (simple_object_elf_write_ehdr):
        (simple_object_elf_write_symbol):
        (simple_object_elf_write_to_file):
        * simple-object.c (simple_object_start_write):
        (simple_object_write_add_symbol):
        (simple_object_release_write):

Signed-off-by: Rishi Raj <rishiraj45035@gmail.com>
2023-07-06 18:44:40 +05:30
Rishi Raj
b13c0682ab lto: Bypass assembler when generating LTO object files.
This patch applies Jan Hubicka previous patch on current sources.
    Now compiler is able to produce object files without assembler although
    a lot of things are missing such as __lto_slim symbol, debug symbols
    etc. They will be added in future patches. To test this current patch,
    use these command below.
    1) ./xgcc -B ./ -O3 a.c -flto -S -fbypass-asm=crtbegin.o  -o a.o
    2) ./xgcc -B ./ -O2 a.o -flto
    3)  ./a.out

    We are currntly working with elf-only support (mach-o, coff, xcoff etc
    will be dealt later) so this will only work on a linux machine. I have tested
    this on my machine ( Arch linux, Machine: Advanced Micro Devices X86-64) and
    all LTO test cases passed as expected.

    gcc/ChangeLog:

            * Makefile.in:
            * common.opt:
            * langhooks.cc (lhd_begin_section):
            (lhd_append_data):
            (lhd_end_section):
            * lto/lto-object.cc: Moved to...
            * lto-object.cc: ...here.
            * lto-streamer.h (struct lto_section_slot):
            (struct lto_section_list):
            (struct lto_file):
            (lto_obj_file_open):
            (lto_obj_file_close):
            (lto_obj_build_section_table):
            (lto_obj_create_section_hash_table):
            (lto_obj_begin_section):
            (lto_obj_append_data):
            (lto_obj_end_section):
            (lto_set_current_out_file):
            (lto_get_current_out_file):
            * toplev.cc (compile_file):
            (lang_dependent_init):

    gcc/lto/ChangeLog:

            * Make-lang.in:
            * lto-common.cc (lto_file_read):
            * lto-lang.cc:
            * lto.h (struct lto_file):
            (lto_obj_file_open):
            (lto_obj_file_close):
            (struct lto_section_list):
            (lto_obj_build_section_table):
            (lto_obj_create_section_hash_table):
            (lto_obj_begin_section):
            (lto_obj_append_data):
            (lto_obj_end_section):
            (lto_set_current_out_file):
            (lto_get_current_out_file):
            (struct lto_section_slot):

Signed-off-by: Rishi Raj <rishiraj45035@gmail.com>
2023-07-06 18:43:51 +05:30
14 changed files with 313 additions and 57 deletions

View File

@@ -1560,6 +1560,7 @@ OBJS = \
lto-section-out.o \
lto-opts.o \
lto-compress.o \
lto-object.o \
mcf.o \
mode-switching.o \
modulo-sched.o \

View File

@@ -1169,6 +1169,9 @@ fbtr-bb-exclusive
Common Ignore
Does nothing. Preserved for backward compatibility.
fbypass-asm=
Common Joined Var(flag_bypass_asm)
fcallgraph-info
Common RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO);
Output callgraph information on a per-file basis.

View File

@@ -38,6 +38,10 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "cgraph.h"
#include "debug.h"
#include "function.h"
#include "basic-block.h"
#include "gimple.h"
#include "lto-streamer.h"
/* Do nothing; in many cases the default hook. */
@@ -817,6 +821,19 @@ lhd_begin_section (const char *name)
{
section *section;
if (flag_bypass_asm)
{
static int initialized = false;
if (!initialized)
{
gcc_assert (asm_out_file == NULL);
lto_set_current_out_file (lto_obj_file_open (asm_file_name, true));
initialized = true;
}
lto_obj_begin_section (name);
return;
}
/* Save the old section so we can restore it in lto_end_asm_section. */
gcc_assert (!saved_section);
saved_section = in_section;
@@ -833,8 +850,13 @@ lhd_begin_section (const char *name)
implementation just calls assemble_string. */
void
lhd_append_data (const void *data, size_t len, void *)
lhd_append_data (const void *data, size_t len, void *v)
{
if (flag_bypass_asm)
{
lto_obj_append_data (data, len, v);
return;
}
if (data)
{
timevar_push (TV_IPA_LTO_OUTPUT);
@@ -851,6 +873,11 @@ lhd_append_data (const void *data, size_t len, void *)
void
lhd_end_section (void)
{
if (flag_bypass_asm)
{
lto_obj_end_section ();
return;
}
if (saved_section)
{
switch_to_section (saved_section);

View File

@@ -21,9 +21,18 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "basic-block.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "gimple-expr.h"
#include "is-a.h"
#include "function.h"
#include "gimple.h"
#include "diagnostic-core.h"
#include "lto.h"
#include "tm.h"
#include "cgraph.h"
#include "lto-streamer.h"
#include "lto-section-names.h"
#include "simple-object.h"
@@ -133,7 +142,13 @@ lto_obj_file_open (const char *filename, bool writable)
}
else
{
gcc_assert (saved_attributes != NULL);
if (!saved_attributes)
{
lto_file *tmp = lto_obj_file_open (flag_bypass_asm, false);
if (!tmp)
goto fail;
lto_obj_file_close (tmp);
}
lo->sobj_w = simple_object_start_write (saved_attributes,
LTO_SEGMENT_NAME,
&errmsg, &err);
@@ -148,7 +163,8 @@ fail_errmsg:
error ("%s: %s", fname, errmsg);
else
error ("%s: %s: %s", fname, errmsg, xstrerror (err));
fail:
if (lo->fd != -1)
lto_obj_file_close ((lto_file *) lo);
free (lo);
@@ -172,7 +188,8 @@ lto_obj_file_close (lto_file *file)
int err;
gcc_assert (lo->base.offset == 0);
/*Add __gnu_lto_slim symbol*/
simple_object_write_add_symbol (lo->sobj_w, "__gnu_lto_slim",1,1);
errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err);
if (errmsg != NULL)
{
@@ -255,15 +272,15 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
the start and size of each section in the .o file. */
htab_t
lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list)
lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list,
htab_t section_hash_table)
{
struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
htab_t section_hash_table;
struct lto_obj_add_section_data loasd;
const char *errmsg;
int err;
section_hash_table = lto_obj_create_section_hash_table ();
gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
loasd.section_hash_table = section_hash_table;

View File

@@ -764,6 +764,30 @@ public:
lto_location_cache location_cache;
};
/* Hash table entry to hold the start offset and length of an LTO
section in a .o file. */
struct lto_section_slot
{
const char *name;
intptr_t start;
size_t len;
struct lto_section_slot *next;
};
/* A list of section slots */
struct lto_section_list
{
struct lto_section_slot *first, *last;
};
/* A file. */
struct lto_file
{
/* The name of the file. */
const char *filename;
/* The offset for the object inside an ar archive file (or zero). */
off_t offset;
};
/* In lto-section-in.cc */
extern class lto_input_block * lto_create_simple_input_block (
@@ -903,6 +927,17 @@ void lto_output_location_and_block (struct output_block *, struct bitpack_d *,
void lto_output_init_mode_table (void);
void lto_prepare_function_for_streaming (cgraph_node *);
/* In lto-elf.c or lto-coff.c */
extern lto_file *lto_obj_file_open (const char *filename, bool writable);
extern void lto_obj_file_close (lto_file *file);
struct lto_section_list;
extern htab_t lto_obj_build_section_table (lto_file *file, struct lto_section_list *list, htab_t section_hash_table);
extern htab_t lto_obj_create_section_hash_table (void);
extern void lto_obj_begin_section (const char *name);
extern void lto_obj_append_data (const void *data, size_t len, void *block);
extern void lto_obj_end_section (void);
extern lto_file *lto_set_current_out_file (lto_file *file);
extern lto_file *lto_get_current_out_file (void);
/* In lto-cgraph.cc */
extern bool asm_nodes_output;

View File

@@ -24,9 +24,9 @@ LTO_EXE = lto1$(exeext)
LTO_DUMP_EXE = lto-dump$(exeext)
LTO_DUMP_INSTALL_NAME := $(shell echo lto-dump|sed '$(program_transform_name)')
# The LTO-specific object files inclued in $(LTO_EXE).
LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o
LTO_OBJS = lto/lto-lang.o lto/lto.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o
lto_OBJS = $(LTO_OBJS)
LTO_DUMP_OBJS = lto/lto-lang.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-dump.o lto/lto-common.o
LTO_DUMP_OBJS = lto/lto-lang.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-dump.o lto/lto-common.o
lto_dump_OBJS = $(LTO_DUMP_OBJS)
# this is only useful in a LTO bootstrap, but this does not work right

View File

@@ -2326,7 +2326,8 @@ lto_file_read (lto_file *file, FILE *resolution_file, int *count)
struct lto_section_list section_list;
memset (&section_list, 0, sizeof (struct lto_section_list));
section_hash_table = lto_obj_build_section_table (file, &section_list);
section_hash_table = lto_obj_create_section_hash_table ();
section_hash_table = lto_obj_build_section_table (file, &section_list, section_hash_table);
/* Dump the details of LTO objects. */
if (flag_lto_dump_objects)

View File

@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "tree.h"
#include "gimple.h"
#include "cgraph.h"
#include "stringpool.h"
#include "diagnostic-core.h"
#include "stor-layout.h"
@@ -35,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-tree.h"
#include "lto.h"
#include "lto-common.h"
#include "lto-streamer.h"
#include "stringpool.h"
#include "attribs.h"

View File

@@ -21,16 +21,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef LTO_H
#define LTO_H
/* A file. */
struct lto_file
{
/* The name of the file. */
const char *filename;
/* The offset for the object inside an ar archive file (or zero). */
off_t offset;
};
/* In lto-lang.cc */
extern const char *resolution_file_name;
@@ -39,36 +29,8 @@ extern tree lto_eh_personality (void);
extern void lto_main (void);
extern void lto_read_all_file_options (void);
/* In lto-elf.c or lto-coff.c */
extern lto_file *lto_obj_file_open (const char *filename, bool writable);
extern void lto_obj_file_close (lto_file *file);
struct lto_section_list;
extern htab_t lto_obj_build_section_table (lto_file *file, struct lto_section_list *list);
extern htab_t lto_obj_create_section_hash_table (void);
extern void lto_obj_begin_section (const char *name);
extern void lto_obj_append_data (const void *data, size_t len, void *block);
extern void lto_obj_end_section (void);
extern lto_file *lto_set_current_out_file (lto_file *file);
extern lto_file *lto_get_current_out_file (void);
extern int lto_link_dump_id, decl_merge_dump_id, partition_dump_id;
/* Hash table entry to hold the start offset and length of an LTO
section in a .o file. */
struct lto_section_slot
{
const char *name;
intptr_t start;
size_t len;
struct lto_section_slot *next;
};
/* A list of section slots */
struct lto_section_list
{
struct lto_section_slot *first, *last;
};
extern unsigned int lto_option_lang_mask (void);
#endif /* LTO_H */

View File

@@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-modref.h"
#include "ipa-param-manipulation.h"
#include "dbgcnt.h"
#include "lto-streamer.h"
#include "selftest.h"
@@ -539,6 +540,12 @@ compile_file (void)
even when user did not ask for it. */
if (flag_generate_lto && !flag_fat_lto_objects)
{
if (flag_bypass_asm)
{
/* TODO */
}
else
{
#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE, "__gnu_lto_slim",
HOST_WIDE_INT_1U, 8);
@@ -550,12 +557,13 @@ compile_file (void)
HOST_WIDE_INT_1U,
HOST_WIDE_INT_1U);
#endif
}
}
/* Attach a special .ident directive to the end of the file to identify
the version of GCC which compiled this code. The format of the .ident
string is patterned after the ones produced by native SVR4 compilers. */
if (!flag_no_ident)
if (!flag_no_ident && !flag_bypass_asm)
{
const char *pkg_version = "(GNU) ";
char *ident_str;
@@ -577,7 +585,11 @@ compile_file (void)
/* This must be at the end. Some target ports emit end of file directives
into the assembly file here, and hence we cannot output anything to the
assembly file after this point. */
targetm.asm_out.file_end ();
if (flag_bypass_asm)
lto_obj_file_close (lto_get_current_out_file ());
else
targetm.asm_out.file_end ();
timevar_stop (TV_PHASE_LATE_ASM);
}
@@ -1819,7 +1831,8 @@ lang_dependent_init (const char *name)
if (!flag_wpa)
{
init_asm_output (name);
if (!flag_bypass_asm)
init_asm_output (name);
if (!flag_generate_lto && !flag_compare_debug)
{

View File

@@ -156,6 +156,11 @@ simple_object_start_write (simple_object_attributes *attrs,
typedef struct simple_object_write_section_struct simple_object_write_section;
/* The type simple_object_symbol is a handle for a symbol
which is being written. */
typedef struct simple_object_symbol_struct simple_object_symbol;
/* Add a section to SIMPLE_OBJECT. NAME is the name of the new
section. ALIGN is the required alignment expressed as the number
of required low-order 0 bits (e.g., 2 for alignment to a 32-bit
@@ -190,6 +195,11 @@ simple_object_write_add_data (simple_object_write *simple_object,
extern const char *
simple_object_write_to_file (simple_object_write *simple_object,
int descriptor, int *err);
/*Add a symbol to sobj struct which will be written to common in simple_
object_write_to_file function*/
extern void
simple_object_write_add_symbol(simple_object_write *sobj, const char *name,
size_t size, unsigned int align);
/* Release all resources associated with SIMPLE_OBJECT, including any
simple_object_write_section's that may have been created. */

View File

@@ -58,6 +58,24 @@ struct simple_object_write_struct
simple_object_write_section *last_section;
/* Private data for the object file format. */
void *data;
/*The start of the list of symbols.*/
simple_object_symbol *symbols;
/*The last entry in the list of symbols*/
simple_object_symbol *last_symbol;
};
/*A symbol in object file being created*/
struct simple_object_symbol_struct
{
/*Next in the list of symbols attached to an
simple_object_write*/
simple_object_symbol *next;
/*The name of this symbol. */
char *name;
/* Symbol value */
unsigned int align;
/* Symbol size */
size_t size;
};
/* A section in an object file being created. */

View File

@@ -787,9 +787,14 @@ simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
++shnum;
if (shnum > 0)
{
/* Add a section header for the dummy section and one for
.shstrtab. */
/* Add a section header for the dummy section,
and .shstrtab*/
shnum += 2;
/*add section header for .symtab and .strtab
if symbol exists
*/
if(sobj->symbols)
shnum += 2;
}
ehdr_size = (cl == ELFCLASS32
@@ -882,6 +887,51 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
errmsg, err);
}
/* Write out an ELF Symbol*/
static int
simple_object_elf_write_symbol(simple_object_write *sobj, int descriptor,
off_t offset, unsigned int st_name, unsigned int st_value, size_t st_size,
unsigned char st_info, unsigned char st_other, unsigned int st_shndx,
const char **errmsg, int *err)
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) sobj->data;
const struct elf_type_functions* fns;
unsigned char cl;
size_t sym_size;
unsigned char buf[sizeof (Elf64_External_Shdr)];
fns = attrs->type_functions;
cl = attrs->ei_class;
sym_size = (cl == ELFCLASS32
? sizeof (Elf32_External_Shdr)
: sizeof (Elf64_External_Shdr));
memset (buf, 0, sizeof (Elf64_External_Shdr));
if(cl==ELFCLASS32)
{
ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name);
ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value);
ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size);
buf[4]=st_info;
buf[5]=st_other;
ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx);
}
else
{
ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name);
buf[4]=st_info;
buf[5]=st_other;
ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx);
ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value);
ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size);
}
return simple_object_internal_write(descriptor, offset,buf,sym_size,
errmsg,err);
}
/* Write out a complete ELF file.
Ehdr
initial dummy Shdr
@@ -932,8 +982,11 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
if (shnum == 0)
return NULL;
/* Add initial dummy Shdr and .shstrtab. */
/* Add initial dummy Shdr and .shstrtab */
shnum += 2;
/*add initial .symtab and .strtab if symbol exists */
if(sobj->symbols)
shnum += 2;
shdr_offset = ehdr_size;
sh_offset = shdr_offset + shnum * shdr_size;
@@ -1035,7 +1088,74 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
sh_name += strlen (section->name) + 1;
sh_offset += sh_size;
}
/*Write out the whole .symtab and .strtab*/
if(sobj->symbols)
{
unsigned int num_sym = 1;
simple_object_symbol *symbol;
for(symbol=sobj->symbols; symbol!=NULL; symbol=symbol->next)
{
++num_sym;
}
size_t sym_size = cl==ELFCLASS32?sizeof(Elf32_External_Sym):sizeof(Elf64_External_Sym);
size_t sh_addralign = cl==ELFCLASS32?0x04:0x08;
size_t sh_entsize = sym_size;
size_t sh_size = num_sym*sym_size;
unsigned int sh_info = 2;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_SYMTAB, 0, 0, sh_offset,
sh_size, shnum-2, sh_info,
sh_addralign,sh_entsize, &errmsg, err))
return errmsg;
shdr_offset += shdr_size;
sh_name += strlen(".symtab")+1;
/*Writes out the dummy symbol */
if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset,
0,0,0,0,0,SHN_UNDEF,&errmsg,err))
return errmsg;
sh_offset += sym_size;
unsigned int st_name=1;
for(symbol=sobj->symbols; symbol!=NULL; symbol=symbol->next)
{
unsigned int st_value = 1;
unsigned int st_size = 1;
unsigned char st_info = 17;
if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset,
st_name,st_value,st_size,st_info,0,SHN_COMMON,&errmsg,err))
return errmsg;
sh_offset += sym_size;
st_name += strlen(symbol->name)+1;
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_STRTAB, 0, 0, sh_offset,
st_name, 0, 0,
1, 0, &errmsg, err))
return errmsg;
shdr_offset += shdr_size;
sh_name += strlen(".strtab")+1;
/*.strtab has a leading zero byte*/
zero = 0;
if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
&errmsg, err))
return errmsg;
++sh_offset;
for(symbol=sobj->symbols;symbol!=NULL;symbol=symbol->next)
{
size_t len=strlen(symbol->name)+1;
if (!simple_object_internal_write (descriptor, sh_offset,
(const unsigned char *) symbol->name,
len, &errmsg, err))
return errmsg;
sh_offset += len;
}
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_STRTAB, 0, 0, sh_offset,
sh_name + strlen (".shstrtab") + 1, 0, 0,
@@ -1060,7 +1180,20 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
return errmsg;
sh_offset += len;
}
/*Adds the name .symtab and .strtab*/
if(sobj->symbols)
{
if (!simple_object_internal_write (descriptor, sh_offset,
(const unsigned char *) ".symtab",
strlen (".symtab") + 1, &errmsg, err))
return errmsg;
sh_offset += strlen(".symtab")+1;
if (!simple_object_internal_write (descriptor, sh_offset,
(const unsigned char *) ".strtab",
strlen (".strtab") + 1, &errmsg, err))
return errmsg;
sh_offset += strlen(".strtab")+1;
}
if (!simple_object_internal_write (descriptor, sh_offset,
(const unsigned char *) ".shstrtab",
strlen (".shstrtab") + 1, &errmsg, err))

View File

@@ -455,6 +455,8 @@ simple_object_start_write (simple_object_attributes *attrs,
ret->sections = NULL;
ret->last_section = NULL;
ret->data = data;
ret->symbols=NULL;
ret->last_symbol=NULL;
return ret;
}
@@ -538,6 +540,28 @@ simple_object_write_to_file (simple_object_write *sobj, int descriptor,
{
return sobj->functions->write_to_file (sobj, descriptor, err);
}
/*Adds a symbol in to common*/
void
simple_object_write_add_symbol(simple_object_write *sobj, const char *name,
size_t size, unsigned int align)
{
simple_object_symbol *symbol;
symbol=XNEW(simple_object_symbol);
symbol->next=NULL;
symbol->name=xstrdup(name);
symbol->align=align;
symbol->size=size;
if(sobj->last_symbol==NULL)
{
sobj->symbols=symbol;
sobj->last_symbol=symbol;
}
else
{
sobj->last_symbol->next=symbol;
sobj->last_symbol=symbol;
}
}
/* Release an simple_object_write. */
@@ -571,6 +595,16 @@ simple_object_release_write (simple_object_write *sobj)
XDELETE (section);
section = next_section;
}
simple_object_symbol *symbol,*next_symbol;
symbol=sobj->symbols;
while(symbol!=NULL)
{
next_symbol=symbol->next;
free(symbol->name);
XDELETE(symbol);
symbol=next_symbol;
}
sobj->functions->release_write (sobj->data);
XDELETE (sobj);