dwarf2out.c (debug_str_hash): New.

* dwarf2out.c (debug_str_hash): New.
	(struct indirect_string_node): New.
	(struct dw_val_struct): Change type of val_str to it.
	(DEBUG_STR_SECTION_FLAGS): Define.
	(add_AT_string): Push string into hashtable, increment reference
	counter.
	(AT_string): Return string from ht_identifier.
	(AT_string_form): New.
	(free_AT): For dw_val_class_str, just decrement reference counter.
	(size_of_string): Remove.
	(size_of_die): Use AT_string_form to decide what size the string
	occupies in DIE.
	(size_of_pubnames): Use strlen instead of size_of_string.
	(value_format): Use AT_string_form for dw_val_class_str.
	(output_die): Output DW_FORM_strp strings using
	dw2_asm_output_offset.
	(indirect_string_alloc, output_indirect_string): New.
	(dwarf2out_finish): Emit .debug_str strings if there are any.

From-SVN: r46858
This commit is contained in:
Jakub Jelinek 2001-11-08 22:07:46 +01:00 committed by Jakub Jelinek
parent 944effb637
commit 9eb4015a4a
2 changed files with 166 additions and 25 deletions

View File

@ -1,3 +1,24 @@
2001-11-08 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (debug_str_hash): New.
(struct indirect_string_node): New.
(struct dw_val_struct): Change type of val_str to it.
(DEBUG_STR_SECTION_FLAGS): Define.
(add_AT_string): Push string into hashtable, increment reference
counter.
(AT_string): Return string from ht_identifier.
(AT_string_form): New.
(free_AT): For dw_val_class_str, just decrement reference counter.
(size_of_string): Remove.
(size_of_die): Use AT_string_form to decide what size the string
occupies in DIE.
(size_of_pubnames): Use strlen instead of size_of_string.
(value_format): Use AT_string_form for dw_val_class_str.
(output_die): Output DW_FORM_strp strings using
dw2_asm_output_offset.
(indirect_string_alloc, output_indirect_string): New.
(dwarf2out_finish): Emit .debug_str strings if there are any.
2001-11-08 Andreas Franck <afranck@gmx.de>
* configure.in: Add AC_ARG_PROGRAM to support program name

View File

