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