This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Bug with merging COFF debug symbols
- To: binutils at sourceware dot cygnus dot com
- Subject: Bug with merging COFF debug symbols
- From: "Mark E." <snowball3 at bigfoot dot com>
- Date: Sun, 16 Jul 2000 00:41:37 -0400
Hi guys,
I found a bug in the BFD version of gas in handling COFF debug symbols and
common symbols, but I'm not quite sure what the right fix is.
The problem can be demonstrated with the following assembly code:
.def ___attr_desc_type_node; .val ___attr_desc_type_node; .scl 2;
.tag _tree_node; .size 100; .type 031; .endef
.comm ___attr_desc_type_node,4
This produces the nm output:
00000000 b .bss
00000000 d .data
00000000 t .text
00000004 C ___attr_desc_type_node
U ___attr_desc_type_node
U _tree_node
You can see that the debug symbol is never deleted.
coff_frob_symbol, used by BFD gas, uses this code:
if (!SF_GET_DEBUG (symp))
{
symbolS *real;
if (!SF_GET_LOCAL (symp)
&& !SF_GET_STATICS (symp)
&& (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
&& real != symp)
{
c_symbol_merge (symp, real);
*punt = 1;
}
if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
{
assert (S_GET_VALUE (symp) == 0);
/* XXX: The next function call prevents the debug symbol from being
deleted upon return. */
S_SET_EXTERNAL (symp);
}
else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
{
if (S_GET_SEGMENT (symp) == text_section
&& symp != seg_info (text_section)->sym)
S_SET_STORAGE_CLASS (symp, C_LABEL);
else
S_SET_STORAGE_CLASS (symp, C_STAT);
}
yank_symbols, used by non-BFD gas, has very similiar code:
if (!SF_GET_DEBUG (symbolP))
{
/* Debug symbols do not need all this rubbish */
symbolS *real_symbolP;
/* L* and C_EFCN symbols never merge. */
if (!SF_GET_LOCAL (symbolP)
&& !SF_GET_STATICS (symbolP)
&& S_GET_STORAGE_CLASS (symbolP) != C_LABEL
&& symbolP->sy_value.X_op == O_constant
&& (real_symbolP = symbol_find_base (S_GET_NAME (symbolP),
DO_NOT_STRIP))
&& real_symbolP != symbolP)
{
/* FIXME-SOON: where do dups come from?
Maybe tag references before definitions? xoxorich. */
/* Move the debug data from the debug symbol to the
real symbol. Do NOT do the oposite (i.e. move from
real symbol to debug symbol and remove real symbol from the
list.) Because some pointers refer to the real symbol
whereas no pointers refer to the debug symbol. */
c_symbol_merge (symbolP, real_symbolP);
/* Replace the current symbol by the real one */
/* The symbols will never be the last or the first
because : 1st symbol is .file and 3 last symbols are
.text, .data, .bss */
symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP);
symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
symbolP = real_symbolP;
} /* if not local but dup'd */
if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1))
{
S_SET_SEGMENT (symbolP, SEG_E0);
} /* push data into text */
resolve_symbol_value (symbolP, 1);
if (S_GET_STORAGE_CLASS (symbolP) == C_NULL)
{
if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP))
{
S_SET_EXTERNAL (symbolP);
}
else if (S_GET_SEGMENT (symbolP) == SEG_E0)
{
S_SET_STORAGE_CLASS (symbolP, C_LABEL);
}
else
{
S_SET_STORAGE_CLASS (symbolP, C_STAT);
}
}
If the code marked with 'XXX' in coff_frob_symbol is only executed if *punt
is 0, then the debug symbol is deleted as it should be. But the problem could
also be solved by making that section of code be executed if the
storage_class is C_NULL like in yank_symbols.
I think the latter solution if the right way to go, if for no other reason
that the code in yank_symbols has been working for years with COFF debug
symbols and the code in coff_frob_symbol hasn't.
Mark