@ -22,8 +22,7 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* TODO: Implement .debug_str handling, and share entries somehow.
Emit .debug_line header even when there are no functions, since
/* TODO: Emit .debug_line header even when there are no functions, since
the file numbers are used by .debug_info. Alternately, leave
out locations for types and decls.
Avoid talking about ctors and op= for PODs.
@ -60,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "diagnostic.h"
#include "debug.h"
#include "target.h"
#include "hashtable.h"
#ifdef DWARF2_DEBUGGING_INFO
static void dwarf2out_source_line PARAMS ((unsigned int, const char *));
@ -255,6 +255,16 @@ static dw_cfi_ref cie_cfi_head;
associated with the current function (body) definition. */
static unsigned current_funcdef_fde;
struct ht *debug_str_hash;
struct indirect_string_node
{
struct ht_identifier id;
unsigned int refcount;
unsigned int form;
char *label;
};
/* Forward declarations for functions defined in this file. */
static char *stripattributes PARAMS ((const char *));
@ -284,6 +294,11 @@ static struct dw_loc_descr_struct *build_cfa_loc
PARAMS ((dw_cfa_location *));
static void def_cfa_1 PARAMS ((const char *, dw_cfa_location *));
/* .debug_str support. */
static hashnode indirect_string_alloc PARAMS ((hash_table *));
static int output_indirect_string PARAMS ((struct cpp_reader *,
hashnode, const PTR));
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
@ -2176,7 +2191,7 @@ typedef struct dw_val_struct
int external;
} val_die_ref;
unsigned val_fde_index;
char *val_str;
struct indirect_string_node *val_str;
char *val_lbl_id;
unsigned char val_flag;
}
@ -3473,7 +3488,6 @@ static void break_out_includes PARAMS ((dw_die_ref));
static void add_sibling_attributes PARAMS ((dw_die_ref));
static void build_abbrev_table PARAMS ((dw_die_ref));
static void output_location_lists PARAMS ((dw_die_ref));
static unsigned long size_of_string PARAMS ((const char *));
static int constant_size PARAMS ((long unsigned));
static unsigned long size_of_die PARAMS ((dw_die_ref));
static void calc_die_sizes PARAMS ((dw_die_ref));
@ -3629,6 +3643,14 @@ static char *gen_internal_sym PARAMS ((const char *));
#define TEXT_SECTION_NAME ".text"
#endif
/* Section flags for .debug_str section. */
#ifdef HAVE_GAS_SHF_MERGE
#define DEBUG_STR_SECTION_FLAGS \
(SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1)
#else
#define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG
#endif
/* Labels we insert at beginning sections we can reference instead of
the section names themselves. */
@ -4406,11 +4428,23 @@ add_AT_string (die, attr_kind, str)
const char *str;
{
dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
struct indirect_string_node *node;
if (! debug_str_hash)
{
debug_str_hash = ht_create (10);
debug_str_hash->alloc_node = indirect_string_alloc;
}
node = (struct indirect_string_node *)
ht_lookup (debug_str_hash, (const unsigned char *) str,
strlen (str), HT_ALLOC);
node->refcount++;
attr->dw_attr_next = NULL;
attr->dw_attr = attr_kind;
attr->dw_attr_val.val_class = dw_val_class_str;
attr->dw_attr_val.v.val_str = xstrdup (str);
attr->dw_attr_val.v.val_str = node;
add_dwarf_attr (die, attr);
}
@ -4420,7 +4454,52 @@ AT_string (a)
dw_attr_ref a;
{
if (a && AT_class (a) == dw_val_class_str)
return a->dw_attr_val.v.val_str;
return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id);
abort ();
}
/* Find out whether a string should be output inline in DIE
or out-of-line in .debug_str section. */
static int AT_string_form PARAMS ((dw_attr_ref));
static int
AT_string_form (a)
dw_attr_ref a;
{
if (a && AT_class (a) == dw_val_class_str)
{
struct indirect_string_node *node;
unsigned int len;
extern int const_labelno;
char label[32];
node = a->dw_attr_val.v.val_str;
if (node->form)
return node->form;
len = HT_LEN (&node->id) + 1;
/* If the string is shorter or equal to the size
of the reference, it is always better to put it
inline. */
if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
return node->form = DW_FORM_string;
if ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0)
{
/* If we cannot expect the linker to merge strings
in .debug_str section, only put it into .debug_str
if it is worth even in this single module. */
if ((len - DWARF_OFFSET_SIZE) * node->refcount <= len)
return node->form = DW_FORM_string;
}
ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
++const_labelno;
node->label = xstrdup (label);
return node->form = DW_FORM_strp;
}
abort ();
}
@ -4776,9 +4855,13 @@ free_AT (a)
switch (AT_class (a))
{
case dw_val_class_str:
if (a->dw_attr_val.v.val_str->refcount)
a->dw_attr_val.v.val_str->refcount--;
break;
case dw_val_class_lbl_id:
case dw_val_class_lbl_offset:
free (a->dw_attr_val.v.val_str);
free (a->dw_attr_val.v.val_lbl_id);
break;
case dw_val_class_float:
@ -5670,20 +5753,6 @@ build_abbrev_table (die)
build_abbrev_table (c);
}
/* Return the size of a string, including the null byte.
This used to treat backslashes as escapes, and hence they were not included
in the count. However, that conflicts with what ASM_OUTPUT_ASCII does,
which treats a backslash as a backslash, escaping it if necessary, and hence
we must include them in the count. */
static unsigned long
size_of_string (str)
const char *str;
{
return strlen (str) + 1;
}
/* Return the power-of-two number of bytes necessary to represent VALUE. */
static int
@ -5764,7 +5833,10 @@ size_of_die (die)
size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_str:
size += size_of_string (AT_string (a));
if (AT_string_form (a) == DW_FORM_strp)
size += DWARF_OFFSET_SIZE;
else
size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1;
break;
default:
abort ();
@ -5836,7 +5908,7 @@ size_of_pubnames ()
for (i = 0; i < pubname_table_in_use; ++i)
{
pubname_ref p = &pubname_table[i];
size += DWARF_OFFSET_SIZE + size_of_string (p->name);
size += DWARF_OFFSET_SIZE + strlen (p->name) + 1;
}
size += DWARF_OFFSET_SIZE;
@ -5925,7 +5997,7 @@ value_format (a)
case dw_val_class_lbl_offset:
return DW_FORM_data;
case dw_val_class_str:
return DW_FORM_string;
return AT_string_form (a);
default:
abort ();
@ -6084,6 +6156,7 @@ output_loc_list (list_head)
"Location list terminator end (%s)",
list_head->ll_symbol);
}
/* Output the DIE and its attributes. Called recursively to generate
the definitions of each child DIE. */
@ -6223,7 +6296,12 @@ output_die (die)
break;
case dw_val_class_str:
dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
if (AT_string_form (a) == DW_FORM_strp)
dw2_asm_output_offset (DWARF_OFFSET_SIZE,
a->dw_attr_val.v.val_str->label,
"%s", name);
else
dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
break;
default:
@ -11706,6 +11784,43 @@ dwarf2out_init (main_input_filename)
}
}
/* Allocate a string in .debug_str hash table. */
static hashnode
indirect_string_alloc (tab)
hash_table *tab ATTRIBUTE_UNUSED;
{
struct indirect_string_node *node;
node = xmalloc (sizeof (struct indirect_string_node));
node->refcount = 0;
node->form = 0;
node->label = NULL;
return (hashnode) node;
}
/* A helper function for dwarf2out_finish called through
ht_forall. Emit one queued .debug_str string. */
static int
output_indirect_string (pfile, h, v)
struct cpp_reader *pfile ATTRIBUTE_UNUSED;
hashnode h;
const PTR v ATTRIBUTE_UNUSED;
{
struct indirect_string_node *node;
node = (struct indirect_string_node *) h;
if (node->form == DW_FORM_strp)
{
named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS);
ASM_OUTPUT_LABEL (asm_out_file, node->label);
assemble_string ((const char *) HT_STR (&node->id),
HT_LEN (&node->id) + 1);
}
return 1;
}
/* Output stuff that dwarf requires at the end of every file,
and generate the DWARF-2 debugging info. */
@ -11845,5 +11960,10 @@ dwarf2out_finish (input_filename)
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
}
/* If we emitted any DW_FORM_strp form attribute, output string
table too. */
if (debug_str_hash)
ht_forall (debug_str_hash, output_indirect_string, NULL);
}
#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */