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