Home | History | Annotate | Line # | Download | only in gas
stabs.c revision 1.1.1.7
      1      1.1  christos /* Generic stabs parsing for gas.
      2  1.1.1.7  christos    Copyright (C) 1989-2024 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of GAS, the GNU Assembler.
      5      1.1  christos 
      6      1.1  christos    GAS is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as
      8      1.1  christos    published by the Free Software Foundation; either version 3,
      9      1.1  christos    or (at your option) any later version.
     10      1.1  christos 
     11      1.1  christos    GAS is distributed in the hope that it will be useful, but
     12      1.1  christos    WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     14      1.1  christos    the GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     18      1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19      1.1  christos    02110-1301, USA.  */
     20      1.1  christos 
     21      1.1  christos #include "as.h"
     22      1.1  christos #include "filenames.h"
     23      1.1  christos #include "obstack.h"
     24      1.1  christos #include "subsegs.h"
     25      1.1  christos #include "ecoff.h"
     26      1.1  christos 
     27      1.1  christos /* We need this, despite the apparent object format dependency, since
     28      1.1  christos    it defines stab types, which all object formats can use now.  */
     29      1.1  christos 
     30      1.1  christos #include "aout/stab_gnu.h"
     31      1.1  christos 
     32      1.1  christos /* Holds whether the assembler is generating stabs line debugging
     33      1.1  christos    information or not.  Potentially used by md_cleanup function.  */
     34      1.1  christos 
     35      1.1  christos int outputting_stabs_line_debug = 0;
     36      1.1  christos 
     37  1.1.1.3  christos static void generate_asm_file (int, const char *);
     38      1.1  christos 
     39      1.1  christos /* Allow backends to override the names used for the stab sections.  */
     40      1.1  christos #ifndef STAB_SECTION_NAME
     41      1.1  christos #define STAB_SECTION_NAME ".stab"
     42      1.1  christos #endif
     43      1.1  christos 
     44      1.1  christos #ifndef STAB_STRING_SECTION_NAME
     45      1.1  christos #define STAB_STRING_SECTION_NAME ".stabstr"
     46      1.1  christos #endif
     47      1.1  christos 
     48  1.1.1.7  christos /* Label at start of current function if we're in the middle of a
     49  1.1.1.7  christos    .func function, in which case stabs_generate_asm_lineno emits
     50  1.1.1.7  christos    function relative line number stabs.  Otherwise it emits line
     51  1.1.1.7  christos    number stabs with absolute addresses.  Note that both cases only
     52  1.1.1.7  christos    apply to assembler code assembled with -gstabs.  */
     53      1.1  christos static const char *current_function_label;
     54      1.1  christos 
     55  1.1.1.7  christos /* State used by generate_asm_file.  */
     56  1.1.1.7  christos static char *last_asm_file;
     57  1.1.1.7  christos static int file_label_count;
     58  1.1.1.7  christos 
     59  1.1.1.7  christos /* State used by stabs_generate_asm_lineno.  */
     60  1.1.1.7  christos static int line_label_count;
     61  1.1.1.7  christos static unsigned int prev_lineno;
     62  1.1.1.7  christos static char *prev_line_file;
     63  1.1.1.7  christos 
     64  1.1.1.7  christos /* State used by stabs_generate_asm_func.  */
     65  1.1.1.7  christos static bool void_emitted_p;
     66  1.1.1.7  christos 
     67  1.1.1.7  christos /* State used by stabs_generate_asm_endfunc.  */
     68  1.1.1.7  christos static int endfunc_label_count;
     69  1.1.1.7  christos 
     70      1.1  christos /*
     71      1.1  christos  * Handle .stabX directives, which used to be open-coded.
     72      1.1  christos  * So much creeping featurism overloaded the semantics that we decided
     73      1.1  christos  * to put all .stabX thinking in one place. Here.
     74      1.1  christos  *
     75      1.1  christos  * We try to make any .stabX directive legal. Other people's AS will often
     76      1.1  christos  * do assembly-time consistency checks: eg assigning meaning to n_type bits
     77      1.1  christos  * and "protecting" you from setting them to certain values. (They also zero
     78      1.1  christos  * certain bits before emitting symbols. Tut tut.)
     79      1.1  christos  *
     80      1.1  christos  * If an expression is not absolute we either gripe or use the relocation
     81      1.1  christos  * information. Other people's assemblers silently forget information they
     82      1.1  christos  * don't need and invent information they need that you didn't supply.
     83      1.1  christos  */
     84      1.1  christos 
     85      1.1  christos /*
     86      1.1  christos  * Build a string dictionary entry for a .stabX symbol.
     87      1.1  christos  * The symbol is added to the .<secname>str section.
     88      1.1  christos  */
     89      1.1  christos 
     90      1.1  christos #ifndef SEPARATE_STAB_SECTIONS
     91      1.1  christos #define SEPARATE_STAB_SECTIONS 0
     92      1.1  christos #endif
     93      1.1  christos 
     94      1.1  christos unsigned int
     95  1.1.1.7  christos get_stab_string_offset (const char *string, segT stabstr)
     96      1.1  christos {
     97      1.1  christos   unsigned int length;
     98      1.1  christos   unsigned int retval;
     99      1.1  christos   segT save_seg;
    100      1.1  christos   subsegT save_subseg;
    101      1.1  christos   char *p;
    102      1.1  christos 
    103      1.1  christos   if (! SEPARATE_STAB_SECTIONS)
    104      1.1  christos     abort ();
    105      1.1  christos 
    106      1.1  christos   length = strlen (string);
    107      1.1  christos 
    108      1.1  christos   save_seg = now_seg;
    109      1.1  christos   save_subseg = now_subseg;
    110      1.1  christos 
    111  1.1.1.7  christos   subseg_set (stabstr, 0);
    112      1.1  christos 
    113  1.1.1.7  christos   retval = seg_info (stabstr)->stabu.stab_string_size;
    114      1.1  christos   if (retval <= 0)
    115      1.1  christos     {
    116      1.1  christos       /* Make sure the first string is empty.  */
    117      1.1  christos       p = frag_more (1);
    118      1.1  christos       *p = 0;
    119  1.1.1.7  christos       retval = seg_info (stabstr)->stabu.stab_string_size = 1;
    120  1.1.1.7  christos       bfd_set_section_flags (stabstr, SEC_READONLY | SEC_DEBUGGING);
    121      1.1  christos     }
    122      1.1  christos 
    123      1.1  christos   if (length > 0)
    124      1.1  christos     {				/* Ordinary case.  */
    125      1.1  christos       p = frag_more (length + 1);
    126      1.1  christos       strcpy (p, string);
    127      1.1  christos 
    128  1.1.1.7  christos       seg_info (stabstr)->stabu.stab_string_size += length + 1;
    129      1.1  christos     }
    130      1.1  christos   else
    131      1.1  christos     retval = 0;
    132      1.1  christos 
    133      1.1  christos   subseg_set (save_seg, save_subseg);
    134      1.1  christos 
    135      1.1  christos   return retval;
    136      1.1  christos }
    137      1.1  christos 
    138      1.1  christos #ifdef AOUT_STABS
    139      1.1  christos #ifndef OBJ_PROCESS_STAB
    140  1.1.1.7  christos #define OBJ_PROCESS_STAB(W,S,T,O,D)	aout_process_stab(W,S,T,O,D)
    141      1.1  christos #endif
    142      1.1  christos 
    143      1.1  christos /* Here instead of obj-aout.c because other formats use it too.  */
    144      1.1  christos void
    145  1.1.1.3  christos aout_process_stab (int what, const char *string, int type, int other, int desc)
    146      1.1  christos {
    147      1.1  christos   /* Put the stab information in the symbol table.  */
    148      1.1  christos   symbolS *symbol;
    149      1.1  christos 
    150      1.1  christos   /* Create the symbol now, but only insert it into the symbol chain
    151      1.1  christos      after any symbols mentioned in the value expression get into the
    152      1.1  christos      symbol chain.  This is to avoid "continuation symbols" (where one
    153      1.1  christos      ends in "\" and the debug info is continued in the next .stabs
    154      1.1  christos      directive) from being separated by other random symbols.  */
    155  1.1.1.6  christos   symbol = symbol_create (string, undefined_section, &zero_address_frag, 0);
    156      1.1  christos   if (what == 's' || what == 'n')
    157      1.1  christos     {
    158      1.1  christos       /* Pick up the value from the input line.  */
    159      1.1  christos       pseudo_set (symbol);
    160      1.1  christos     }
    161      1.1  christos   else
    162      1.1  christos     {
    163      1.1  christos       /* .stabd sets the name to NULL.  Why?  */
    164      1.1  christos       S_SET_NAME (symbol, NULL);
    165      1.1  christos       symbol_set_frag (symbol, frag_now);
    166      1.1  christos       S_SET_VALUE (symbol, (valueT) frag_now_fix ());
    167      1.1  christos     }
    168      1.1  christos 
    169      1.1  christos   symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
    170      1.1  christos 
    171      1.1  christos   symbol_get_bfdsym (symbol)->flags |= BSF_DEBUGGING;
    172      1.1  christos 
    173      1.1  christos   S_SET_TYPE (symbol, type);
    174      1.1  christos   S_SET_OTHER (symbol, other);
    175      1.1  christos   S_SET_DESC (symbol, desc);
    176      1.1  christos }
    177      1.1  christos #endif
    178      1.1  christos 
    179  1.1.1.7  christos static bool
    180  1.1.1.7  christos eat_comma (int what)
    181  1.1.1.7  christos {
    182  1.1.1.7  christos   if (*input_line_pointer == ',')
    183  1.1.1.7  christos     {
    184  1.1.1.7  christos       input_line_pointer++;
    185  1.1.1.7  christos       return true;
    186  1.1.1.7  christos     }
    187  1.1.1.7  christos   as_warn (_(".stab%c: missing comma"), what);
    188  1.1.1.7  christos   ignore_rest_of_line ();
    189  1.1.1.7  christos   return false;
    190  1.1.1.7  christos }
    191  1.1.1.7  christos 
    192      1.1  christos /* This can handle different kinds of stabs (s,n,d) and different
    193  1.1.1.7  christos    kinds of stab sections.  If FREENAMES is true, then STAB_SECNAME
    194  1.1.1.7  christos    and STABSTR_SECNAME are allocated in that order on the notes
    195  1.1.1.7  christos    obstack and will be freed if possible.  */
    196      1.1  christos 
    197      1.1  christos static void
    198  1.1.1.5  christos s_stab_generic (int what,
    199  1.1.1.5  christos 		const char *stab_secname,
    200  1.1.1.5  christos 		const char *stabstr_secname,
    201  1.1.1.7  christos 		bool freenames)
    202      1.1  christos {
    203  1.1.1.3  christos   const char *string;
    204  1.1.1.3  christos   char *saved_string_obstack_end;
    205      1.1  christos   int type;
    206      1.1  christos   int other;
    207      1.1  christos   int desc;
    208  1.1.1.7  christos   segT stab, stabstr = NULL;
    209  1.1.1.7  christos   segT saved_seg = now_seg;
    210  1.1.1.7  christos   subsegT saved_subseg = now_subseg;
    211  1.1.1.7  christos   fragS *saved_frag = frag_now;
    212  1.1.1.7  christos   valueT dot = 0;
    213  1.1.1.7  christos 
    214  1.1.1.7  christos   if (SEPARATE_STAB_SECTIONS)
    215  1.1.1.7  christos     /* Output the stab information in a separate section.  This is used
    216  1.1.1.7  christos        at least for COFF and ELF.  */
    217  1.1.1.7  christos     {
    218  1.1.1.7  christos       dot = frag_now_fix ();
    219  1.1.1.7  christos 
    220  1.1.1.7  christos #ifdef md_flush_pending_output
    221  1.1.1.7  christos       md_flush_pending_output ();
    222  1.1.1.7  christos #endif
    223  1.1.1.7  christos       stab = subseg_new (stab_secname, 0);
    224  1.1.1.7  christos       stabstr = subseg_new (stabstr_secname, 0);
    225  1.1.1.7  christos 
    226  1.1.1.7  christos       if (freenames
    227  1.1.1.7  christos 	  && stab->name != stab_secname
    228  1.1.1.7  christos 	  && stabstr->name != stabstr_secname)
    229  1.1.1.7  christos 	obstack_free (&notes, stab_secname);
    230  1.1.1.7  christos 
    231  1.1.1.7  christos       subseg_set (stab, 0);
    232  1.1.1.7  christos       if (!seg_info (stab)->hadone)
    233  1.1.1.7  christos 	{
    234  1.1.1.7  christos 	  bfd_set_section_flags (stab,
    235  1.1.1.7  christos 				 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
    236  1.1.1.7  christos #ifdef INIT_STAB_SECTION
    237  1.1.1.7  christos 	  INIT_STAB_SECTION (stab, stabstr);
    238  1.1.1.7  christos #endif
    239  1.1.1.7  christos 	  seg_info (stab)->hadone = 1;
    240  1.1.1.7  christos 	}
    241  1.1.1.7  christos     }
    242  1.1.1.7  christos   else if (freenames)
    243  1.1.1.7  christos     obstack_free (&notes, stab_secname);
    244      1.1  christos 
    245      1.1  christos   /* The general format is:
    246      1.1  christos      .stabs "STRING",TYPE,OTHER,DESC,VALUE
    247      1.1  christos      .stabn TYPE,OTHER,DESC,VALUE
    248      1.1  christos      .stabd TYPE,OTHER,DESC
    249      1.1  christos      At this point input_line_pointer points after the pseudo-op and
    250      1.1  christos      any trailing whitespace.  The argument what is one of 's', 'n' or
    251      1.1  christos      'd' indicating which type of .stab this is.  */
    252      1.1  christos 
    253  1.1.1.7  christos   saved_string_obstack_end = NULL;
    254      1.1  christos   if (what != 's')
    255  1.1.1.7  christos     string = "";
    256      1.1  christos   else
    257      1.1  christos     {
    258      1.1  christos       int length;
    259      1.1  christos 
    260      1.1  christos       string = demand_copy_C_string (&length);
    261  1.1.1.4  christos       if (string == NULL)
    262  1.1.1.4  christos 	{
    263  1.1.1.4  christos 	  as_warn (_(".stab%c: missing string"), what);
    264  1.1.1.4  christos 	  ignore_rest_of_line ();
    265  1.1.1.7  christos 	  goto out2;
    266  1.1.1.4  christos 	}
    267      1.1  christos       /* FIXME: We should probably find some other temporary storage
    268      1.1  christos 	 for string, rather than leaking memory if someone else
    269      1.1  christos 	 happens to use the notes obstack.  */
    270  1.1.1.5  christos       saved_string_obstack_end = obstack_next_free (&notes);
    271      1.1  christos       SKIP_WHITESPACE ();
    272  1.1.1.7  christos       if (!eat_comma (what))
    273  1.1.1.7  christos 	goto out;
    274      1.1  christos     }
    275      1.1  christos 
    276  1.1.1.7  christos   type = get_absolute_expression ();
    277  1.1.1.7  christos   if (!eat_comma (what))
    278  1.1.1.7  christos     goto out;
    279      1.1  christos 
    280  1.1.1.7  christos   other = get_absolute_expression ();
    281  1.1.1.7  christos   if (!eat_comma (what))
    282  1.1.1.7  christos     goto out;
    283      1.1  christos 
    284      1.1  christos   desc = get_absolute_expression ();
    285      1.1  christos 
    286      1.1  christos   if ((desc > 0xffff) || (desc < -0x8000))
    287      1.1  christos     /* This could happen for example with a source file with a huge
    288      1.1  christos        number of lines.  The only cure is to use a different debug
    289      1.1  christos        format, probably DWARF.  */
    290      1.1  christos     as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
    291      1.1  christos 	     what, desc);
    292      1.1  christos 
    293      1.1  christos   if (what == 's' || what == 'n')
    294      1.1  christos     {
    295  1.1.1.7  christos       if (!eat_comma (what))
    296  1.1.1.7  christos 	goto out;
    297      1.1  christos       SKIP_WHITESPACE ();
    298      1.1  christos     }
    299      1.1  christos 
    300      1.1  christos #ifdef TC_PPC
    301      1.1  christos #ifdef OBJ_ELF
    302      1.1  christos   /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
    303      1.1  christos      given 4 arguments, make it a .stabn */
    304      1.1  christos   else if (what == 'd')
    305      1.1  christos     {
    306      1.1  christos       char *save_location = input_line_pointer;
    307      1.1  christos 
    308      1.1  christos       SKIP_WHITESPACE ();
    309      1.1  christos       if (*input_line_pointer == ',')
    310      1.1  christos 	{
    311      1.1  christos 	  input_line_pointer++;
    312      1.1  christos 	  what = 'n';
    313      1.1  christos 	}
    314      1.1  christos       else
    315      1.1  christos 	input_line_pointer = save_location;
    316      1.1  christos     }
    317      1.1  christos #endif /* OBJ_ELF */
    318      1.1  christos #endif /* TC_PPC */
    319      1.1  christos 
    320      1.1  christos #ifndef NO_LISTING
    321      1.1  christos   if (listing)
    322      1.1  christos     {
    323      1.1  christos       switch (type)
    324      1.1  christos 	{
    325      1.1  christos 	case N_SLINE:
    326      1.1  christos 	  listing_source_line ((unsigned int) desc);
    327      1.1  christos 	  break;
    328      1.1  christos 	case N_SO:
    329      1.1  christos 	case N_SOL:
    330      1.1  christos 	  listing_source_file (string);
    331      1.1  christos 	  break;
    332      1.1  christos 	}
    333      1.1  christos     }
    334      1.1  christos #endif /* ! NO_LISTING */
    335      1.1  christos 
    336      1.1  christos   /* We have now gathered the type, other, and desc information.  For
    337      1.1  christos      .stabs or .stabn, input_line_pointer is now pointing at the
    338      1.1  christos      value.  */
    339      1.1  christos 
    340      1.1  christos   if (SEPARATE_STAB_SECTIONS)
    341      1.1  christos     /* Output the stab information in a separate section.  This is used
    342      1.1  christos        at least for COFF and ELF.  */
    343      1.1  christos     {
    344      1.1  christos       unsigned int stroff;
    345      1.1  christos       char *p;
    346      1.1  christos 
    347  1.1.1.7  christos       stroff = get_stab_string_offset (string, stabstr);
    348      1.1  christos 
    349  1.1.1.7  christos       /* Release the string, if nobody else has used the obstack.
    350  1.1.1.7  christos 	 This must be done before creating symbols below, which uses
    351  1.1.1.7  christos 	 the notes obstack.  */
    352  1.1.1.7  christos       if (saved_string_obstack_end == obstack_next_free (&notes))
    353      1.1  christos 	{
    354  1.1.1.7  christos 	  obstack_free (&notes, string);
    355  1.1.1.7  christos 	  saved_string_obstack_end = NULL;
    356      1.1  christos 	}
    357      1.1  christos 
    358      1.1  christos       /* At least for now, stabs in a special stab section are always
    359      1.1  christos 	 output as 12 byte blocks of information.  */
    360      1.1  christos       p = frag_more (8);
    361      1.1  christos       md_number_to_chars (p, (valueT) stroff, 4);
    362      1.1  christos       md_number_to_chars (p + 4, (valueT) type, 1);
    363      1.1  christos       md_number_to_chars (p + 5, (valueT) other, 1);
    364      1.1  christos       md_number_to_chars (p + 6, (valueT) desc, 2);
    365      1.1  christos 
    366      1.1  christos       if (what == 's' || what == 'n')
    367      1.1  christos 	{
    368      1.1  christos 	  /* Pick up the value from the input line.  */
    369      1.1  christos 	  cons (4);
    370      1.1  christos 	  input_line_pointer--;
    371      1.1  christos 	}
    372      1.1  christos       else
    373      1.1  christos 	{
    374      1.1  christos 	  symbolS *symbol;
    375      1.1  christos 	  expressionS exp;
    376      1.1  christos 
    377      1.1  christos 	  /* Arrange for a value representing the current location.  */
    378  1.1.1.6  christos 	  symbol = symbol_temp_new (saved_seg, saved_frag, dot);
    379      1.1  christos 
    380      1.1  christos 	  exp.X_op = O_symbol;
    381      1.1  christos 	  exp.X_add_symbol = symbol;
    382      1.1  christos 	  exp.X_add_number = 0;
    383      1.1  christos 
    384      1.1  christos 	  emit_expr (&exp, 4);
    385      1.1  christos 	}
    386      1.1  christos 
    387      1.1  christos #ifdef OBJ_PROCESS_STAB
    388  1.1.1.7  christos       OBJ_PROCESS_STAB (what, string, type, other, desc);
    389      1.1  christos #endif
    390      1.1  christos     }
    391      1.1  christos   else
    392      1.1  christos     {
    393      1.1  christos #ifdef OBJ_PROCESS_STAB
    394  1.1.1.7  christos       OBJ_PROCESS_STAB (what, string, type, other, desc);
    395      1.1  christos #else
    396      1.1  christos       abort ();
    397      1.1  christos #endif
    398      1.1  christos     }
    399      1.1  christos 
    400      1.1  christos   demand_empty_rest_of_line ();
    401  1.1.1.7  christos  out:
    402  1.1.1.7  christos   if (saved_string_obstack_end == obstack_next_free (&notes))
    403  1.1.1.7  christos     obstack_free (&notes, string);
    404  1.1.1.7  christos  out2:
    405  1.1.1.7  christos   subseg_set (saved_seg, saved_subseg);
    406      1.1  christos }
    407      1.1  christos 
    408      1.1  christos /* Regular stab directive.  */
    409      1.1  christos 
    410      1.1  christos void
    411      1.1  christos s_stab (int what)
    412      1.1  christos {
    413  1.1.1.7  christos   s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME, false);
    414      1.1  christos }
    415      1.1  christos 
    416      1.1  christos /* "Extended stabs", used in Solaris only now.  */
    417      1.1  christos 
    418      1.1  christos void
    419      1.1  christos s_xstab (int what)
    420      1.1  christos {
    421      1.1  christos   int length;
    422  1.1.1.7  christos   char *stab_secname, *stabstr_secname;
    423      1.1  christos 
    424      1.1  christos   stab_secname = demand_copy_C_string (&length);
    425      1.1  christos   SKIP_WHITESPACE ();
    426      1.1  christos   if (*input_line_pointer == ',')
    427  1.1.1.7  christos     {
    428  1.1.1.7  christos       input_line_pointer++;
    429  1.1.1.7  christos       /* To get the name of the stab string section, simply add
    430  1.1.1.7  christos 	 "str" to the stab section name.  */
    431  1.1.1.7  christos       stabstr_secname = notes_concat (stab_secname, "str", (char *) NULL);
    432  1.1.1.7  christos       s_stab_generic (what, stab_secname, stabstr_secname, true);
    433  1.1.1.7  christos     }
    434      1.1  christos   else
    435      1.1  christos     {
    436      1.1  christos       as_bad (_("comma missing in .xstabs"));
    437      1.1  christos       ignore_rest_of_line ();
    438      1.1  christos     }
    439      1.1  christos }
    440      1.1  christos 
    441      1.1  christos #ifdef S_SET_DESC
    442      1.1  christos 
    443      1.1  christos /* Frob invented at RMS' request. Set the n_desc of a symbol.  */
    444      1.1  christos 
    445      1.1  christos void
    446  1.1.1.3  christos s_desc (int ignore ATTRIBUTE_UNUSED)
    447      1.1  christos {
    448      1.1  christos   char *name;
    449      1.1  christos   char c;
    450      1.1  christos   char *p;
    451      1.1  christos   symbolS *symbolP;
    452      1.1  christos   int temp;
    453      1.1  christos 
    454  1.1.1.2  christos   c = get_symbol_name (&name);
    455      1.1  christos   p = input_line_pointer;
    456      1.1  christos   *p = c;
    457  1.1.1.2  christos   SKIP_WHITESPACE_AFTER_NAME ();
    458      1.1  christos   if (*input_line_pointer != ',')
    459      1.1  christos     {
    460      1.1  christos       *p = 0;
    461      1.1  christos       as_bad (_("expected comma after \"%s\""), name);
    462      1.1  christos       *p = c;
    463      1.1  christos       ignore_rest_of_line ();
    464      1.1  christos     }
    465      1.1  christos   else
    466      1.1  christos     {
    467      1.1  christos       input_line_pointer++;
    468      1.1  christos       temp = get_absolute_expression ();
    469      1.1  christos       *p = 0;
    470      1.1  christos       symbolP = symbol_find_or_make (name);
    471      1.1  christos       *p = c;
    472      1.1  christos       S_SET_DESC (symbolP, temp);
    473      1.1  christos     }
    474      1.1  christos   demand_empty_rest_of_line ();
    475      1.1  christos }				/* s_desc() */
    476      1.1  christos 
    477      1.1  christos #endif /* defined (S_SET_DESC) */
    478      1.1  christos 
    479      1.1  christos /* Generate stabs debugging information to denote the main source file.  */
    480      1.1  christos 
    481      1.1  christos void
    482      1.1  christos stabs_generate_asm_file (void)
    483      1.1  christos {
    484  1.1.1.3  christos   const char *file;
    485      1.1  christos   unsigned int lineno;
    486      1.1  christos 
    487  1.1.1.3  christos   file = as_where (&lineno);
    488      1.1  christos   if (use_gnu_debug_info_extensions)
    489      1.1  christos     {
    490  1.1.1.6  christos       char *dir;
    491      1.1  christos       char *dir2;
    492      1.1  christos 
    493      1.1  christos       dir = remap_debug_filename (getpwd ());
    494  1.1.1.3  christos       dir2 = concat (dir, "/", NULL);
    495      1.1  christos       generate_asm_file (N_SO, dir2);
    496  1.1.1.3  christos       free (dir2);
    497  1.1.1.6  christos       free (dir);
    498      1.1  christos     }
    499      1.1  christos   generate_asm_file (N_SO, file);
    500      1.1  christos }
    501      1.1  christos 
    502      1.1  christos /* Generate stabs debugging information to denote the source file.
    503      1.1  christos    TYPE is one of N_SO, N_SOL.  */
    504      1.1  christos 
    505      1.1  christos static void
    506  1.1.1.3  christos generate_asm_file (int type, const char *file)
    507      1.1  christos {
    508      1.1  christos   char sym[30];
    509      1.1  christos   char *buf;
    510  1.1.1.3  christos   const char *tmp = file;
    511  1.1.1.3  christos   const char *file_endp = file + strlen (file);
    512      1.1  christos   char *bufp;
    513      1.1  christos 
    514  1.1.1.7  christos   if (last_asm_file != NULL
    515  1.1.1.7  christos       && filename_cmp (last_asm_file, file) == 0)
    516      1.1  christos     return;
    517      1.1  christos 
    518      1.1  christos   /* Rather than try to do this in some efficient fashion, we just
    519      1.1  christos      generate a string and then parse it again.  That lets us use the
    520      1.1  christos      existing stabs hook, which expect to see a string, rather than
    521      1.1  christos      inventing new ones.  */
    522  1.1.1.7  christos   sprintf (sym, "%sF%d", FAKE_LABEL_NAME, file_label_count);
    523  1.1.1.7  christos   ++file_label_count;
    524      1.1  christos 
    525      1.1  christos   /* Allocate enough space for the file name (possibly extended with
    526      1.1  christos      doubled up backslashes), the symbol name, and the other characters
    527      1.1  christos      that make up a stabs file directive.  */
    528  1.1.1.3  christos   bufp = buf = XNEWVEC (char, 2 * strlen (file) + strlen (sym) + 12);
    529      1.1  christos 
    530      1.1  christos   *bufp++ = '"';
    531      1.1  christos 
    532      1.1  christos   while (tmp < file_endp)
    533      1.1  christos     {
    534  1.1.1.3  christos       const char *bslash = strchr (tmp, '\\');
    535  1.1.1.4  christos       size_t len = bslash != NULL ? bslash - tmp + 1 : file_endp - tmp;
    536      1.1  christos 
    537      1.1  christos       /* Double all backslashes, since demand_copy_C_string (used by
    538      1.1  christos 	 s_stab to extract the part in quotes) will try to replace them as
    539      1.1  christos 	 escape sequences.  backslash may appear in a filespec.  */
    540  1.1.1.4  christos       memcpy (bufp, tmp, len);
    541      1.1  christos 
    542      1.1  christos       tmp += len;
    543      1.1  christos       bufp += len;
    544      1.1  christos 
    545      1.1  christos       if (bslash != NULL)
    546      1.1  christos 	*bufp++ = '\\';
    547      1.1  christos     }
    548      1.1  christos 
    549      1.1  christos   sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
    550      1.1  christos 
    551  1.1.1.4  christos   temp_ilp (buf);
    552      1.1  christos   s_stab ('s');
    553  1.1.1.4  christos   restore_ilp ();
    554  1.1.1.4  christos 
    555      1.1  christos   colon (sym);
    556      1.1  christos 
    557  1.1.1.7  christos   free (last_asm_file);
    558  1.1.1.7  christos   last_asm_file = xstrdup (file);
    559      1.1  christos 
    560      1.1  christos   free (buf);
    561      1.1  christos }
    562      1.1  christos 
    563      1.1  christos /* Generate stabs debugging information for the current line.  This is
    564      1.1  christos    used to produce debugging information for an assembler file.  */
    565      1.1  christos 
    566      1.1  christos void
    567      1.1  christos stabs_generate_asm_lineno (void)
    568      1.1  christos {
    569  1.1.1.3  christos   const char *file;
    570      1.1  christos   unsigned int lineno;
    571      1.1  christos   char *buf;
    572      1.1  christos   char sym[30];
    573      1.1  christos 
    574      1.1  christos   /* Rather than try to do this in some efficient fashion, we just
    575      1.1  christos      generate a string and then parse it again.  That lets us use the
    576      1.1  christos      existing stabs hook, which expect to see a string, rather than
    577      1.1  christos      inventing new ones.  */
    578      1.1  christos 
    579  1.1.1.3  christos   file = as_where (&lineno);
    580      1.1  christos 
    581      1.1  christos   /* Don't emit sequences of stabs for the same line.  */
    582  1.1.1.7  christos   if (prev_line_file != NULL
    583  1.1.1.7  christos       && filename_cmp (file, prev_line_file) == 0)
    584      1.1  christos     {
    585  1.1.1.7  christos       if (lineno == prev_lineno)
    586  1.1.1.7  christos 	/* Same file/line as last time.  */
    587  1.1.1.7  christos 	return;
    588      1.1  christos     }
    589      1.1  christos   else
    590      1.1  christos     {
    591      1.1  christos       /* Remember file/line for next time.  */
    592  1.1.1.7  christos       free (prev_line_file);
    593  1.1.1.7  christos       prev_line_file = xstrdup (file);
    594      1.1  christos     }
    595      1.1  christos 
    596  1.1.1.7  christos   prev_lineno = lineno;
    597  1.1.1.7  christos 
    598      1.1  christos   /* Let the world know that we are in the middle of generating a
    599      1.1  christos      piece of stabs line debugging information.  */
    600      1.1  christos   outputting_stabs_line_debug = 1;
    601      1.1  christos 
    602      1.1  christos   generate_asm_file (N_SOL, file);
    603      1.1  christos 
    604  1.1.1.7  christos   sprintf (sym, "%sL%d", FAKE_LABEL_NAME, line_label_count);
    605  1.1.1.7  christos   ++line_label_count;
    606      1.1  christos 
    607  1.1.1.7  christos   if (current_function_label)
    608      1.1  christos     {
    609  1.1.1.3  christos       buf = XNEWVEC (char, 100 + strlen (current_function_label));
    610      1.1  christos       sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
    611      1.1  christos 	       sym, current_function_label);
    612      1.1  christos     }
    613      1.1  christos   else
    614      1.1  christos     {
    615  1.1.1.3  christos       buf = XNEWVEC (char, 100);
    616      1.1  christos       sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
    617      1.1  christos     }
    618  1.1.1.4  christos 
    619  1.1.1.4  christos   temp_ilp (buf);
    620      1.1  christos   s_stab ('n');
    621  1.1.1.4  christos   restore_ilp ();
    622  1.1.1.4  christos 
    623      1.1  christos   colon (sym);
    624      1.1  christos 
    625      1.1  christos   outputting_stabs_line_debug = 0;
    626  1.1.1.3  christos   free (buf);
    627      1.1  christos }
    628      1.1  christos 
    629      1.1  christos /* Emit a function stab.
    630      1.1  christos    All assembler functions are assumed to have return type `void'.  */
    631      1.1  christos 
    632      1.1  christos void
    633      1.1  christos stabs_generate_asm_func (const char *funcname, const char *startlabname)
    634      1.1  christos {
    635      1.1  christos   char *buf;
    636      1.1  christos   unsigned int lineno;
    637      1.1  christos 
    638      1.1  christos   if (! void_emitted_p)
    639      1.1  christos     {
    640  1.1.1.4  christos       temp_ilp ((char *) "\"void:t1=1\",128,0,0,0");
    641      1.1  christos       s_stab ('s');
    642  1.1.1.4  christos       restore_ilp ();
    643  1.1.1.6  christos       void_emitted_p = true;
    644      1.1  christos     }
    645      1.1  christos 
    646  1.1.1.3  christos   as_where (&lineno);
    647      1.1  christos   if (asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
    648      1.1  christos 		funcname, N_FUN, lineno + 1, startlabname) == -1)
    649      1.1  christos     as_fatal ("%s", xstrerror (errno));
    650  1.1.1.4  christos 
    651  1.1.1.4  christos   temp_ilp (buf);
    652      1.1  christos   s_stab ('s');
    653  1.1.1.4  christos   restore_ilp ();
    654      1.1  christos   free (buf);
    655      1.1  christos 
    656  1.1.1.7  christos   free ((char *) current_function_label);
    657      1.1  christos   current_function_label = xstrdup (startlabname);
    658      1.1  christos }
    659      1.1  christos 
    660      1.1  christos /* Emit a stab to record the end of a function.  */
    661      1.1  christos 
    662      1.1  christos void
    663      1.1  christos stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
    664      1.1  christos 			    const char *startlabname)
    665      1.1  christos {
    666      1.1  christos   char *buf;
    667      1.1  christos   char sym[30];
    668      1.1  christos 
    669  1.1.1.7  christos   sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, endfunc_label_count);
    670  1.1.1.7  christos   ++endfunc_label_count;
    671      1.1  christos   colon (sym);
    672      1.1  christos 
    673      1.1  christos   if (asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname) == -1)
    674      1.1  christos     as_fatal ("%s", xstrerror (errno));
    675  1.1.1.4  christos 
    676  1.1.1.4  christos   temp_ilp (buf);
    677      1.1  christos   s_stab ('s');
    678  1.1.1.4  christos   restore_ilp ();
    679      1.1  christos   free (buf);
    680      1.1  christos 
    681  1.1.1.7  christos   free ((char *) current_function_label);
    682  1.1.1.7  christos   current_function_label = NULL;
    683  1.1.1.7  christos }
    684  1.1.1.7  christos 
    685  1.1.1.7  christos void
    686  1.1.1.7  christos stabs_begin (void)
    687  1.1.1.7  christos {
    688      1.1  christos   current_function_label = NULL;
    689  1.1.1.7  christos   last_asm_file = NULL;
    690  1.1.1.7  christos   file_label_count = 0;
    691  1.1.1.7  christos   line_label_count = 0;
    692  1.1.1.7  christos   prev_lineno = -1u;
    693  1.1.1.7  christos   prev_line_file = NULL;
    694  1.1.1.7  christos   void_emitted_p = false;
    695  1.1.1.7  christos   endfunc_label_count = 0;
    696  1.1.1.7  christos }
    697  1.1.1.7  christos 
    698  1.1.1.7  christos void
    699  1.1.1.7  christos stabs_end (void)
    700  1.1.1.7  christos {
    701  1.1.1.7  christos   free ((char *) current_function_label);
    702  1.1.1.7  christos   free (last_asm_file);
    703  1.1.1.7  christos   free (prev_line_file);
    704      1.1  christos }
    705