43f3e411c4
Currently "symtabs" in gdb are stored as a single linked list of struct symtab that contains both symbol symtabs (the blockvectors) and file symtabs (the linetables). This has led to confusion, bugs, and performance issues. This patch is conceptually very simple: split struct symtab into two pieces: one part containing things common across the entire compilation unit, and one part containing things specific to each source file. Example. For the case of a program built out of these files: foo.c foo1.h foo2.h bar.c foo1.h bar.h Today we have a single list of struct symtabs: objfile -> foo.c -> foo1.h -> foo2.h -> bar.c -> foo1.h -> bar.h -> NULL where "->" means the "next" pointer in struct symtab. With this patch, that turns into: objfile -> foo.c(cu) -> bar.c(cu) -> NULL | | v v foo.c bar.c | | v v foo1.h foo1.h | | v v foo2.h bar.h | | v v NULL NULL where "foo.c(cu)" and "bar.c(cu)" are struct compunit_symtab objects, and the files foo.c, etc. are struct symtab objects. So now, for example, when we want to iterate over all blockvectors we can now just iterate over the compunit_symtab list. Plus a lot of the data that was either unused or replicated for each symtab in a compilation unit now lives in struct compunit_symtab. E.g., the objfile pointer, the producer string, etc. I thought of moving "language" out of struct symtab but there is logic to try to compute the language based on previously seen files, and I think that's best left as is for now. With my standard monster benchmark with -readnow (which I can't actually do, but based on my calculations), whereas today the list requires 77MB to store all the struct symtabs, it now only requires 37MB. A modest space savings given the gigabytes needed for all the debug info, etc. Still, it's nice. Plus, whereas today we create a copy of dirname for each source file symtab in a compilation unit, we now only create one for the compunit. So this patch is basically just a data structure reorg, I don't expect significant performance improvements from it. Notes: 1) A followup patch can do a similar split for struct partial_symtab. I have left that until after I get the changes I want in to better utilize .gdb_index (it may affect how we do partial syms). 2) Another followup patch *could* rename struct symtab. The term "symtab" is ambiguous and has been a source of confusion. In this patch I'm leaving it alone, calling it the "historical" name of "filetabs", which is what they are now: just the file-name + line-table. gdb/ChangeLog: Split struct symtab into two: struct symtab and compunit_symtab. * amd64-tdep.c (amd64_skip_xmm_prologue): Fetch producer from compunit. * block.c (blockvector_for_pc_sect): Change "struct symtab *" argument to "struct compunit_symtab *". All callers updated. (set_block_compunit_symtab): Renamed from set_block_symtab. Change "struct symtab *" argument to "struct compunit_symtab *". All callers updated. (get_block_compunit_symtab): Renamed from get_block_symtab. Change result to "struct compunit_symtab *". All callers updated. (find_iterator_compunit_symtab): Renamed from find_iterator_symtab. Change result to "struct compunit_symtab *". All callers updated. * block.h (struct global_block) <compunit_symtab>: Renamed from symtab. hange type to "struct compunit_symtab *". All uses updated. (struct block_iterator) <d.compunit_symtab>: Renamed from "d.symtab". Change type to "struct compunit_symtab *". All uses updated. * buildsym.c (struct buildsym_compunit): New struct. (subfiles, buildsym_compdir, buildsym_objfile, main_subfile): Delete. (buildsym_compunit): New static global. (finish_block_internal): Update to fetch objfile from buildsym_compunit. (make_blockvector): Delete objfile argument. (start_subfile): Rewrite to use buildsym_compunit. Don't initialize debugformat, producer. (start_buildsym_compunit): New function. (free_buildsym_compunit): Renamed from free_subfiles_list. All callers updated. (patch_subfile_names): Rewrite to use buildsym_compunit. (get_compunit_symtab): New function. (get_macro_table): Delete argument comp_dir. All callers updated. (start_symtab): Change result to "struct compunit_symtab *". All callers updated. Create the subfile of the main source file. (watch_main_source_file_lossage): Rewrite to use buildsym_compunit. (reset_symtab_globals): Update. (end_symtab_get_static_block): Update to use buildsym_compunit. (end_symtab_without_blockvector): Rewrite. (end_symtab_with_blockvector): Change result to "struct compunit_symtab *". All callers updated. Update to use buildsym_compunit. Don't set symtab->dirname, instead set it in the compunit. Explicitly make sure main symtab is first in its list. Set debugformat, producer, blockvector, block_line_section, and macrotable in the compunit. (end_symtab_from_static_block): Change result to "struct compunit_symtab *". All callers updated. (end_symtab, end_expandable_symtab): Ditto. (set_missing_symtab): Change symtab argument to "struct compunit_symtab *". All callers updated. (augment_type_symtab): Ditto. (record_debugformat): Update to use buildsym_compunit. (record_producer): Update to use buildsym_compunit. * buildsym.h (struct subfile) <dirname>: Delete. <producer, debugformat>: Delete. <buildsym_compunit>: New member. (get_compunit_symtab): Declare. * dwarf2read.c (struct type_unit_group) <compunit_symtab>: Renamed from primary_symtab. Change type to "struct compunit_symtab *". All uses updated. (dwarf2_start_symtab): Change result to "struct compunit_symtab *". All callers updated. (dwarf_decode_macros): Delete comp_dir argument. All callers updated. (struct dwarf2_per_cu_quick_data) <compunit_symtab>: Renamed from symtab. Change type to "struct compunit_symtab *". All uses updated. (dw2_instantiate_symtab): Change result to "struct compunit_symtab *". All callers updated. (dw2_find_last_source_symtab): Ditto. (dw2_lookup_symbol): Ditto. (recursively_find_pc_sect_compunit_symtab): Renamed from recursively_find_pc_sect_symtab. Change result to "struct compunit_symtab *". All callers updated. (dw2_find_pc_sect_compunit_symtab): Renamed from dw2_find_pc_sect_symtab. Change result to "struct compunit_symtab *". All callers updated. (get_compunit_symtab): Renamed from get_symtab. Change result to "struct compunit_symtab *". All callers updated. (recursively_compute_inclusions): Change type of immediate_parent argument to "struct compunit_symtab *". All callers updated. (compute_compunit_symtab_includes): Renamed from compute_symtab_includes. All callers updated. Rewrite to compute includes of compunit_symtabs and not symtabs. (process_full_comp_unit): Update to work with struct compunit_symtab. (process_full_type_unit): Ditto. (dwarf_decode_lines_1): Delete argument comp_dir. All callers updated. (dwarf_decode_lines): Remove special case handling of main subfile. (macro_start_file): Delete argument comp_dir. All callers updated. (dwarf_decode_macro_bytes): Ditto. * guile/scm-block.c (bkscm_print_block_syms_progress_smob): Update to use struct compunit_symtab. * i386-tdep.c (i386_skip_prologue): Fetch producer from compunit. * jit.c (finalize_symtab): Build compunit_symtab. * jv-lang.c (get_java_class_symtab): Change result to "struct compunit_symtab *". All callers updated. * macroscope.c (sal_macro_scope): Fetch macro table from compunit. * macrotab.c (struct macro_table) <compunit_symtab>: Renamed from comp_dir. Change type to "struct compunit_symtab *". All uses updated. (new_macro_table): Change comp_dir argument to cust, "struct compunit_symtab *". All callers updated. * maint.c (struct cmd_stats) <nr_compunit_symtabs>: Renamed from nr_primary_symtabs. All uses updated. (count_symtabs_and_blocks): Update to handle compunits. (report_command_stats): Update output, "primary symtabs" renamed to "compunits". * mdebugread.c (new_symtab): Change result to "struct compunit_symtab *". All callers updated. (parse_procedure): Change type of search_symtab argument to "struct compunit_symtab *". All callers updated. * objfiles.c (objfile_relocate1): Loop over blockvectors in a separate loop. * objfiles.h (struct objfile) <compunit_symtabs>: Renamed from symtabs. Change type to "struct compunit_symtab *". All uses updated. (ALL_OBJFILE_FILETABS): Renamed from ALL_OBJFILE_SYMTABS. All uses updated. (ALL_OBJFILE_COMPUNITS): Renamed from ALL_OBJFILE_PRIMARY_SYMTABS. All uses updated. (ALL_FILETABS): Renamed from ALL_SYMTABS. All uses updated. (ALL_COMPUNITS): Renamed from ALL_PRIMARY_SYMTABS. All uses updated. * psympriv.h (struct partial_symtab) <compunit_symtab>: Renamed from symtab. Change type to "struct compunit_symtab *". All uses updated. * psymtab.c (psymtab_to_symtab): Change result type to "struct compunit_symtab *". All callers updated. (find_pc_sect_compunit_symtab_from_partial): Renamed from find_pc_sect_symtab_from_partial. Change result type to "struct compunit_symtab *". All callers updated. (lookup_symbol_aux_psymtabs): Change result type to "struct compunit_symtab *". All callers updated. (find_last_source_symtab_from_partial): Ditto. * python/py-symtab.c (stpy_get_producer): Fetch producer from compunit. * source.c (forget_cached_source_info_for_objfile): Fetch debugformat and macro_table from compunit. * symfile-debug.c (debug_qf_find_last_source_symtab): Change result type to "struct compunit_symtab *". All callers updated. (debug_qf_lookup_symbol): Ditto. (debug_qf_find_pc_sect_compunit_symtab): Renamed from debug_qf_find_pc_sect_symtab, change result type to "struct compunit_symtab *". All callers updated. * symfile.c (allocate_symtab): Delete objfile argument. New argument cust. (allocate_compunit_symtab): New function. (add_compunit_symtab_to_objfile): New function. * symfile.h (struct quick_symbol_functions) <lookup_symbol>: Change result type to "struct compunit_symtab *". All uses updated. <find_pc_sect_compunit_symtab>: Renamed from find_pc_sect_symtab. Change result type to "struct compunit_symtab *". All uses updated. * symmisc.c (print_objfile_statistics): Compute blockvector count in separate loop. (dump_symtab_1): Update test for primary source symtab. (maintenance_info_symtabs): Update to handle compunit symtabs. (maintenance_check_symtabs): Ditto. * symtab.c (set_primary_symtab): Delete. (compunit_primary_filetab): New function. (compunit_language): New function. (iterate_over_some_symtabs): Change type of arguments "first", "after_last" to "struct compunit_symtab *". All callers updated. Update to loop over symtabs in each compunit. (error_in_psymtab_expansion): Rename symtab argument to cust, and change type to "struct compunit_symtab *". All callers updated. (find_pc_sect_compunit_symtab): Renamed from find_pc_sect_symtab. Change result type to "struct compunit_symtab *". All callers updated. (find_pc_compunit_symtab): Renamed from find_pc_symtab. Change result type to "struct compunit_symtab *". All callers updated. (find_pc_sect_line): Only loop over symtabs within selected compunit instead of all symtabs in the objfile. * symtab.h (struct symtab) <blockvector>: Moved to compunit_symtab. <compunit_symtab> New member. <block_line_section>: Moved to compunit_symtab. <locations_valid>: Ditto. <epilogue_unwind_valid>: Ditto. <macro_table>: Ditto. <dirname>: Ditto. <debugformat>: Ditto. <producer>: Ditto. <objfile>: Ditto. <call_site_htab>: Ditto. <includes>: Ditto. <user>: Ditto. <primary>: Delete (SYMTAB_COMPUNIT): New macro. (SYMTAB_BLOCKVECTOR): Update definition. (SYMTAB_OBJFILE): Update definition. (SYMTAB_DIRNAME): Update definition. (struct compunit_symtab): New type. Common members among all source symtabs within a compilation unit moved here. All uses updated. (COMPUNIT_OBJFILE): New macro. (COMPUNIT_FILETABS): New macro. (COMPUNIT_DEBUGFORMAT): New macro. (COMPUNIT_PRODUCER): New macro. (COMPUNIT_DIRNAME): New macro. (COMPUNIT_BLOCKVECTOR): New macro. (COMPUNIT_BLOCK_LINE_SECTION): New macro. (COMPUNIT_LOCATIONS_VALID): New macro. (COMPUNIT_EPILOGUE_UNWIND_VALID): New macro. (COMPUNIT_CALL_SITE_HTAB): New macro. (COMPUNIT_MACRO_TABLE): New macro. (ALL_COMPUNIT_FILETABS): New macro. (compunit_symtab_ptr): New typedef. (DEF_VEC_P (compunit_symtab_ptr)): New vector type. gdb/testsuite/ChangeLog: * gdb.base/maint.exp: Update expected output.
660 lines
18 KiB
C
660 lines
18 KiB
C
/* Python interface to symbol tables.
|
||
|
||
Copyright (C) 2008-2014 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
||
#include "defs.h"
|
||
#include "charset.h"
|
||
#include "symtab.h"
|
||
#include "source.h"
|
||
#include "python-internal.h"
|
||
#include "objfiles.h"
|
||
#include "block.h"
|
||
|
||
typedef struct stpy_symtab_object {
|
||
PyObject_HEAD
|
||
/* The GDB Symbol table structure. */
|
||
struct symtab *symtab;
|
||
/* A symtab object is associated with an objfile, so keep track with
|
||
a doubly-linked list, rooted in the objfile. This allows
|
||
invalidation of the underlying struct symtab when the objfile is
|
||
deleted. */
|
||
struct stpy_symtab_object *prev;
|
||
struct stpy_symtab_object *next;
|
||
} symtab_object;
|
||
|
||
static PyTypeObject symtab_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("symtab_object");
|
||
static const struct objfile_data *stpy_objfile_data_key;
|
||
|
||
/* Require a valid symbol table. All access to symtab_object->symtab
|
||
should be gated by this call. */
|
||
#define STPY_REQUIRE_VALID(symtab_obj, symtab) \
|
||
do { \
|
||
symtab = symtab_object_to_symtab (symtab_obj); \
|
||
if (symtab == NULL) \
|
||
{ \
|
||
PyErr_SetString (PyExc_RuntimeError, \
|
||
_("Symbol Table is invalid.")); \
|
||
return NULL; \
|
||
} \
|
||
} while (0)
|
||
|
||
typedef struct salpy_sal_object {
|
||
PyObject_HEAD
|
||
/* The GDB Symbol table structure. */
|
||
symtab_object *symtab;
|
||
/* The GDB Symbol table and line structure. */
|
||
struct symtab_and_line *sal;
|
||
/* A Symtab and line object is associated with an objfile, so keep
|
||
track with a doubly-linked list, rooted in the objfile. This
|
||
allows invalidation of the underlying struct symtab_and_line
|
||
when the objfile is deleted. */
|
||
struct salpy_sal_object *prev;
|
||
struct salpy_sal_object *next;
|
||
} sal_object;
|
||
|
||
static PyTypeObject sal_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("sal_object");
|
||
static const struct objfile_data *salpy_objfile_data_key;
|
||
|
||
/* Require a valid symbol table and line object. All access to
|
||
sal_object->sal should be gated by this call. */
|
||
#define SALPY_REQUIRE_VALID(sal_obj, sal) \
|
||
do { \
|
||
sal = sal_object_to_symtab_and_line (sal_obj); \
|
||
if (sal == NULL) \
|
||
{ \
|
||
PyErr_SetString (PyExc_RuntimeError, \
|
||
_("Symbol Table and Line is invalid.")); \
|
||
return NULL; \
|
||
} \
|
||
} while (0)
|
||
|
||
static PyObject *
|
||
stpy_str (PyObject *self)
|
||
{
|
||
PyObject *result;
|
||
struct symtab *symtab = NULL;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
result = PyString_FromString (symtab_to_filename_for_display (symtab));
|
||
|
||
return result;
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_get_filename (PyObject *self, void *closure)
|
||
{
|
||
PyObject *str_obj;
|
||
struct symtab *symtab = NULL;
|
||
const char *filename;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
filename = symtab_to_filename_for_display (symtab);
|
||
|
||
str_obj = PyString_Decode (filename, strlen (filename),
|
||
host_charset (), NULL);
|
||
return str_obj;
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_get_objfile (PyObject *self, void *closure)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
PyObject *result;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
result = objfile_to_objfile_object (SYMTAB_OBJFILE (symtab));
|
||
Py_XINCREF (result);
|
||
return result;
|
||
}
|
||
|
||
/* Getter function for symtab.producer. */
|
||
|
||
static PyObject *
|
||
stpy_get_producer (PyObject *self, void *closure)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
struct compunit_symtab *cust;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
cust = SYMTAB_COMPUNIT (symtab);
|
||
if (COMPUNIT_PRODUCER (cust) != NULL)
|
||
{
|
||
const char *producer = COMPUNIT_PRODUCER (cust);
|
||
|
||
return PyString_Decode (producer, strlen (producer),
|
||
host_charset (), NULL);
|
||
}
|
||
|
||
Py_RETURN_NONE;
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_fullname (PyObject *self, PyObject *args)
|
||
{
|
||
const char *fullname;
|
||
struct symtab *symtab = NULL;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
fullname = symtab_to_fullname (symtab);
|
||
|
||
return PyString_Decode (fullname, strlen (fullname), host_charset (), NULL);
|
||
}
|
||
|
||
/* Implementation of gdb.Symtab.is_valid (self) -> Boolean.
|
||
Returns True if this Symbol table still exists in GDB. */
|
||
|
||
static PyObject *
|
||
stpy_is_valid (PyObject *self, PyObject *args)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
|
||
symtab = symtab_object_to_symtab (self);
|
||
if (symtab == NULL)
|
||
Py_RETURN_FALSE;
|
||
|
||
Py_RETURN_TRUE;
|
||
}
|
||
|
||
/* Return the GLOBAL_BLOCK of the underlying symtab. */
|
||
|
||
static PyObject *
|
||
stpy_global_block (PyObject *self, PyObject *args)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
struct block *block = NULL;
|
||
const struct blockvector *blockvector;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
blockvector = SYMTAB_BLOCKVECTOR (symtab);
|
||
block = BLOCKVECTOR_BLOCK (blockvector, GLOBAL_BLOCK);
|
||
return block_to_block_object (block, SYMTAB_OBJFILE (symtab));
|
||
}
|
||
|
||
/* Return the STATIC_BLOCK of the underlying symtab. */
|
||
|
||
static PyObject *
|
||
stpy_static_block (PyObject *self, PyObject *args)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
struct block *block = NULL;
|
||
const struct blockvector *blockvector;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
blockvector = SYMTAB_BLOCKVECTOR (symtab);
|
||
block = BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK);
|
||
return block_to_block_object (block, SYMTAB_OBJFILE (symtab));
|
||
}
|
||
|
||
/* Implementation of gdb.Symtab.linetable (self) -> gdb.Linetable.
|
||
Returns a gdb.Linetable object corresponding to this symbol
|
||
table. */
|
||
|
||
static PyObject *
|
||
stpy_get_linetable (PyObject *self, PyObject *args)
|
||
{
|
||
struct symtab *symtab = NULL;
|
||
|
||
STPY_REQUIRE_VALID (self, symtab);
|
||
|
||
return symtab_to_linetable_object (self);
|
||
}
|
||
|
||
static PyObject *
|
||
salpy_str (PyObject *self)
|
||
{
|
||
char *s;
|
||
const char *filename;
|
||
sal_object *sal_obj;
|
||
PyObject *result;
|
||
struct symtab_and_line *sal = NULL;
|
||
|
||
SALPY_REQUIRE_VALID (self, sal);
|
||
|
||
sal_obj = (sal_object *) self;
|
||
filename = (sal_obj->symtab == (symtab_object *) Py_None)
|
||
? "<unknown>" : symtab_to_filename_for_display (sal_obj->symtab->symtab);
|
||
|
||
s = xstrprintf ("symbol and line for %s, line %d", filename,
|
||
sal->line);
|
||
|
||
result = PyString_FromString (s);
|
||
xfree (s);
|
||
|
||
return result;
|
||
}
|
||
|
||
static void
|
||
stpy_dealloc (PyObject *obj)
|
||
{
|
||
symtab_object *symtab = (symtab_object *) obj;
|
||
|
||
if (symtab->prev)
|
||
symtab->prev->next = symtab->next;
|
||
else if (symtab->symtab)
|
||
{
|
||
set_objfile_data (SYMTAB_OBJFILE (symtab->symtab),
|
||
stpy_objfile_data_key, symtab->next);
|
||
}
|
||
if (symtab->next)
|
||
symtab->next->prev = symtab->prev;
|
||
symtab->symtab = NULL;
|
||
}
|
||
|
||
|
||
static PyObject *
|
||
salpy_get_pc (PyObject *self, void *closure)
|
||
{
|
||
struct symtab_and_line *sal = NULL;
|
||
|
||
SALPY_REQUIRE_VALID (self, sal);
|
||
|
||
return gdb_py_long_from_ulongest (sal->pc);
|
||
}
|
||
|
||
/* Implementation of the get method for the 'last' attribute of
|
||
gdb.Symtab_and_line. */
|
||
|
||
static PyObject *
|
||
salpy_get_last (PyObject *self, void *closure)
|
||
{
|
||
struct symtab_and_line *sal = NULL;
|
||
|
||
SALPY_REQUIRE_VALID (self, sal);
|
||
|
||
if (sal->end > 0)
|
||
return gdb_py_long_from_ulongest (sal->end - 1);
|
||
else
|
||
Py_RETURN_NONE;
|
||
}
|
||
|
||
static PyObject *
|
||
salpy_get_line (PyObject *self, void *closure)
|
||
{
|
||
struct symtab_and_line *sal = NULL;
|
||
|
||
SALPY_REQUIRE_VALID (self, sal);
|
||
|
||
return PyInt_FromLong (sal->line);
|
||
}
|
||
|
||
static PyObject *
|
||
salpy_get_symtab (PyObject *self, void *closure)
|
||
{
|
||
struct symtab_and_line *sal;
|
||
sal_object *self_sal = (sal_object *) self;
|
||
|
||
SALPY_REQUIRE_VALID (self, sal);
|
||
|
||
Py_INCREF (self_sal->symtab);
|
||
|
||
return (PyObject *) self_sal->symtab;
|
||
}
|
||
|
||
/* Implementation of gdb.Symtab_and_line.is_valid (self) -> Boolean.
|
||
Returns True if this Symbol table and line object still exists GDB. */
|
||
|
||
static PyObject *
|
||
salpy_is_valid (PyObject *self, PyObject *args)
|
||
{
|
||
struct symtab_and_line *sal;
|
||
|
||
sal = sal_object_to_symtab_and_line (self);
|
||
if (sal == NULL)
|
||
Py_RETURN_FALSE;
|
||
|
||
Py_RETURN_TRUE;
|
||
}
|
||
|
||
static void
|
||
salpy_dealloc (PyObject *self)
|
||
{
|
||
sal_object *self_sal = (sal_object *) self;
|
||
|
||
if (self_sal->prev)
|
||
self_sal->prev->next = self_sal->next;
|
||
else if (self_sal->symtab != (symtab_object * ) Py_None)
|
||
set_objfile_data (SYMTAB_OBJFILE (self_sal->symtab->symtab),
|
||
salpy_objfile_data_key, self_sal->next);
|
||
|
||
if (self_sal->next)
|
||
self_sal->next->prev = self_sal->prev;
|
||
|
||
Py_DECREF (self_sal->symtab);
|
||
xfree (self_sal->sal);
|
||
Py_TYPE (self)->tp_free (self);
|
||
}
|
||
|
||
/* Given a sal, and a sal_object that has previously been allocated
|
||
and initialized, populate the sal_object with the struct sal data.
|
||
Also, register the sal_object life-cycle with the life-cycle of the
|
||
object file associated with this sal, if needed. If a failure
|
||
occurs during the sal population, this function will return -1. */
|
||
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||
set_sal (sal_object *sal_obj, struct symtab_and_line sal)
|
||
{
|
||
symtab_object *symtab_obj;
|
||
|
||
if (sal.symtab)
|
||
{
|
||
symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab);
|
||
/* If a symtab existed in the sal, but it cannot be duplicated,
|
||
we exit. */
|
||
if (symtab_obj == NULL)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
symtab_obj = (symtab_object *) Py_None;
|
||
Py_INCREF (Py_None);
|
||
}
|
||
|
||
sal_obj->sal = xmemdup (&sal, sizeof (struct symtab_and_line),
|
||
sizeof (struct symtab_and_line));
|
||
sal_obj->symtab = symtab_obj;
|
||
sal_obj->prev = NULL;
|
||
|
||
/* If the SAL does not have a symtab, we do not add it to the
|
||
objfile cleanup observer linked list. */
|
||
if (sal_obj->symtab != (symtab_object *)Py_None)
|
||
{
|
||
sal_obj->next = objfile_data (SYMTAB_OBJFILE (sal_obj->symtab->symtab),
|
||
salpy_objfile_data_key);
|
||
if (sal_obj->next)
|
||
sal_obj->next->prev = sal_obj;
|
||
|
||
set_objfile_data (SYMTAB_OBJFILE (sal_obj->symtab->symtab),
|
||
salpy_objfile_data_key, sal_obj);
|
||
}
|
||
else
|
||
sal_obj->next = NULL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* Given a symtab, and a symtab_object that has previously been
|
||
allocated and initialized, populate the symtab_object with the
|
||
struct symtab data. Also, register the symtab_object life-cycle
|
||
with the life-cycle of the object file associated with this
|
||
symtab, if needed. */
|
||
static void
|
||
set_symtab (symtab_object *obj, struct symtab *symtab)
|
||
{
|
||
obj->symtab = symtab;
|
||
obj->prev = NULL;
|
||
if (symtab)
|
||
{
|
||
obj->next = objfile_data (SYMTAB_OBJFILE (symtab),
|
||
stpy_objfile_data_key);
|
||
if (obj->next)
|
||
obj->next->prev = obj;
|
||
set_objfile_data (SYMTAB_OBJFILE (symtab), stpy_objfile_data_key, obj);
|
||
}
|
||
else
|
||
obj->next = NULL;
|
||
}
|
||
|
||
/* Create a new symbol table (gdb.Symtab) object that encapsulates the
|
||
symtab structure from GDB. */
|
||
PyObject *
|
||
symtab_to_symtab_object (struct symtab *symtab)
|
||
{
|
||
symtab_object *symtab_obj;
|
||
|
||
symtab_obj = PyObject_New (symtab_object, &symtab_object_type);
|
||
if (symtab_obj)
|
||
set_symtab (symtab_obj, symtab);
|
||
|
||
return (PyObject *) symtab_obj;
|
||
}
|
||
|
||
/* Create a new symtab and line (gdb.Symtab_and_line) object
|
||
that encapsulates the symtab_and_line structure from GDB. */
|
||
PyObject *
|
||
symtab_and_line_to_sal_object (struct symtab_and_line sal)
|
||
{
|
||
sal_object *sal_obj;
|
||
int success = 0;
|
||
|
||
sal_obj = PyObject_New (sal_object, &sal_object_type);
|
||
if (sal_obj)
|
||
{
|
||
if (set_sal (sal_obj, sal) < 0)
|
||
{
|
||
Py_DECREF (sal_obj);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
return (PyObject *) sal_obj;
|
||
}
|
||
|
||
/* Return struct symtab_and_line reference that is wrapped by this
|
||
object. */
|
||
struct symtab_and_line *
|
||
sal_object_to_symtab_and_line (PyObject *obj)
|
||
{
|
||
if (! PyObject_TypeCheck (obj, &sal_object_type))
|
||
return NULL;
|
||
return ((sal_object *) obj)->sal;
|
||
}
|
||
|
||
/* Return struct symtab reference that is wrapped by this object. */
|
||
struct symtab *
|
||
symtab_object_to_symtab (PyObject *obj)
|
||
{
|
||
if (! PyObject_TypeCheck (obj, &symtab_object_type))
|
||
return NULL;
|
||
return ((symtab_object *) obj)->symtab;
|
||
}
|
||
|
||
/* This function is called when an objfile is about to be freed.
|
||
Invalidate the symbol table as further actions on the symbol table
|
||
would result in bad data. All access to obj->symtab should be
|
||
gated by STPY_REQUIRE_VALID which will raise an exception on
|
||
invalid symbol tables. */
|
||
static void
|
||
del_objfile_symtab (struct objfile *objfile, void *datum)
|
||
{
|
||
symtab_object *obj = datum;
|
||
|
||
while (obj)
|
||
{
|
||
symtab_object *next = obj->next;
|
||
|
||
obj->symtab = NULL;
|
||
obj->next = NULL;
|
||
obj->prev = NULL;
|
||
obj = next;
|
||
}
|
||
}
|
||
|
||
/* This function is called when an objfile is about to be freed.
|
||
Invalidate the sal object as further actions on the sal
|
||
would result in bad data. All access to obj->sal should be
|
||
gated by SALPY_REQUIRE_VALID which will raise an exception on
|
||
invalid symbol table and line objects. */
|
||
static void
|
||
del_objfile_sal (struct objfile *objfile, void *datum)
|
||
{
|
||
sal_object *obj = datum;
|
||
|
||
while (obj)
|
||
{
|
||
sal_object *next = obj->next;
|
||
|
||
Py_DECREF (obj->symtab);
|
||
obj->symtab = (symtab_object *) Py_None;
|
||
Py_INCREF (Py_None);
|
||
|
||
obj->next = NULL;
|
||
obj->prev = NULL;
|
||
xfree (obj->sal);
|
||
obj->sal = NULL;
|
||
|
||
obj = next;
|
||
}
|
||
}
|
||
|
||
int
|
||
gdbpy_initialize_symtabs (void)
|
||
{
|
||
symtab_object_type.tp_new = PyType_GenericNew;
|
||
if (PyType_Ready (&symtab_object_type) < 0)
|
||
return -1;
|
||
|
||
sal_object_type.tp_new = PyType_GenericNew;
|
||
if (PyType_Ready (&sal_object_type) < 0)
|
||
return -1;
|
||
|
||
/* Register an objfile "free" callback so we can properly
|
||
invalidate symbol tables, and symbol table and line data
|
||
structures when an object file that is about to be
|
||
deleted. */
|
||
stpy_objfile_data_key
|
||
= register_objfile_data_with_cleanup (NULL, del_objfile_symtab);
|
||
salpy_objfile_data_key
|
||
= register_objfile_data_with_cleanup (NULL, del_objfile_sal);
|
||
|
||
if (gdb_pymodule_addobject (gdb_module, "Symtab",
|
||
(PyObject *) &symtab_object_type) < 0)
|
||
return -1;
|
||
|
||
return gdb_pymodule_addobject (gdb_module, "Symtab_and_line",
|
||
(PyObject *) &sal_object_type);
|
||
}
|
||
|
||
|
||
|
||
static PyGetSetDef symtab_object_getset[] = {
|
||
{ "filename", stpy_get_filename, NULL,
|
||
"The symbol table's source filename.", NULL },
|
||
{ "objfile", stpy_get_objfile, NULL, "The symtab's objfile.",
|
||
NULL },
|
||
{ "producer", stpy_get_producer, NULL,
|
||
"The name/version of the program that compiled this symtab.", NULL },
|
||
{NULL} /* Sentinel */
|
||
};
|
||
|
||
static PyMethodDef symtab_object_methods[] = {
|
||
{ "is_valid", stpy_is_valid, METH_NOARGS,
|
||
"is_valid () -> Boolean.\n\
|
||
Return true if this symbol table is valid, false if not." },
|
||
{ "fullname", stpy_fullname, METH_NOARGS,
|
||
"fullname () -> String.\n\
|
||
Return the symtab's full source filename." },
|
||
{ "global_block", stpy_global_block, METH_NOARGS,
|
||
"global_block () -> gdb.Block.\n\
|
||
Return the global block of the symbol table." },
|
||
{ "static_block", stpy_static_block, METH_NOARGS,
|
||
"static_block () -> gdb.Block.\n\
|
||
Return the static block of the symbol table." },
|
||
{ "linetable", stpy_get_linetable, METH_NOARGS,
|
||
"linetable () -> gdb.Linetable.\n\
|
||
Return the Linetable associated with this symbol table" },
|
||
{NULL} /* Sentinel */
|
||
};
|
||
|
||
static PyTypeObject symtab_object_type = {
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.Symtab", /*tp_name*/
|
||
sizeof (symtab_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
stpy_dealloc, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
0, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
stpy_str, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||
"GDB symtab object", /*tp_doc */
|
||
0, /*tp_traverse */
|
||
0, /*tp_clear */
|
||
0, /*tp_richcompare */
|
||
0, /*tp_weaklistoffset */
|
||
0, /*tp_iter */
|
||
0, /*tp_iternext */
|
||
symtab_object_methods, /*tp_methods */
|
||
0, /*tp_members */
|
||
symtab_object_getset /*tp_getset */
|
||
};
|
||
|
||
static PyGetSetDef sal_object_getset[] = {
|
||
{ "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL },
|
||
{ "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL },
|
||
{ "last", salpy_get_last, NULL,
|
||
"Return the symtab_and_line's last address.", NULL },
|
||
{ "line", salpy_get_line, NULL,
|
||
"Return the symtab_and_line's line.", NULL },
|
||
{NULL} /* Sentinel */
|
||
};
|
||
|
||
static PyMethodDef sal_object_methods[] = {
|
||
{ "is_valid", salpy_is_valid, METH_NOARGS,
|
||
"is_valid () -> Boolean.\n\
|
||
Return true if this symbol table and line is valid, false if not." },
|
||
{NULL} /* Sentinel */
|
||
};
|
||
|
||
static PyTypeObject sal_object_type = {
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.Symtab_and_line", /*tp_name*/
|
||
sizeof (sal_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
salpy_dealloc, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
0, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
salpy_str, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||
"GDB symtab_and_line object", /*tp_doc */
|
||
0, /*tp_traverse */
|
||
0, /*tp_clear */
|
||
0, /*tp_richcompare */
|
||
0, /*tp_weaklistoffset */
|
||
0, /*tp_iter */
|
||
0, /*tp_iternext */
|
||
sal_object_methods, /*tp_methods */
|
||
0, /*tp_members */
|
||
sal_object_getset /*tp_getset */
|
||
};
|