133965Sjdp/* Generic stabs parsing for gas.
278828Sobrien   Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
3218822Sdim   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GAS, the GNU Assembler.
633965Sjdp
733965SjdpGAS is free software; you can redistribute it and/or modify
833965Sjdpit under the terms of the GNU General Public License as
933965Sjdppublished by the Free Software Foundation; either version 2,
1033965Sjdpor (at your option) any later version.
1133965Sjdp
1233965SjdpGAS is distributed in the hope that it will be useful, but
1333965SjdpWITHOUT ANY WARRANTY; without even the implied warranty of
1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1533965Sjdpthe GNU General Public License for more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public License
1833965Sjdpalong with GAS; see the file COPYING.  If not, write to the Free
19218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim02110-1301, USA.  */
2133965Sjdp
2233965Sjdp#include "as.h"
2333965Sjdp#include "obstack.h"
2433965Sjdp#include "subsegs.h"
2533965Sjdp#include "ecoff.h"
2633965Sjdp
2733965Sjdp/* We need this, despite the apparent object format dependency, since
2877298Sobrien   it defines stab types, which all object formats can use now.  */
2933965Sjdp
3033965Sjdp#include "aout/stab_gnu.h"
3133965Sjdp
3277298Sobrien/* Holds whether the assembler is generating stabs line debugging
3377298Sobrien   information or not.  Potentially used by md_cleanup function.  */
3477298Sobrien
3577298Sobrienint outputting_stabs_line_debug = 0;
3677298Sobrien
37130561Sobrienstatic void s_stab_generic (int, char *, char *);
38130561Sobrienstatic void generate_asm_file (int, char *);
3933965Sjdp
4033965Sjdp/* Allow backends to override the names used for the stab sections.  */
4133965Sjdp#ifndef STAB_SECTION_NAME
4233965Sjdp#define STAB_SECTION_NAME ".stab"
4333965Sjdp#endif
4433965Sjdp
4533965Sjdp#ifndef STAB_STRING_SECTION_NAME
4633965Sjdp#define STAB_STRING_SECTION_NAME ".stabstr"
4733965Sjdp#endif
4833965Sjdp
4960484Sobrien/* Non-zero if we're in the middle of a .func function, in which case
5060484Sobrien   stabs_generate_asm_lineno emits function relative line number stabs.
5160484Sobrien   Otherwise it emits line number stabs with absolute addresses.  Note that
5260484Sobrien   both cases only apply to assembler code assembled with -gstabs.  */
5360484Sobrienstatic int in_dot_func_p;
5460484Sobrien
5560484Sobrien/* Label at start of current function if in_dot_func_p != 0.  */
5660484Sobrienstatic const char *current_function_label;
5760484Sobrien
5833965Sjdp/*
5933965Sjdp * Handle .stabX directives, which used to be open-coded.
6033965Sjdp * So much creeping featurism overloaded the semantics that we decided
6133965Sjdp * to put all .stabX thinking in one place. Here.
6233965Sjdp *
6333965Sjdp * We try to make any .stabX directive legal. Other people's AS will often
6433965Sjdp * do assembly-time consistency checks: eg assigning meaning to n_type bits
6533965Sjdp * and "protecting" you from setting them to certain values. (They also zero
6633965Sjdp * certain bits before emitting symbols. Tut tut.)
6733965Sjdp *
6833965Sjdp * If an expression is not absolute we either gripe or use the relocation
6933965Sjdp * information. Other people's assemblers silently forget information they
7033965Sjdp * don't need and invent information they need that you didn't supply.
7133965Sjdp */
7233965Sjdp
7333965Sjdp/*
7433965Sjdp * Build a string dictionary entry for a .stabX symbol.
7533965Sjdp * The symbol is added to the .<secname>str section.
7633965Sjdp */
7733965Sjdp
7833965Sjdp#ifndef SEPARATE_STAB_SECTIONS
7933965Sjdp#define SEPARATE_STAB_SECTIONS 0
8033965Sjdp#endif
8133965Sjdp
8233965Sjdpunsigned int
83130561Sobrienget_stab_string_offset (const char *string, const char *stabstr_secname)
8433965Sjdp{
8533965Sjdp  unsigned int length;
8633965Sjdp  unsigned int retval;
8738889Sjdp  segT save_seg;
8838889Sjdp  subsegT save_subseg;
8938889Sjdp  segT seg;
9038889Sjdp  char *p;
9133965Sjdp
9233965Sjdp  if (! SEPARATE_STAB_SECTIONS)
9333965Sjdp    abort ();
9433965Sjdp
9533965Sjdp  length = strlen (string);
9633965Sjdp
9738889Sjdp  save_seg = now_seg;
9838889Sjdp  save_subseg = now_subseg;
9933965Sjdp
10038889Sjdp  /* Create the stab string section.  */
10138889Sjdp  seg = subseg_new (stabstr_secname, 0);
10233965Sjdp
10338889Sjdp  retval = seg_info (seg)->stabu.stab_string_size;
10438889Sjdp  if (retval <= 0)
10538889Sjdp    {
10638889Sjdp      /* Make sure the first string is empty.  */
10738889Sjdp      p = frag_more (1);
10838889Sjdp      *p = 0;
10938889Sjdp      retval = seg_info (seg)->stabu.stab_string_size = 1;
11038889Sjdp      bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
11138889Sjdp      if (seg->name == stabstr_secname)
11238889Sjdp	seg->name = xstrdup (stabstr_secname);
11338889Sjdp    }
11433965Sjdp
11538889Sjdp  if (length > 0)
11677298Sobrien    {				/* Ordinary case.  */
11733965Sjdp      p = frag_more (length + 1);
11833965Sjdp      strcpy (p, string);
11933965Sjdp
12033965Sjdp      seg_info (seg)->stabu.stab_string_size += length + 1;
12133965Sjdp    }
12238889Sjdp  else
12338889Sjdp    retval = 0;
12433965Sjdp
12538889Sjdp  subseg_set (save_seg, save_subseg);
12638889Sjdp
12733965Sjdp  return retval;
12833965Sjdp}
12933965Sjdp
13033965Sjdp#ifdef AOUT_STABS
13133965Sjdp#ifndef OBJ_PROCESS_STAB
13233965Sjdp#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D)	aout_process_stab(W,S,T,O,D)
13333965Sjdp#endif
13433965Sjdp
13577298Sobrien/* Here instead of obj-aout.c because other formats use it too.  */
13677298Sobrienvoid
13733965Sjdpaout_process_stab (what, string, type, other, desc)
13833965Sjdp     int what;
13933965Sjdp     const char *string;
14033965Sjdp     int type, other, desc;
14133965Sjdp{
14233965Sjdp  /* Put the stab information in the symbol table.  */
14333965Sjdp  symbolS *symbol;
14433965Sjdp
14533965Sjdp  /* Create the symbol now, but only insert it into the symbol chain
14633965Sjdp     after any symbols mentioned in the value expression get into the
14733965Sjdp     symbol chain.  This is to avoid "continuation symbols" (where one
14833965Sjdp     ends in "\" and the debug info is continued in the next .stabs
14933965Sjdp     directive) from being separated by other random symbols.  */
15033965Sjdp  symbol = symbol_create (string, undefined_section, 0,
151218822Sdim			  &zero_address_frag);
15233965Sjdp  if (what == 's' || what == 'n')
15333965Sjdp    {
15433965Sjdp      /* Pick up the value from the input line.  */
15533965Sjdp      pseudo_set (symbol);
15633965Sjdp    }
15733965Sjdp  else
15833965Sjdp    {
15933965Sjdp      /* .stabd sets the name to NULL.  Why?  */
16033965Sjdp      S_SET_NAME (symbol, NULL);
16160484Sobrien      symbol_set_frag (symbol, frag_now);
16233965Sjdp      S_SET_VALUE (symbol, (valueT) frag_now_fix ());
16333965Sjdp    }
16433965Sjdp
16533965Sjdp  symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
16633965Sjdp
16733965Sjdp  S_SET_TYPE (symbol, type);
16833965Sjdp  S_SET_OTHER (symbol, other);
16933965Sjdp  S_SET_DESC (symbol, desc);
17033965Sjdp}
17133965Sjdp#endif
17233965Sjdp
17333965Sjdp/* This can handle different kinds of stabs (s,n,d) and different
17477298Sobrien   kinds of stab sections.  */
17533965Sjdp
17677298Sobrienstatic void
177130561Sobriens_stab_generic (int what, char *stab_secname, char *stabstr_secname)
17833965Sjdp{
17933965Sjdp  long longint;
18078828Sobrien  char *string, *saved_string_obstack_end;
18133965Sjdp  int type;
18233965Sjdp  int other;
18333965Sjdp  int desc;
18433965Sjdp
18533965Sjdp  /* The general format is:
18633965Sjdp     .stabs "STRING",TYPE,OTHER,DESC,VALUE
18733965Sjdp     .stabn TYPE,OTHER,DESC,VALUE
18833965Sjdp     .stabd TYPE,OTHER,DESC
18933965Sjdp     At this point input_line_pointer points after the pseudo-op and
19033965Sjdp     any trailing whitespace.  The argument what is one of 's', 'n' or
19133965Sjdp     'd' indicating which type of .stab this is.  */
19233965Sjdp
19333965Sjdp  if (what != 's')
19478828Sobrien    {
19578828Sobrien      string = "";
19678828Sobrien      saved_string_obstack_end = 0;
19778828Sobrien    }
19833965Sjdp  else
19933965Sjdp    {
20033965Sjdp      int length;
20133965Sjdp
20233965Sjdp      string = demand_copy_C_string (&length);
20378828Sobrien      /* FIXME: We should probably find some other temporary storage
20478828Sobrien	 for string, rather than leaking memory if someone else
20578828Sobrien	 happens to use the notes obstack.  */
20678828Sobrien      saved_string_obstack_end = notes.next_free;
20733965Sjdp      SKIP_WHITESPACE ();
20833965Sjdp      if (*input_line_pointer == ',')
20933965Sjdp	input_line_pointer++;
21033965Sjdp      else
21133965Sjdp	{
21289857Sobrien	  as_warn (_(".stab%c: missing comma"), what);
21333965Sjdp	  ignore_rest_of_line ();
21433965Sjdp	  return;
21533965Sjdp	}
21633965Sjdp    }
21733965Sjdp
21833965Sjdp  if (get_absolute_expression_and_terminator (&longint) != ',')
21933965Sjdp    {
22089857Sobrien      as_warn (_(".stab%c: missing comma"), what);
22133965Sjdp      ignore_rest_of_line ();
22233965Sjdp      return;
22333965Sjdp    }
22433965Sjdp  type = longint;
22533965Sjdp
22633965Sjdp  if (get_absolute_expression_and_terminator (&longint) != ',')
22733965Sjdp    {
22889857Sobrien      as_warn (_(".stab%c: missing comma"), what);
22933965Sjdp      ignore_rest_of_line ();
23033965Sjdp      return;
23133965Sjdp    }
23233965Sjdp  other = longint;
23333965Sjdp
23433965Sjdp  desc = get_absolute_expression ();
23599461Sobrien
23699461Sobrien  if ((desc > 0xffff) || (desc < -0x8000))
23799461Sobrien    /* This could happen for example with a source file with a huge
23899461Sobrien       number of lines.  The only cure is to use a different debug
23999461Sobrien       format, probably DWARF.  */
24099461Sobrien    as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
24199461Sobrien	     what, desc);
242104834Sobrien
24333965Sjdp  if (what == 's' || what == 'n')
24433965Sjdp    {
24533965Sjdp      if (*input_line_pointer != ',')
24633965Sjdp	{
24789857Sobrien	  as_warn (_(".stab%c: missing comma"), what);
24833965Sjdp	  ignore_rest_of_line ();
24933965Sjdp	  return;
25033965Sjdp	}
25133965Sjdp      input_line_pointer++;
25233965Sjdp      SKIP_WHITESPACE ();
25333965Sjdp    }
25433965Sjdp
25533965Sjdp#ifdef TC_PPC
25633965Sjdp#ifdef OBJ_ELF
25733965Sjdp  /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
25833965Sjdp     given 4 arguments, make it a .stabn */
25933965Sjdp  else if (what == 'd')
26033965Sjdp    {
26133965Sjdp      char *save_location = input_line_pointer;
26233965Sjdp
26333965Sjdp      SKIP_WHITESPACE ();
26433965Sjdp      if (*input_line_pointer == ',')
26533965Sjdp	{
26633965Sjdp	  input_line_pointer++;
26733965Sjdp	  what = 'n';
26833965Sjdp	}
26933965Sjdp      else
27033965Sjdp	input_line_pointer = save_location;
27133965Sjdp    }
27233965Sjdp#endif /* OBJ_ELF */
27333965Sjdp#endif /* TC_PPC */
27433965Sjdp
27533965Sjdp#ifndef NO_LISTING
27633965Sjdp  if (listing)
27733965Sjdp    {
27833965Sjdp      switch (type)
27933965Sjdp	{
28033965Sjdp	case N_SLINE:
28133965Sjdp	  listing_source_line ((unsigned int) desc);
28233965Sjdp	  break;
28333965Sjdp	case N_SO:
28433965Sjdp	case N_SOL:
28533965Sjdp	  listing_source_file (string);
28633965Sjdp	  break;
28733965Sjdp	}
28833965Sjdp    }
28933965Sjdp#endif /* ! NO_LISTING */
29033965Sjdp
29133965Sjdp  /* We have now gathered the type, other, and desc information.  For
29233965Sjdp     .stabs or .stabn, input_line_pointer is now pointing at the
29333965Sjdp     value.  */
29433965Sjdp
29533965Sjdp  if (SEPARATE_STAB_SECTIONS)
29633965Sjdp    /* Output the stab information in a separate section.  This is used
29733965Sjdp       at least for COFF and ELF.  */
29833965Sjdp    {
29933965Sjdp      segT saved_seg = now_seg;
30033965Sjdp      subsegT saved_subseg = now_subseg;
30133965Sjdp      fragS *saved_frag = frag_now;
30233965Sjdp      valueT dot;
30333965Sjdp      segT seg;
30433965Sjdp      unsigned int stroff;
30533965Sjdp      char *p;
30633965Sjdp
30733965Sjdp      static segT cached_sec;
30833965Sjdp      static char *cached_secname;
30933965Sjdp
31033965Sjdp      dot = frag_now_fix ();
31133965Sjdp
31260484Sobrien#ifdef md_flush_pending_output
31360484Sobrien      md_flush_pending_output ();
31460484Sobrien#endif
31560484Sobrien
31633965Sjdp      if (cached_secname && !strcmp (cached_secname, stab_secname))
31733965Sjdp	{
31833965Sjdp	  seg = cached_sec;
31933965Sjdp	  subseg_set (seg, 0);
32033965Sjdp	}
32133965Sjdp      else
32233965Sjdp	{
32333965Sjdp	  seg = subseg_new (stab_secname, 0);
32433965Sjdp	  if (cached_secname)
32533965Sjdp	    free (cached_secname);
32633965Sjdp	  cached_secname = xstrdup (stab_secname);
32733965Sjdp	  cached_sec = seg;
32833965Sjdp	}
32933965Sjdp
33033965Sjdp      if (! seg_info (seg)->hadone)
33133965Sjdp	{
33233965Sjdp	  bfd_set_section_flags (stdoutput, seg,
33333965Sjdp				 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
33433965Sjdp#ifdef INIT_STAB_SECTION
33533965Sjdp	  INIT_STAB_SECTION (seg);
33633965Sjdp#endif
33733965Sjdp	  seg_info (seg)->hadone = 1;
33833965Sjdp	}
33933965Sjdp
34033965Sjdp      stroff = get_stab_string_offset (string, stabstr_secname);
34133965Sjdp      if (what == 's')
34233965Sjdp	{
34378828Sobrien	  /* Release the string, if nobody else has used the obstack.  */
344104834Sobrien	  if (saved_string_obstack_end == notes.next_free)
34578828Sobrien	    obstack_free (&notes, string);
34633965Sjdp	}
34733965Sjdp
34833965Sjdp      /* At least for now, stabs in a special stab section are always
34933965Sjdp	 output as 12 byte blocks of information.  */
35033965Sjdp      p = frag_more (8);
35133965Sjdp      md_number_to_chars (p, (valueT) stroff, 4);
35233965Sjdp      md_number_to_chars (p + 4, (valueT) type, 1);
35333965Sjdp      md_number_to_chars (p + 5, (valueT) other, 1);
35433965Sjdp      md_number_to_chars (p + 6, (valueT) desc, 2);
35533965Sjdp
35633965Sjdp      if (what == 's' || what == 'n')
35733965Sjdp	{
35833965Sjdp	  /* Pick up the value from the input line.  */
35933965Sjdp	  cons (4);
36033965Sjdp	  input_line_pointer--;
36133965Sjdp	}
36233965Sjdp      else
36333965Sjdp	{
36433965Sjdp	  symbolS *symbol;
36533965Sjdp	  expressionS exp;
36633965Sjdp
36733965Sjdp	  /* Arrange for a value representing the current location.  */
368130561Sobrien	  symbol = symbol_temp_new (saved_seg, dot, saved_frag);
36933965Sjdp
37033965Sjdp	  exp.X_op = O_symbol;
37133965Sjdp	  exp.X_add_symbol = symbol;
37233965Sjdp	  exp.X_add_number = 0;
37333965Sjdp
37433965Sjdp	  emit_expr (&exp, 4);
37533965Sjdp	}
37633965Sjdp
37733965Sjdp#ifdef OBJ_PROCESS_STAB
37833965Sjdp      OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
37933965Sjdp#endif
38033965Sjdp
38133965Sjdp      subseg_set (saved_seg, saved_subseg);
38233965Sjdp    }
38333965Sjdp  else
38433965Sjdp    {
38533965Sjdp#ifdef OBJ_PROCESS_STAB
38633965Sjdp      OBJ_PROCESS_STAB (0, what, string, type, other, desc);
38733965Sjdp#else
38833965Sjdp      abort ();
38933965Sjdp#endif
39033965Sjdp    }
39133965Sjdp
39233965Sjdp  demand_empty_rest_of_line ();
39333965Sjdp}
39433965Sjdp
39577298Sobrien/* Regular stab directive.  */
39633965Sjdp
39733965Sjdpvoid
398130561Sobriens_stab (int what)
39933965Sjdp{
40033965Sjdp  s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
40133965Sjdp}
40233965Sjdp
40377298Sobrien/* "Extended stabs", used in Solaris only now.  */
40433965Sjdp
40533965Sjdpvoid
406130561Sobriens_xstab (int what)
40733965Sjdp{
40833965Sjdp  int length;
40933965Sjdp  char *stab_secname, *stabstr_secname;
41033965Sjdp  static char *saved_secname, *saved_strsecname;
41133965Sjdp
41233965Sjdp  /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
41333965Sjdp     cases it will be the same string, so we could release the storage
41433965Sjdp     back to the obstack it came from.  */
41533965Sjdp  stab_secname = demand_copy_C_string (&length);
41633965Sjdp  SKIP_WHITESPACE ();
41733965Sjdp  if (*input_line_pointer == ',')
41833965Sjdp    input_line_pointer++;
41933965Sjdp  else
42033965Sjdp    {
42160484Sobrien      as_bad (_("comma missing in .xstabs"));
42233965Sjdp      ignore_rest_of_line ();
42333965Sjdp      return;
42433965Sjdp    }
42533965Sjdp
42633965Sjdp  /* To get the name of the stab string section, simply add "str" to
42733965Sjdp     the stab section name.  */
42833965Sjdp  if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
42933965Sjdp    {
43033965Sjdp      stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
43133965Sjdp      strcpy (stabstr_secname, stab_secname);
43233965Sjdp      strcat (stabstr_secname, "str");
43333965Sjdp      if (saved_secname)
43433965Sjdp	{
43533965Sjdp	  free (saved_secname);
43633965Sjdp	  free (saved_strsecname);
43733965Sjdp	}
43833965Sjdp      saved_secname = stab_secname;
43933965Sjdp      saved_strsecname = stabstr_secname;
44033965Sjdp    }
44133965Sjdp  s_stab_generic (what, saved_secname, saved_strsecname);
44233965Sjdp}
44333965Sjdp
44433965Sjdp#ifdef S_SET_DESC
44533965Sjdp
44633965Sjdp/* Frob invented at RMS' request. Set the n_desc of a symbol.  */
44733965Sjdp
44877298Sobrienvoid
44933965Sjdps_desc (ignore)
45077298Sobrien     int ignore ATTRIBUTE_UNUSED;
45133965Sjdp{
45233965Sjdp  char *name;
45333965Sjdp  char c;
45433965Sjdp  char *p;
45533965Sjdp  symbolS *symbolP;
45633965Sjdp  int temp;
45733965Sjdp
45833965Sjdp  name = input_line_pointer;
45933965Sjdp  c = get_symbol_end ();
46033965Sjdp  p = input_line_pointer;
46133965Sjdp  *p = c;
46233965Sjdp  SKIP_WHITESPACE ();
46333965Sjdp  if (*input_line_pointer != ',')
46433965Sjdp    {
46533965Sjdp      *p = 0;
46689857Sobrien      as_bad (_("expected comma after \"%s\""), name);
46733965Sjdp      *p = c;
46833965Sjdp      ignore_rest_of_line ();
46933965Sjdp    }
47033965Sjdp  else
47133965Sjdp    {
47233965Sjdp      input_line_pointer++;
47333965Sjdp      temp = get_absolute_expression ();
47433965Sjdp      *p = 0;
47533965Sjdp      symbolP = symbol_find_or_make (name);
47633965Sjdp      *p = c;
47733965Sjdp      S_SET_DESC (symbolP, temp);
47833965Sjdp    }
47933965Sjdp  demand_empty_rest_of_line ();
48033965Sjdp}				/* s_desc() */
48133965Sjdp
48233965Sjdp#endif /* defined (S_SET_DESC) */
48338889Sjdp
48460484Sobrien/* Generate stabs debugging information to denote the main source file.  */
48538889Sjdp
48638889Sjdpvoid
487130561Sobrienstabs_generate_asm_file (void)
48838889Sjdp{
48960484Sobrien  char *file;
49060484Sobrien  unsigned int lineno;
49160484Sobrien
49260484Sobrien  as_where (&file, &lineno);
493130561Sobrien  if (use_gnu_debug_info_extensions)
494130561Sobrien    {
495130561Sobrien      char *dir, *dir2;
496130561Sobrien
497130561Sobrien      dir = getpwd ();
498130561Sobrien      dir2 = alloca (strlen (dir) + 2);
499130561Sobrien      sprintf (dir2, "%s%s", dir, "/");
500130561Sobrien      generate_asm_file (N_SO, dir2);
501130561Sobrien    }
50260484Sobrien  generate_asm_file (N_SO, file);
50360484Sobrien}
50460484Sobrien
50560484Sobrien/* Generate stabs debugging information to denote the source file.
50660484Sobrien   TYPE is one of N_SO, N_SOL.  */
50760484Sobrien
50860484Sobrienstatic void
509130561Sobriengenerate_asm_file (int type, char *file)
51060484Sobrien{
51138889Sjdp  static char *last_file;
51260484Sobrien  static int label_count;
51338889Sjdp  char *hold;
51438889Sjdp  char sym[30];
51577298Sobrien  char *buf;
51677298Sobrien  char *tmp = file;
51777298Sobrien  char *endp = file + strlen (file);
518130561Sobrien  char *bufp;
51938889Sjdp
52077298Sobrien  if (last_file != NULL
52177298Sobrien      && strcmp (last_file, file) == 0)
52277298Sobrien    return;
52377298Sobrien
52438889Sjdp  /* Rather than try to do this in some efficient fashion, we just
52538889Sjdp     generate a string and then parse it again.  That lets us use the
52638889Sjdp     existing stabs hook, which expect to see a string, rather than
52738889Sjdp     inventing new ones.  */
52838889Sjdp  hold = input_line_pointer;
52938889Sjdp
53077298Sobrien  sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
53177298Sobrien  ++label_count;
53277298Sobrien
53377298Sobrien  /* Allocate enough space for the file name (possibly extended with
53477298Sobrien     doubled up backslashes), the symbol name, and the other characters
53577298Sobrien     that make up a stabs file directive.  */
53677298Sobrien  bufp = buf = xmalloc (2 * strlen (file) + strlen (sym) + 12);
53777298Sobrien
53877298Sobrien  *bufp++ = '"';
53977298Sobrien
54077298Sobrien  while (tmp < endp)
54138889Sjdp    {
54277298Sobrien      char *bslash = strchr (tmp, '\\');
54389857Sobrien      size_t len = (bslash) ? (size_t) (bslash - tmp + 1) : strlen (tmp);
54438889Sjdp
54577298Sobrien      /* Double all backslashes, since demand_copy_C_string (used by
54677298Sobrien	 s_stab to extract the part in quotes) will try to replace them as
54777298Sobrien	 escape sequences.  backslash may appear in a filespec.  */
54877298Sobrien      strncpy (bufp, tmp, len);
54960484Sobrien
55077298Sobrien      tmp += len;
55177298Sobrien      bufp += len;
55238889Sjdp
55377298Sobrien      if (bslash != NULL)
55477298Sobrien	*bufp++ = '\\';
55538889Sjdp    }
55638889Sjdp
55777298Sobrien  sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
55877298Sobrien
55977298Sobrien  input_line_pointer = buf;
56077298Sobrien  s_stab ('s');
56177298Sobrien  colon (sym);
56277298Sobrien
56377298Sobrien  if (last_file != NULL)
56477298Sobrien    free (last_file);
56577298Sobrien  last_file = xstrdup (file);
56677298Sobrien
56777298Sobrien  free (buf);
56877298Sobrien
56960484Sobrien  input_line_pointer = hold;
57060484Sobrien}
57138889Sjdp
57260484Sobrien/* Generate stabs debugging information for the current line.  This is
57360484Sobrien   used to produce debugging information for an assembler file.  */
57460484Sobrien
57560484Sobrienvoid
576130561Sobrienstabs_generate_asm_lineno (void)
57760484Sobrien{
57860484Sobrien  static int label_count;
57960484Sobrien  char *hold;
58060484Sobrien  char *file;
58160484Sobrien  unsigned int lineno;
58260484Sobrien  char *buf;
58360484Sobrien  char sym[30];
584104834Sobrien  /* Remember the last file/line and avoid duplicates.  */
58589857Sobrien  static unsigned int prev_lineno = -1;
58689857Sobrien  static char *prev_file = NULL;
58760484Sobrien
58860484Sobrien  /* Rather than try to do this in some efficient fashion, we just
58960484Sobrien     generate a string and then parse it again.  That lets us use the
59060484Sobrien     existing stabs hook, which expect to see a string, rather than
59160484Sobrien     inventing new ones.  */
59260484Sobrien
59360484Sobrien  hold = input_line_pointer;
59460484Sobrien
59560484Sobrien  as_where (&file, &lineno);
59660484Sobrien
597104834Sobrien  /* Don't emit sequences of stabs for the same line.  */
59889857Sobrien  if (prev_file == NULL)
59989857Sobrien    {
600104834Sobrien      /* First time thru.  */
60189857Sobrien      prev_file = xstrdup (file);
60289857Sobrien      prev_lineno = lineno;
60389857Sobrien    }
60489857Sobrien  else if (lineno == prev_lineno
60589857Sobrien	   && strcmp (file, prev_file) == 0)
60689857Sobrien    {
607104834Sobrien      /* Same file/line as last time.  */
60889857Sobrien      return;
60989857Sobrien    }
61089857Sobrien  else
61189857Sobrien    {
612104834Sobrien      /* Remember file/line for next time.  */
61389857Sobrien      prev_lineno = lineno;
61489857Sobrien      if (strcmp (file, prev_file) != 0)
61589857Sobrien	{
61689857Sobrien	  free (prev_file);
61789857Sobrien	  prev_file = xstrdup (file);
61889857Sobrien	}
61989857Sobrien    }
62089857Sobrien
62189857Sobrien  /* Let the world know that we are in the middle of generating a
62289857Sobrien     piece of stabs line debugging information.  */
62389857Sobrien  outputting_stabs_line_debug = 1;
62489857Sobrien
62560484Sobrien  generate_asm_file (N_SOL, file);
62660484Sobrien
62760484Sobrien  sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
62860484Sobrien  ++label_count;
62960484Sobrien
63060484Sobrien  if (in_dot_func_p)
63160484Sobrien    {
63260484Sobrien      buf = (char *) alloca (100 + strlen (current_function_label));
63360484Sobrien      sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
63460484Sobrien	       sym, current_function_label);
63560484Sobrien    }
63660484Sobrien  else
63760484Sobrien    {
63860484Sobrien      buf = (char *) alloca (100);
63960484Sobrien      sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
64060484Sobrien    }
64138889Sjdp  input_line_pointer = buf;
64238889Sjdp  s_stab ('n');
64338889Sjdp  colon (sym);
64438889Sjdp
64538889Sjdp  input_line_pointer = hold;
64677298Sobrien  outputting_stabs_line_debug = 0;
64738889Sjdp}
64860484Sobrien
64960484Sobrien/* Emit a function stab.
65060484Sobrien   All assembler functions are assumed to have return type `void'.  */
65160484Sobrien
65260484Sobrienvoid
653130561Sobrienstabs_generate_asm_func (const char *funcname, const char *startlabname)
65460484Sobrien{
65560484Sobrien  static int void_emitted_p;
65660484Sobrien  char *hold = input_line_pointer;
65760484Sobrien  char *buf;
65860484Sobrien  char *file;
65960484Sobrien  unsigned int lineno;
66060484Sobrien
66160484Sobrien  if (! void_emitted_p)
66260484Sobrien    {
66360484Sobrien      input_line_pointer = "\"void:t1=1\",128,0,0,0";
66460484Sobrien      s_stab ('s');
66560484Sobrien      void_emitted_p = 1;
66660484Sobrien    }
66760484Sobrien
66860484Sobrien  as_where (&file, &lineno);
66960484Sobrien  asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
67060484Sobrien	    funcname, N_FUN, lineno + 1, startlabname);
67160484Sobrien  input_line_pointer = buf;
67260484Sobrien  s_stab ('s');
67360484Sobrien  free (buf);
67460484Sobrien
67560484Sobrien  input_line_pointer = hold;
67660484Sobrien  current_function_label = xstrdup (startlabname);
67760484Sobrien  in_dot_func_p = 1;
67860484Sobrien}
67960484Sobrien
68060484Sobrien/* Emit a stab to record the end of a function.  */
68160484Sobrien
68260484Sobrienvoid
683130561Sobrienstabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
684130561Sobrien			    const char *startlabname)
68560484Sobrien{
68660484Sobrien  static int label_count;
68760484Sobrien  char *hold = input_line_pointer;
68860484Sobrien  char *buf;
68960484Sobrien  char sym[30];
69060484Sobrien
69160484Sobrien  sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
69260484Sobrien  ++label_count;
69360484Sobrien  colon (sym);
69460484Sobrien
69560484Sobrien  asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
69660484Sobrien  input_line_pointer = buf;
69760484Sobrien  s_stab ('s');
69860484Sobrien  free (buf);
69960484Sobrien
70060484Sobrien  input_line_pointer = hold;
70160484Sobrien  in_dot_func_p = 0;
70260484Sobrien  current_function_label = NULL;
70360484Sobrien}
704