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 (¬es, 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