xref: /openbsd-src/gnu/usr.bin/binutils/gas/stabs.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* Generic stabs parsing for gas.
2b55d4692Sfgsch    Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
3b305b0f1Sespie    Free Software Foundation, Inc.
42159047fSniklas 
52159047fSniklas This file is part of GAS, the GNU Assembler.
62159047fSniklas 
72159047fSniklas GAS is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as
92159047fSniklas published by the Free Software Foundation; either version 2,
102159047fSniklas or (at your option) any later version.
112159047fSniklas 
122159047fSniklas GAS is distributed in the hope that it will be useful, but
132159047fSniklas WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
152159047fSniklas the GNU General Public License for more details.
162159047fSniklas 
170c6d0228Sniklas You should have received a copy of the GNU General Public License
180c6d0228Sniklas along with GAS; see the file COPYING.  If not, write to the Free
190c6d0228Sniklas Software Foundation, 59 Temple Place - Suite 330, Boston, MA
200c6d0228Sniklas 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #include "as.h"
232159047fSniklas #include "obstack.h"
242159047fSniklas #include "subsegs.h"
250c6d0228Sniklas #include "ecoff.h"
262159047fSniklas 
272159047fSniklas /* We need this, despite the apparent object format dependency, since
282159047fSniklas    it defines stab types, which all object formats can use now.  */
292159047fSniklas 
302159047fSniklas #include "aout/stab_gnu.h"
312159047fSniklas 
32b55d4692Sfgsch /* Holds whether the assembler is generating stabs line debugging
33b55d4692Sfgsch    information or not.  Potentially used by md_cleanup function.  */
34b55d4692Sfgsch 
35b55d4692Sfgsch int outputting_stabs_line_debug = 0;
36b55d4692Sfgsch 
37*007c2a45Smiod static void s_stab_generic (int, char *, char *);
38*007c2a45Smiod static void generate_asm_file (int, char *);
39b305b0f1Sespie 
402159047fSniklas /* Allow backends to override the names used for the stab sections.  */
412159047fSniklas #ifndef STAB_SECTION_NAME
422159047fSniklas #define STAB_SECTION_NAME ".stab"
432159047fSniklas #endif
442159047fSniklas 
452159047fSniklas #ifndef STAB_STRING_SECTION_NAME
462159047fSniklas #define STAB_STRING_SECTION_NAME ".stabstr"
472159047fSniklas #endif
482159047fSniklas 
49b305b0f1Sespie /* Non-zero if we're in the middle of a .func function, in which case
50b305b0f1Sespie    stabs_generate_asm_lineno emits function relative line number stabs.
51b305b0f1Sespie    Otherwise it emits line number stabs with absolute addresses.  Note that
52b305b0f1Sespie    both cases only apply to assembler code assembled with -gstabs.  */
53b305b0f1Sespie static int in_dot_func_p;
54b305b0f1Sespie 
55b305b0f1Sespie /* Label at start of current function if in_dot_func_p != 0.  */
56b305b0f1Sespie static const char *current_function_label;
57b305b0f1Sespie 
582159047fSniklas /*
592159047fSniklas  * Handle .stabX directives, which used to be open-coded.
602159047fSniklas  * So much creeping featurism overloaded the semantics that we decided
612159047fSniklas  * to put all .stabX thinking in one place. Here.
622159047fSniklas  *
632159047fSniklas  * We try to make any .stabX directive legal. Other people's AS will often
642159047fSniklas  * do assembly-time consistency checks: eg assigning meaning to n_type bits
652159047fSniklas  * and "protecting" you from setting them to certain values. (They also zero
662159047fSniklas  * certain bits before emitting symbols. Tut tut.)
672159047fSniklas  *
682159047fSniklas  * If an expression is not absolute we either gripe or use the relocation
692159047fSniklas  * information. Other people's assemblers silently forget information they
702159047fSniklas  * don't need and invent information they need that you didn't supply.
712159047fSniklas  */
722159047fSniklas 
732159047fSniklas /*
742159047fSniklas  * Build a string dictionary entry for a .stabX symbol.
752159047fSniklas  * The symbol is added to the .<secname>str section.
762159047fSniklas  */
772159047fSniklas 
782159047fSniklas #ifndef SEPARATE_STAB_SECTIONS
792159047fSniklas #define SEPARATE_STAB_SECTIONS 0
802159047fSniklas #endif
812159047fSniklas 
822159047fSniklas unsigned int
get_stab_string_offset(const char * string,const char * stabstr_secname)83*007c2a45Smiod get_stab_string_offset (const char *string, const char *stabstr_secname)
842159047fSniklas {
852159047fSniklas   unsigned int length;
862159047fSniklas   unsigned int retval;
872159047fSniklas   segT save_seg;
882159047fSniklas   subsegT save_subseg;
892159047fSniklas   segT seg;
902159047fSniklas   char *p;
912159047fSniklas 
92b305b0f1Sespie   if (! SEPARATE_STAB_SECTIONS)
93b305b0f1Sespie     abort ();
94b305b0f1Sespie 
95b305b0f1Sespie   length = strlen (string);
96b305b0f1Sespie 
972159047fSniklas   save_seg = now_seg;
982159047fSniklas   save_subseg = now_subseg;
992159047fSniklas 
1002159047fSniklas   /* Create the stab string section.  */
1012159047fSniklas   seg = subseg_new (stabstr_secname, 0);
1022159047fSniklas 
1032159047fSniklas   retval = seg_info (seg)->stabu.stab_string_size;
1042159047fSniklas   if (retval <= 0)
1052159047fSniklas     {
1062159047fSniklas       /* Make sure the first string is empty.  */
1072159047fSniklas       p = frag_more (1);
1082159047fSniklas       *p = 0;
1092159047fSniklas       retval = seg_info (seg)->stabu.stab_string_size = 1;
1102159047fSniklas #ifdef BFD_ASSEMBLER
1112159047fSniklas       bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
1122159047fSniklas       if (seg->name == stabstr_secname)
113191aa565Sniklas 	seg->name = xstrdup (stabstr_secname);
1142159047fSniklas #endif
1152159047fSniklas     }
1162159047fSniklas 
117b305b0f1Sespie   if (length > 0)
118b305b0f1Sespie     {				/* Ordinary case.  */
1192159047fSniklas       p = frag_more (length + 1);
1202159047fSniklas       strcpy (p, string);
1212159047fSniklas 
1222159047fSniklas       seg_info (seg)->stabu.stab_string_size += length + 1;
123b305b0f1Sespie     }
124b305b0f1Sespie   else
125b305b0f1Sespie     retval = 0;
1262159047fSniklas 
1272159047fSniklas   subseg_set (save_seg, save_subseg);
1282159047fSniklas 
1292159047fSniklas   return retval;
1302159047fSniklas }
1312159047fSniklas 
1322159047fSniklas #ifdef AOUT_STABS
1332159047fSniklas #ifndef OBJ_PROCESS_STAB
1342159047fSniklas #define OBJ_PROCESS_STAB(SEG,W,S,T,O,D)	aout_process_stab(W,S,T,O,D)
1352159047fSniklas #endif
1362159047fSniklas 
137b55d4692Sfgsch /* Here instead of obj-aout.c because other formats use it too.  */
138b55d4692Sfgsch void
aout_process_stab(what,string,type,other,desc)1392159047fSniklas aout_process_stab (what, string, type, other, desc)
1402159047fSniklas      int what;
1412159047fSniklas      const char *string;
1422159047fSniklas      int type, other, desc;
1432159047fSniklas {
1442159047fSniklas   /* Put the stab information in the symbol table.  */
1452159047fSniklas   symbolS *symbol;
1462159047fSniklas 
1472159047fSniklas   /* Create the symbol now, but only insert it into the symbol chain
1482159047fSniklas      after any symbols mentioned in the value expression get into the
1492159047fSniklas      symbol chain.  This is to avoid "continuation symbols" (where one
1502159047fSniklas      ends in "\" and the debug info is continued in the next .stabs
1512159047fSniklas      directive) from being separated by other random symbols.  */
1522159047fSniklas   symbol = symbol_create (string, undefined_section, 0,
1532159047fSniklas 			  (struct frag *) NULL);
1542159047fSniklas   if (what == 's' || what == 'n')
1552159047fSniklas     {
1562159047fSniklas       /* Pick up the value from the input line.  */
157b305b0f1Sespie       symbol_set_frag (symbol, &zero_address_frag);
1582159047fSniklas       pseudo_set (symbol);
1592159047fSniklas     }
1602159047fSniklas   else
1612159047fSniklas     {
1622159047fSniklas       /* .stabd sets the name to NULL.  Why?  */
1632159047fSniklas       S_SET_NAME (symbol, NULL);
164b305b0f1Sespie       symbol_set_frag (symbol, frag_now);
1652159047fSniklas       S_SET_VALUE (symbol, (valueT) frag_now_fix ());
1662159047fSniklas     }
1672159047fSniklas 
1682159047fSniklas   symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
1692159047fSniklas 
1702159047fSniklas   S_SET_TYPE (symbol, type);
1712159047fSniklas   S_SET_OTHER (symbol, other);
1722159047fSniklas   S_SET_DESC (symbol, desc);
1732159047fSniklas }
1742159047fSniklas #endif
1752159047fSniklas 
1762159047fSniklas /* This can handle different kinds of stabs (s,n,d) and different
1772159047fSniklas    kinds of stab sections.  */
1782159047fSniklas 
1792159047fSniklas static void
s_stab_generic(int what,char * stab_secname,char * stabstr_secname)180*007c2a45Smiod s_stab_generic (int what, char *stab_secname, char *stabstr_secname)
1812159047fSniklas {
1822159047fSniklas   long longint;
183b55d4692Sfgsch   char *string, *saved_string_obstack_end;
1842159047fSniklas   int type;
1852159047fSniklas   int other;
1862159047fSniklas   int desc;
1872159047fSniklas 
1882159047fSniklas   /* The general format is:
1892159047fSniklas      .stabs "STRING",TYPE,OTHER,DESC,VALUE
1902159047fSniklas      .stabn TYPE,OTHER,DESC,VALUE
1912159047fSniklas      .stabd TYPE,OTHER,DESC
1922159047fSniklas      At this point input_line_pointer points after the pseudo-op and
1932159047fSniklas      any trailing whitespace.  The argument what is one of 's', 'n' or
1942159047fSniklas      'd' indicating which type of .stab this is.  */
1952159047fSniklas 
1962159047fSniklas   if (what != 's')
197b55d4692Sfgsch     {
1982159047fSniklas       string = "";
199b55d4692Sfgsch       saved_string_obstack_end = 0;
200b55d4692Sfgsch     }
2012159047fSniklas   else
2022159047fSniklas     {
2032159047fSniklas       int length;
2042159047fSniklas 
2052159047fSniklas       string = demand_copy_C_string (&length);
206b55d4692Sfgsch       /* FIXME: We should probably find some other temporary storage
207b55d4692Sfgsch 	 for string, rather than leaking memory if someone else
208b55d4692Sfgsch 	 happens to use the notes obstack.  */
209b55d4692Sfgsch       saved_string_obstack_end = notes.next_free;
2102159047fSniklas       SKIP_WHITESPACE ();
2112159047fSniklas       if (*input_line_pointer == ',')
2122159047fSniklas 	input_line_pointer++;
2132159047fSniklas       else
2142159047fSniklas 	{
215c074d1c9Sdrahn 	  as_warn (_(".stab%c: missing comma"), what);
2162159047fSniklas 	  ignore_rest_of_line ();
2172159047fSniklas 	  return;
2182159047fSniklas 	}
2192159047fSniklas     }
2202159047fSniklas 
2212159047fSniklas   if (get_absolute_expression_and_terminator (&longint) != ',')
2222159047fSniklas     {
223c074d1c9Sdrahn       as_warn (_(".stab%c: missing comma"), what);
2242159047fSniklas       ignore_rest_of_line ();
2252159047fSniklas       return;
2262159047fSniklas     }
2272159047fSniklas   type = longint;
2282159047fSniklas 
2292159047fSniklas   if (get_absolute_expression_and_terminator (&longint) != ',')
2302159047fSniklas     {
231c074d1c9Sdrahn       as_warn (_(".stab%c: missing comma"), what);
2322159047fSniklas       ignore_rest_of_line ();
2332159047fSniklas       return;
2342159047fSniklas     }
2352159047fSniklas   other = longint;
2362159047fSniklas 
2372159047fSniklas   desc = get_absolute_expression ();
238c074d1c9Sdrahn 
239c074d1c9Sdrahn   if ((desc > 0xffff) || (desc < -0x8000))
240c074d1c9Sdrahn     /* This could happen for example with a source file with a huge
241c074d1c9Sdrahn        number of lines.  The only cure is to use a different debug
242c074d1c9Sdrahn        format, probably DWARF.  */
243c074d1c9Sdrahn     as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
244c074d1c9Sdrahn 	     what, desc);
245c074d1c9Sdrahn 
2462159047fSniklas   if (what == 's' || what == 'n')
2472159047fSniklas     {
2482159047fSniklas       if (*input_line_pointer != ',')
2492159047fSniklas 	{
250c074d1c9Sdrahn 	  as_warn (_(".stab%c: missing comma"), what);
2512159047fSniklas 	  ignore_rest_of_line ();
2522159047fSniklas 	  return;
2532159047fSniklas 	}
2542159047fSniklas       input_line_pointer++;
2552159047fSniklas       SKIP_WHITESPACE ();
2562159047fSniklas     }
2572159047fSniklas 
258191aa565Sniklas #ifdef TC_PPC
259191aa565Sniklas #ifdef OBJ_ELF
260191aa565Sniklas   /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
261191aa565Sniklas      given 4 arguments, make it a .stabn */
262191aa565Sniklas   else if (what == 'd')
263191aa565Sniklas     {
264191aa565Sniklas       char *save_location = input_line_pointer;
265191aa565Sniklas 
266191aa565Sniklas       SKIP_WHITESPACE ();
267191aa565Sniklas       if (*input_line_pointer == ',')
268191aa565Sniklas 	{
269191aa565Sniklas 	  input_line_pointer++;
270191aa565Sniklas 	  what = 'n';
271191aa565Sniklas 	}
272191aa565Sniklas       else
273191aa565Sniklas 	input_line_pointer = save_location;
274191aa565Sniklas     }
275191aa565Sniklas #endif /* OBJ_ELF */
276191aa565Sniklas #endif /* TC_PPC */
277191aa565Sniklas 
278191aa565Sniklas #ifndef NO_LISTING
279191aa565Sniklas   if (listing)
280191aa565Sniklas     {
281191aa565Sniklas       switch (type)
282191aa565Sniklas 	{
283191aa565Sniklas 	case N_SLINE:
284191aa565Sniklas 	  listing_source_line ((unsigned int) desc);
285191aa565Sniklas 	  break;
286191aa565Sniklas 	case N_SO:
287191aa565Sniklas 	case N_SOL:
288191aa565Sniklas 	  listing_source_file (string);
289191aa565Sniklas 	  break;
290191aa565Sniklas 	}
291191aa565Sniklas     }
292191aa565Sniklas #endif /* ! NO_LISTING */
293191aa565Sniklas 
2942159047fSniklas   /* We have now gathered the type, other, and desc information.  For
2952159047fSniklas      .stabs or .stabn, input_line_pointer is now pointing at the
2962159047fSniklas      value.  */
2972159047fSniklas 
2982159047fSniklas   if (SEPARATE_STAB_SECTIONS)
2992159047fSniklas     /* Output the stab information in a separate section.  This is used
3002159047fSniklas        at least for COFF and ELF.  */
3012159047fSniklas     {
3022159047fSniklas       segT saved_seg = now_seg;
3032159047fSniklas       subsegT saved_subseg = now_subseg;
3042159047fSniklas       fragS *saved_frag = frag_now;
3052159047fSniklas       valueT dot;
3062159047fSniklas       segT seg;
3072159047fSniklas       unsigned int stroff;
3082159047fSniklas       char *p;
3092159047fSniklas 
3102159047fSniklas       static segT cached_sec;
3112159047fSniklas       static char *cached_secname;
3122159047fSniklas 
3132159047fSniklas       dot = frag_now_fix ();
3142159047fSniklas 
315b305b0f1Sespie #ifdef md_flush_pending_output
316b305b0f1Sespie       md_flush_pending_output ();
317b305b0f1Sespie #endif
318b305b0f1Sespie 
3192159047fSniklas       if (cached_secname && !strcmp (cached_secname, stab_secname))
3202159047fSniklas 	{
3212159047fSniklas 	  seg = cached_sec;
3222159047fSniklas 	  subseg_set (seg, 0);
3232159047fSniklas 	}
3242159047fSniklas       else
3252159047fSniklas 	{
3262159047fSniklas 	  seg = subseg_new (stab_secname, 0);
3272159047fSniklas 	  if (cached_secname)
3282159047fSniklas 	    free (cached_secname);
329191aa565Sniklas 	  cached_secname = xstrdup (stab_secname);
3302159047fSniklas 	  cached_sec = seg;
3312159047fSniklas 	}
3322159047fSniklas 
3332159047fSniklas       if (! seg_info (seg)->hadone)
3342159047fSniklas 	{
3352159047fSniklas #ifdef BFD_ASSEMBLER
3362159047fSniklas 	  bfd_set_section_flags (stdoutput, seg,
3372159047fSniklas 				 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
3382159047fSniklas #endif
3392159047fSniklas #ifdef INIT_STAB_SECTION
3402159047fSniklas 	  INIT_STAB_SECTION (seg);
3412159047fSniklas #endif
3422159047fSniklas 	  seg_info (seg)->hadone = 1;
3432159047fSniklas 	}
3442159047fSniklas 
3452159047fSniklas       stroff = get_stab_string_offset (string, stabstr_secname);
346191aa565Sniklas       if (what == 's')
347191aa565Sniklas 	{
348b55d4692Sfgsch 	  /* Release the string, if nobody else has used the obstack.  */
349b55d4692Sfgsch 	  if (saved_string_obstack_end == notes.next_free)
350191aa565Sniklas 	    obstack_free (&notes, string);
351191aa565Sniklas 	}
3522159047fSniklas 
3532159047fSniklas       /* At least for now, stabs in a special stab section are always
3542159047fSniklas 	 output as 12 byte blocks of information.  */
3552159047fSniklas       p = frag_more (8);
3562159047fSniklas       md_number_to_chars (p, (valueT) stroff, 4);
3572159047fSniklas       md_number_to_chars (p + 4, (valueT) type, 1);
3582159047fSniklas       md_number_to_chars (p + 5, (valueT) other, 1);
3592159047fSniklas       md_number_to_chars (p + 6, (valueT) desc, 2);
3602159047fSniklas 
3612159047fSniklas       if (what == 's' || what == 'n')
3622159047fSniklas 	{
3632159047fSniklas 	  /* Pick up the value from the input line.  */
3642159047fSniklas 	  cons (4);
3652159047fSniklas 	  input_line_pointer--;
3662159047fSniklas 	}
3672159047fSniklas       else
3682159047fSniklas 	{
3692159047fSniklas 	  symbolS *symbol;
3702159047fSniklas 	  expressionS exp;
3712159047fSniklas 
3722159047fSniklas 	  /* Arrange for a value representing the current location.  */
373*007c2a45Smiod 	  symbol = symbol_temp_new (saved_seg, dot, saved_frag);
3742159047fSniklas 
3752159047fSniklas 	  exp.X_op = O_symbol;
3762159047fSniklas 	  exp.X_add_symbol = symbol;
3772159047fSniklas 	  exp.X_add_number = 0;
3782159047fSniklas 
3792159047fSniklas 	  emit_expr (&exp, 4);
3802159047fSniklas 	}
3812159047fSniklas 
3822159047fSniklas #ifdef OBJ_PROCESS_STAB
383191aa565Sniklas       OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
3842159047fSniklas #endif
3852159047fSniklas 
3862159047fSniklas       subseg_set (saved_seg, saved_subseg);
3872159047fSniklas     }
3882159047fSniklas   else
3892159047fSniklas     {
3902159047fSniklas #ifdef OBJ_PROCESS_STAB
3912159047fSniklas       OBJ_PROCESS_STAB (0, what, string, type, other, desc);
3922159047fSniklas #else
3932159047fSniklas       abort ();
3942159047fSniklas #endif
3952159047fSniklas     }
3962159047fSniklas 
3972159047fSniklas   demand_empty_rest_of_line ();
3982159047fSniklas }
3992159047fSniklas 
4002159047fSniklas /* Regular stab directive.  */
4012159047fSniklas 
4022159047fSniklas void
s_stab(int what)403*007c2a45Smiod s_stab (int what)
4042159047fSniklas {
4052159047fSniklas   s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
4062159047fSniklas }
4072159047fSniklas 
4082159047fSniklas /* "Extended stabs", used in Solaris only now.  */
4092159047fSniklas 
4102159047fSniklas void
s_xstab(int what)411*007c2a45Smiod s_xstab (int what)
4122159047fSniklas {
4132159047fSniklas   int length;
4142159047fSniklas   char *stab_secname, *stabstr_secname;
4152159047fSniklas   static char *saved_secname, *saved_strsecname;
4162159047fSniklas 
4172159047fSniklas   /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
4182159047fSniklas      cases it will be the same string, so we could release the storage
4192159047fSniklas      back to the obstack it came from.  */
4202159047fSniklas   stab_secname = demand_copy_C_string (&length);
4212159047fSniklas   SKIP_WHITESPACE ();
4222159047fSniklas   if (*input_line_pointer == ',')
4232159047fSniklas     input_line_pointer++;
4242159047fSniklas   else
4252159047fSniklas     {
426b305b0f1Sespie       as_bad (_("comma missing in .xstabs"));
4272159047fSniklas       ignore_rest_of_line ();
4282159047fSniklas       return;
4292159047fSniklas     }
4302159047fSniklas 
4312159047fSniklas   /* To get the name of the stab string section, simply add "str" to
4322159047fSniklas      the stab section name.  */
4332159047fSniklas   if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
4342159047fSniklas     {
4352159047fSniklas       stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
4362159047fSniklas       strcpy (stabstr_secname, stab_secname);
4372159047fSniklas       strcat (stabstr_secname, "str");
4382159047fSniklas       if (saved_secname)
4392159047fSniklas 	{
4402159047fSniklas 	  free (saved_secname);
4412159047fSniklas 	  free (saved_strsecname);
4422159047fSniklas 	}
4432159047fSniklas       saved_secname = stab_secname;
4442159047fSniklas       saved_strsecname = stabstr_secname;
4452159047fSniklas     }
4462159047fSniklas   s_stab_generic (what, saved_secname, saved_strsecname);
4472159047fSniklas }
4482159047fSniklas 
4492159047fSniklas #ifdef S_SET_DESC
4502159047fSniklas 
4512159047fSniklas /* Frob invented at RMS' request. Set the n_desc of a symbol.  */
4522159047fSniklas 
4532159047fSniklas void
s_desc(ignore)4542159047fSniklas s_desc (ignore)
455b55d4692Sfgsch      int ignore ATTRIBUTE_UNUSED;
4562159047fSniklas {
4572159047fSniklas   char *name;
4582159047fSniklas   char c;
4592159047fSniklas   char *p;
4602159047fSniklas   symbolS *symbolP;
4612159047fSniklas   int temp;
4622159047fSniklas 
4632159047fSniklas   name = input_line_pointer;
4642159047fSniklas   c = get_symbol_end ();
4652159047fSniklas   p = input_line_pointer;
4662159047fSniklas   *p = c;
4672159047fSniklas   SKIP_WHITESPACE ();
4682159047fSniklas   if (*input_line_pointer != ',')
4692159047fSniklas     {
4702159047fSniklas       *p = 0;
471c074d1c9Sdrahn       as_bad (_("expected comma after \"%s\""), name);
4722159047fSniklas       *p = c;
4732159047fSniklas       ignore_rest_of_line ();
4742159047fSniklas     }
4752159047fSniklas   else
4762159047fSniklas     {
4772159047fSniklas       input_line_pointer++;
4782159047fSniklas       temp = get_absolute_expression ();
4792159047fSniklas       *p = 0;
4802159047fSniklas       symbolP = symbol_find_or_make (name);
4812159047fSniklas       *p = c;
4822159047fSniklas       S_SET_DESC (symbolP, temp);
4832159047fSniklas     }
4842159047fSniklas   demand_empty_rest_of_line ();
4852159047fSniklas }				/* s_desc() */
4862159047fSniklas 
4872159047fSniklas #endif /* defined (S_SET_DESC) */
488b305b0f1Sespie 
489b305b0f1Sespie /* Generate stabs debugging information to denote the main source file.  */
490b305b0f1Sespie 
491b305b0f1Sespie void
stabs_generate_asm_file(void)492*007c2a45Smiod stabs_generate_asm_file (void)
493b305b0f1Sespie {
494b305b0f1Sespie   char *file;
495b305b0f1Sespie   unsigned int lineno;
496b305b0f1Sespie 
497b305b0f1Sespie   as_where (&file, &lineno);
498*007c2a45Smiod   if (use_gnu_debug_info_extensions)
499*007c2a45Smiod     {
500*007c2a45Smiod       char *dir, *dir2;
501*007c2a45Smiod 
502*007c2a45Smiod       dir = getpwd ();
503*007c2a45Smiod       dir2 = alloca (strlen (dir) + 2);
504*007c2a45Smiod       sprintf (dir2, "%s%s", dir, "/");
505*007c2a45Smiod       generate_asm_file (N_SO, dir2);
506*007c2a45Smiod     }
507b305b0f1Sespie   generate_asm_file (N_SO, file);
508b305b0f1Sespie }
509b305b0f1Sespie 
510b305b0f1Sespie /* Generate stabs debugging information to denote the source file.
511b305b0f1Sespie    TYPE is one of N_SO, N_SOL.  */
512b305b0f1Sespie 
513b305b0f1Sespie static void
generate_asm_file(int type,char * file)514*007c2a45Smiod generate_asm_file (int type, char *file)
515b305b0f1Sespie {
516b305b0f1Sespie   static char *last_file;
517b305b0f1Sespie   static int label_count;
518b305b0f1Sespie   char *hold;
519b305b0f1Sespie   char sym[30];
520b55d4692Sfgsch   char *buf;
521b55d4692Sfgsch   char *tmp = file;
522b55d4692Sfgsch   char *endp = file + strlen (file);
523*007c2a45Smiod   char *bufp;
524b55d4692Sfgsch 
525b55d4692Sfgsch   if (last_file != NULL
526b55d4692Sfgsch       && strcmp (last_file, file) == 0)
527b55d4692Sfgsch     return;
528b305b0f1Sespie 
529b305b0f1Sespie   /* Rather than try to do this in some efficient fashion, we just
530b305b0f1Sespie      generate a string and then parse it again.  That lets us use the
531b305b0f1Sespie      existing stabs hook, which expect to see a string, rather than
532b305b0f1Sespie      inventing new ones.  */
533b305b0f1Sespie   hold = input_line_pointer;
534b305b0f1Sespie 
535b305b0f1Sespie   sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
536b305b0f1Sespie   ++label_count;
537b305b0f1Sespie 
538b55d4692Sfgsch   /* Allocate enough space for the file name (possibly extended with
539b55d4692Sfgsch      doubled up backslashes), the symbol name, and the other characters
540b55d4692Sfgsch      that make up a stabs file directive.  */
541b55d4692Sfgsch   bufp = buf = xmalloc (2 * strlen (file) + strlen (sym) + 12);
542b55d4692Sfgsch 
543b305b0f1Sespie   *bufp++ = '"';
544b55d4692Sfgsch 
545b305b0f1Sespie   while (tmp < endp)
546b305b0f1Sespie     {
547b305b0f1Sespie       char *bslash = strchr (tmp, '\\');
548c074d1c9Sdrahn       size_t len = (bslash) ? (size_t) (bslash - tmp + 1) : strlen (tmp);
549b55d4692Sfgsch 
550b55d4692Sfgsch       /* Double all backslashes, since demand_copy_C_string (used by
551b305b0f1Sespie 	 s_stab to extract the part in quotes) will try to replace them as
552b305b0f1Sespie 	 escape sequences.  backslash may appear in a filespec.  */
553b305b0f1Sespie       strncpy (bufp, tmp, len);
554b55d4692Sfgsch 
555b305b0f1Sespie       tmp += len;
556b305b0f1Sespie       bufp += len;
557b55d4692Sfgsch 
558b305b0f1Sespie       if (bslash != NULL)
559b305b0f1Sespie 	*bufp++ = '\\';
560b305b0f1Sespie     }
561b55d4692Sfgsch 
562b305b0f1Sespie   sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
563b55d4692Sfgsch 
564b305b0f1Sespie   input_line_pointer = buf;
565b305b0f1Sespie   s_stab ('s');
566b305b0f1Sespie   colon (sym);
567b305b0f1Sespie 
568b305b0f1Sespie   if (last_file != NULL)
569b305b0f1Sespie     free (last_file);
570b305b0f1Sespie   last_file = xstrdup (file);
571b55d4692Sfgsch 
572b55d4692Sfgsch   free (buf);
573b305b0f1Sespie 
574b305b0f1Sespie   input_line_pointer = hold;
575b305b0f1Sespie }
576b305b0f1Sespie 
577b305b0f1Sespie /* Generate stabs debugging information for the current line.  This is
578b305b0f1Sespie    used to produce debugging information for an assembler file.  */
579b305b0f1Sespie 
580b305b0f1Sespie void
stabs_generate_asm_lineno(void)581*007c2a45Smiod stabs_generate_asm_lineno (void)
582b305b0f1Sespie {
583b305b0f1Sespie   static int label_count;
584b305b0f1Sespie   char *hold;
585b305b0f1Sespie   char *file;
586b305b0f1Sespie   unsigned int lineno;
587b305b0f1Sespie   char *buf;
588b305b0f1Sespie   char sym[30];
589c074d1c9Sdrahn   /* Remember the last file/line and avoid duplicates.  */
590c074d1c9Sdrahn   static unsigned int prev_lineno = -1;
591c074d1c9Sdrahn   static char *prev_file = NULL;
592b55d4692Sfgsch 
593b305b0f1Sespie   /* Rather than try to do this in some efficient fashion, we just
594b305b0f1Sespie      generate a string and then parse it again.  That lets us use the
595b305b0f1Sespie      existing stabs hook, which expect to see a string, rather than
596b305b0f1Sespie      inventing new ones.  */
597b305b0f1Sespie 
598b305b0f1Sespie   hold = input_line_pointer;
599b305b0f1Sespie 
600b305b0f1Sespie   as_where (&file, &lineno);
601b305b0f1Sespie 
602c074d1c9Sdrahn   /* Don't emit sequences of stabs for the same line.  */
603c074d1c9Sdrahn   if (prev_file == NULL)
604c074d1c9Sdrahn     {
605c074d1c9Sdrahn       /* First time thru.  */
606c074d1c9Sdrahn       prev_file = xstrdup (file);
607c074d1c9Sdrahn       prev_lineno = lineno;
608c074d1c9Sdrahn     }
609c074d1c9Sdrahn   else if (lineno == prev_lineno
610c074d1c9Sdrahn 	   && strcmp (file, prev_file) == 0)
611c074d1c9Sdrahn     {
612c074d1c9Sdrahn       /* Same file/line as last time.  */
613c074d1c9Sdrahn       return;
614c074d1c9Sdrahn     }
615c074d1c9Sdrahn   else
616c074d1c9Sdrahn     {
617c074d1c9Sdrahn       /* Remember file/line for next time.  */
618c074d1c9Sdrahn       prev_lineno = lineno;
619c074d1c9Sdrahn       if (strcmp (file, prev_file) != 0)
620c074d1c9Sdrahn 	{
621c074d1c9Sdrahn 	  free (prev_file);
622c074d1c9Sdrahn 	  prev_file = xstrdup (file);
623c074d1c9Sdrahn 	}
624c074d1c9Sdrahn     }
625c074d1c9Sdrahn 
626c074d1c9Sdrahn   /* Let the world know that we are in the middle of generating a
627c074d1c9Sdrahn      piece of stabs line debugging information.  */
628c074d1c9Sdrahn   outputting_stabs_line_debug = 1;
629c074d1c9Sdrahn 
630b305b0f1Sespie   generate_asm_file (N_SOL, file);
631b305b0f1Sespie 
632b305b0f1Sespie   sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
633b305b0f1Sespie   ++label_count;
634b305b0f1Sespie 
635b305b0f1Sespie   if (in_dot_func_p)
636b305b0f1Sespie     {
637b305b0f1Sespie       buf = (char *) alloca (100 + strlen (current_function_label));
638b305b0f1Sespie       sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
639b305b0f1Sespie 	       sym, current_function_label);
640b305b0f1Sespie     }
641b305b0f1Sespie   else
642b305b0f1Sespie     {
643b305b0f1Sespie       buf = (char *) alloca (100);
644b305b0f1Sespie       sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
645b305b0f1Sespie     }
646b305b0f1Sespie   input_line_pointer = buf;
647b305b0f1Sespie   s_stab ('n');
648b305b0f1Sespie   colon (sym);
649b305b0f1Sespie 
650b305b0f1Sespie   input_line_pointer = hold;
651b55d4692Sfgsch   outputting_stabs_line_debug = 0;
652b305b0f1Sespie }
653b305b0f1Sespie 
654b305b0f1Sespie /* Emit a function stab.
655b305b0f1Sespie    All assembler functions are assumed to have return type `void'.  */
656b305b0f1Sespie 
657b305b0f1Sespie void
stabs_generate_asm_func(const char * funcname,const char * startlabname)658*007c2a45Smiod stabs_generate_asm_func (const char *funcname, const char *startlabname)
659b305b0f1Sespie {
660b305b0f1Sespie   static int void_emitted_p;
661b305b0f1Sespie   char *hold = input_line_pointer;
662b305b0f1Sespie   char *buf;
663b305b0f1Sespie   char *file;
664b305b0f1Sespie   unsigned int lineno;
665b305b0f1Sespie 
666b305b0f1Sespie   if (! void_emitted_p)
667b305b0f1Sespie     {
668b305b0f1Sespie       input_line_pointer = "\"void:t1=1\",128,0,0,0";
669b305b0f1Sespie       s_stab ('s');
670b305b0f1Sespie       void_emitted_p = 1;
671b305b0f1Sespie     }
672b305b0f1Sespie 
673b305b0f1Sespie   as_where (&file, &lineno);
674b305b0f1Sespie   asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
675b305b0f1Sespie 	    funcname, N_FUN, lineno + 1, startlabname);
676b305b0f1Sespie   input_line_pointer = buf;
677b305b0f1Sespie   s_stab ('s');
678b305b0f1Sespie   free (buf);
679b305b0f1Sespie 
680b305b0f1Sespie   input_line_pointer = hold;
681b305b0f1Sespie   current_function_label = xstrdup (startlabname);
682b305b0f1Sespie   in_dot_func_p = 1;
683b305b0f1Sespie }
684b305b0f1Sespie 
685b305b0f1Sespie /* Emit a stab to record the end of a function.  */
686b305b0f1Sespie 
687b305b0f1Sespie void
stabs_generate_asm_endfunc(const char * funcname ATTRIBUTE_UNUSED,const char * startlabname)688*007c2a45Smiod stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
689*007c2a45Smiod 			    const char *startlabname)
690b305b0f1Sespie {
691b305b0f1Sespie   static int label_count;
692b305b0f1Sespie   char *hold = input_line_pointer;
693b305b0f1Sespie   char *buf;
694b305b0f1Sespie   char sym[30];
695b305b0f1Sespie 
696b305b0f1Sespie   sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
697b305b0f1Sespie   ++label_count;
698b305b0f1Sespie   colon (sym);
699b305b0f1Sespie 
700b305b0f1Sespie   asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
701b305b0f1Sespie   input_line_pointer = buf;
702b305b0f1Sespie   s_stab ('s');
703b305b0f1Sespie   free (buf);
704b305b0f1Sespie 
705b305b0f1Sespie   input_line_pointer = hold;
706b305b0f1Sespie   in_dot_func_p = 0;
707b305b0f1Sespie   current_function_label = NULL;
708b305b0f1Sespie }
709