Back to index

cell-binutils  2.17cvs20070401
stabs.c
Go to the documentation of this file.
00001 /* Generic stabs parsing for gas.
00002    Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
00003    2002, 2003, 2004, 2005 Free Software Foundation, Inc.
00004 
00005 This file is part of GAS, the GNU Assembler.
00006 
00007 GAS is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2,
00010 or (at your option) any later version.
00011 
00012 GAS is distributed in the hope that it will be useful, but
00013 WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00015 the GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GAS; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020 02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "obstack.h"
00024 #include "subsegs.h"
00025 #include "ecoff.h"
00026 
00027 /* We need this, despite the apparent object format dependency, since
00028    it defines stab types, which all object formats can use now.  */
00029 
00030 #include "aout/stab_gnu.h"
00031 
00032 /* Holds whether the assembler is generating stabs line debugging
00033    information or not.  Potentially used by md_cleanup function.  */
00034 
00035 int outputting_stabs_line_debug = 0;
00036 
00037 static void s_stab_generic (int, char *, char *);
00038 static void generate_asm_file (int, char *);
00039 
00040 /* Allow backends to override the names used for the stab sections.  */
00041 #ifndef STAB_SECTION_NAME
00042 #define STAB_SECTION_NAME ".stab"
00043 #endif
00044 
00045 #ifndef STAB_STRING_SECTION_NAME
00046 #define STAB_STRING_SECTION_NAME ".stabstr"
00047 #endif
00048 
00049 /* Non-zero if we're in the middle of a .func function, in which case
00050    stabs_generate_asm_lineno emits function relative line number stabs.
00051    Otherwise it emits line number stabs with absolute addresses.  Note that
00052    both cases only apply to assembler code assembled with -gstabs.  */
00053 static int in_dot_func_p;
00054 
00055 /* Label at start of current function if in_dot_func_p != 0.  */
00056 static const char *current_function_label;
00057 
00058 /*
00059  * Handle .stabX directives, which used to be open-coded.
00060  * So much creeping featurism overloaded the semantics that we decided
00061  * to put all .stabX thinking in one place. Here.
00062  *
00063  * We try to make any .stabX directive legal. Other people's AS will often
00064  * do assembly-time consistency checks: eg assigning meaning to n_type bits
00065  * and "protecting" you from setting them to certain values. (They also zero
00066  * certain bits before emitting symbols. Tut tut.)
00067  *
00068  * If an expression is not absolute we either gripe or use the relocation
00069  * information. Other people's assemblers silently forget information they
00070  * don't need and invent information they need that you didn't supply.
00071  */
00072 
00073 /*
00074  * Build a string dictionary entry for a .stabX symbol.
00075  * The symbol is added to the .<secname>str section.
00076  */
00077 
00078 #ifndef SEPARATE_STAB_SECTIONS
00079 #define SEPARATE_STAB_SECTIONS 0
00080 #endif
00081 
00082 unsigned int
00083 get_stab_string_offset (const char *string, const char *stabstr_secname)
00084 {
00085   unsigned int length;
00086   unsigned int retval;
00087   segT save_seg;
00088   subsegT save_subseg;
00089   segT seg;
00090   char *p;
00091 
00092   if (! SEPARATE_STAB_SECTIONS)
00093     abort ();
00094 
00095   length = strlen (string);
00096 
00097   save_seg = now_seg;
00098   save_subseg = now_subseg;
00099 
00100   /* Create the stab string section.  */
00101   seg = subseg_new (stabstr_secname, 0);
00102 
00103   retval = seg_info (seg)->stabu.stab_string_size;
00104   if (retval <= 0)
00105     {
00106       /* Make sure the first string is empty.  */
00107       p = frag_more (1);
00108       *p = 0;
00109       retval = seg_info (seg)->stabu.stab_string_size = 1;
00110       bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
00111       if (seg->name == stabstr_secname)
00112        seg->name = xstrdup (stabstr_secname);
00113     }
00114 
00115   if (length > 0)
00116     {                       /* Ordinary case.  */
00117       p = frag_more (length + 1);
00118       strcpy (p, string);
00119 
00120       seg_info (seg)->stabu.stab_string_size += length + 1;
00121     }
00122   else
00123     retval = 0;
00124 
00125   subseg_set (save_seg, save_subseg);
00126 
00127   return retval;
00128 }
00129 
00130 #ifdef AOUT_STABS
00131 #ifndef OBJ_PROCESS_STAB
00132 #define OBJ_PROCESS_STAB(SEG,W,S,T,O,D)   aout_process_stab(W,S,T,O,D)
00133 #endif
00134 
00135 /* Here instead of obj-aout.c because other formats use it too.  */
00136 void
00137 aout_process_stab (what, string, type, other, desc)
00138      int what;
00139      const char *string;
00140      int type, other, desc;
00141 {
00142   /* Put the stab information in the symbol table.  */
00143   symbolS *symbol;
00144 
00145   /* Create the symbol now, but only insert it into the symbol chain
00146      after any symbols mentioned in the value expression get into the
00147      symbol chain.  This is to avoid "continuation symbols" (where one
00148      ends in "\" and the debug info is continued in the next .stabs
00149      directive) from being separated by other random symbols.  */
00150   symbol = symbol_create (string, undefined_section, 0,
00151                        &zero_address_frag);
00152   if (what == 's' || what == 'n')
00153     {
00154       /* Pick up the value from the input line.  */
00155       pseudo_set (symbol);
00156     }
00157   else
00158     {
00159       /* .stabd sets the name to NULL.  Why?  */
00160       S_SET_NAME (symbol, NULL);
00161       symbol_set_frag (symbol, frag_now);
00162       S_SET_VALUE (symbol, (valueT) frag_now_fix ());
00163     }
00164 
00165   symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
00166 
00167   S_SET_TYPE (symbol, type);
00168   S_SET_OTHER (symbol, other);
00169   S_SET_DESC (symbol, desc);
00170 }
00171 #endif
00172 
00173 /* This can handle different kinds of stabs (s,n,d) and different
00174    kinds of stab sections.  */
00175 
00176 static void
00177 s_stab_generic (int what, char *stab_secname, char *stabstr_secname)
00178 {
00179   long longint;
00180   char *string, *saved_string_obstack_end;
00181   int type;
00182   int other;
00183   int desc;
00184 
00185   /* The general format is:
00186      .stabs "STRING",TYPE,OTHER,DESC,VALUE
00187      .stabn TYPE,OTHER,DESC,VALUE
00188      .stabd TYPE,OTHER,DESC
00189      At this point input_line_pointer points after the pseudo-op and
00190      any trailing whitespace.  The argument what is one of 's', 'n' or
00191      'd' indicating which type of .stab this is.  */
00192 
00193   if (what != 's')
00194     {
00195       string = "";
00196       saved_string_obstack_end = 0;
00197     }
00198   else
00199     {
00200       int length;
00201 
00202       string = demand_copy_C_string (&length);
00203       /* FIXME: We should probably find some other temporary storage
00204         for string, rather than leaking memory if someone else
00205         happens to use the notes obstack.  */
00206       saved_string_obstack_end = notes.next_free;
00207       SKIP_WHITESPACE ();
00208       if (*input_line_pointer == ',')
00209        input_line_pointer++;
00210       else
00211        {
00212          as_warn (_(".stab%c: missing comma"), what);
00213          ignore_rest_of_line ();
00214          return;
00215        }
00216     }
00217 
00218   if (get_absolute_expression_and_terminator (&longint) != ',')
00219     {
00220       as_warn (_(".stab%c: missing comma"), what);
00221       ignore_rest_of_line ();
00222       return;
00223     }
00224   type = longint;
00225 
00226   if (get_absolute_expression_and_terminator (&longint) != ',')
00227     {
00228       as_warn (_(".stab%c: missing comma"), what);
00229       ignore_rest_of_line ();
00230       return;
00231     }
00232   other = longint;
00233 
00234   desc = get_absolute_expression ();
00235 
00236   if ((desc > 0xffff) || (desc < -0x8000))
00237     /* This could happen for example with a source file with a huge
00238        number of lines.  The only cure is to use a different debug
00239        format, probably DWARF.  */
00240     as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
00241             what, desc);
00242 
00243   if (what == 's' || what == 'n')
00244     {
00245       if (*input_line_pointer != ',')
00246        {
00247          as_warn (_(".stab%c: missing comma"), what);
00248          ignore_rest_of_line ();
00249          return;
00250        }
00251       input_line_pointer++;
00252       SKIP_WHITESPACE ();
00253     }
00254 
00255 #ifdef TC_PPC
00256 #ifdef OBJ_ELF
00257   /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
00258      given 4 arguments, make it a .stabn */
00259   else if (what == 'd')
00260     {
00261       char *save_location = input_line_pointer;
00262 
00263       SKIP_WHITESPACE ();
00264       if (*input_line_pointer == ',')
00265        {
00266          input_line_pointer++;
00267          what = 'n';
00268        }
00269       else
00270        input_line_pointer = save_location;
00271     }
00272 #endif /* OBJ_ELF */
00273 #endif /* TC_PPC */
00274 
00275 #ifndef NO_LISTING
00276   if (listing)
00277     {
00278       switch (type)
00279        {
00280        case N_SLINE:
00281          listing_source_line ((unsigned int) desc);
00282          break;
00283        case N_SO:
00284        case N_SOL:
00285          listing_source_file (string);
00286          break;
00287        }
00288     }
00289 #endif /* ! NO_LISTING */
00290 
00291   /* We have now gathered the type, other, and desc information.  For
00292      .stabs or .stabn, input_line_pointer is now pointing at the
00293      value.  */
00294 
00295   if (SEPARATE_STAB_SECTIONS)
00296     /* Output the stab information in a separate section.  This is used
00297        at least for COFF and ELF.  */
00298     {
00299       segT saved_seg = now_seg;
00300       subsegT saved_subseg = now_subseg;
00301       fragS *saved_frag = frag_now;
00302       valueT dot;
00303       segT seg;
00304       unsigned int stroff;
00305       char *p;
00306 
00307       static segT cached_sec;
00308       static char *cached_secname;
00309 
00310       dot = frag_now_fix ();
00311 
00312 #ifdef md_flush_pending_output
00313       md_flush_pending_output ();
00314 #endif
00315 
00316       if (cached_secname && !strcmp (cached_secname, stab_secname))
00317        {
00318          seg = cached_sec;
00319          subseg_set (seg, 0);
00320        }
00321       else
00322        {
00323          seg = subseg_new (stab_secname, 0);
00324          if (cached_secname)
00325            free (cached_secname);
00326          cached_secname = xstrdup (stab_secname);
00327          cached_sec = seg;
00328        }
00329 
00330       if (! seg_info (seg)->hadone)
00331        {
00332          bfd_set_section_flags (stdoutput, seg,
00333                              SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
00334 #ifdef INIT_STAB_SECTION
00335          INIT_STAB_SECTION (seg);
00336 #endif
00337          seg_info (seg)->hadone = 1;
00338        }
00339 
00340       stroff = get_stab_string_offset (string, stabstr_secname);
00341       if (what == 's')
00342        {
00343          /* Release the string, if nobody else has used the obstack.  */
00344          if (saved_string_obstack_end == notes.next_free)
00345            obstack_free (&notes, string);
00346        }
00347 
00348       /* At least for now, stabs in a special stab section are always
00349         output as 12 byte blocks of information.  */
00350       p = frag_more (8);
00351       md_number_to_chars (p, (valueT) stroff, 4);
00352       md_number_to_chars (p + 4, (valueT) type, 1);
00353       md_number_to_chars (p + 5, (valueT) other, 1);
00354       md_number_to_chars (p + 6, (valueT) desc, 2);
00355 
00356       if (what == 's' || what == 'n')
00357        {
00358          /* Pick up the value from the input line.  */
00359          cons (4);
00360          input_line_pointer--;
00361        }
00362       else
00363        {
00364          symbolS *symbol;
00365          expressionS exp;
00366 
00367          /* Arrange for a value representing the current location.  */
00368          symbol = symbol_temp_new (saved_seg, dot, saved_frag);
00369 
00370          exp.X_op = O_symbol;
00371          exp.X_add_symbol = symbol;
00372          exp.X_add_number = 0;
00373 
00374          emit_expr (&exp, 4);
00375        }
00376 
00377 #ifdef OBJ_PROCESS_STAB
00378       OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
00379 #endif
00380 
00381       subseg_set (saved_seg, saved_subseg);
00382     }
00383   else
00384     {
00385 #ifdef OBJ_PROCESS_STAB
00386       OBJ_PROCESS_STAB (0, what, string, type, other, desc);
00387 #else
00388       abort ();
00389 #endif
00390     }
00391 
00392   demand_empty_rest_of_line ();
00393 }
00394 
00395 /* Regular stab directive.  */
00396 
00397 void
00398 s_stab (int what)
00399 {
00400   s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
00401 }
00402 
00403 /* "Extended stabs", used in Solaris only now.  */
00404 
00405 void
00406 s_xstab (int what)
00407 {
00408   int length;
00409   char *stab_secname, *stabstr_secname;
00410   static char *saved_secname, *saved_strsecname;
00411 
00412   /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
00413      cases it will be the same string, so we could release the storage
00414      back to the obstack it came from.  */
00415   stab_secname = demand_copy_C_string (&length);
00416   SKIP_WHITESPACE ();
00417   if (*input_line_pointer == ',')
00418     input_line_pointer++;
00419   else
00420     {
00421       as_bad (_("comma missing in .xstabs"));
00422       ignore_rest_of_line ();
00423       return;
00424     }
00425 
00426   /* To get the name of the stab string section, simply add "str" to
00427      the stab section name.  */
00428   if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
00429     {
00430       stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
00431       strcpy (stabstr_secname, stab_secname);
00432       strcat (stabstr_secname, "str");
00433       if (saved_secname)
00434        {
00435          free (saved_secname);
00436          free (saved_strsecname);
00437        }
00438       saved_secname = stab_secname;
00439       saved_strsecname = stabstr_secname;
00440     }
00441   s_stab_generic (what, saved_secname, saved_strsecname);
00442 }
00443 
00444 #ifdef S_SET_DESC
00445 
00446 /* Frob invented at RMS' request. Set the n_desc of a symbol.  */
00447 
00448 void
00449 s_desc (ignore)
00450      int ignore ATTRIBUTE_UNUSED;
00451 {
00452   char *name;
00453   char c;
00454   char *p;
00455   symbolS *symbolP;
00456   int temp;
00457 
00458   name = input_line_pointer;
00459   c = get_symbol_end ();
00460   p = input_line_pointer;
00461   *p = c;
00462   SKIP_WHITESPACE ();
00463   if (*input_line_pointer != ',')
00464     {
00465       *p = 0;
00466       as_bad (_("expected comma after \"%s\""), name);
00467       *p = c;
00468       ignore_rest_of_line ();
00469     }
00470   else
00471     {
00472       input_line_pointer++;
00473       temp = get_absolute_expression ();
00474       *p = 0;
00475       symbolP = symbol_find_or_make (name);
00476       *p = c;
00477       S_SET_DESC (symbolP, temp);
00478     }
00479   demand_empty_rest_of_line ();
00480 }                           /* s_desc() */
00481 
00482 #endif /* defined (S_SET_DESC) */
00483 
00484 /* Generate stabs debugging information to denote the main source file.  */
00485 
00486 void
00487 stabs_generate_asm_file (void)
00488 {
00489   char *file;
00490   unsigned int lineno;
00491 
00492   as_where (&file, &lineno);
00493   if (use_gnu_debug_info_extensions)
00494     {
00495       char *dir, *dir2;
00496 
00497       dir = getpwd ();
00498       dir2 = alloca (strlen (dir) + 2);
00499       sprintf (dir2, "%s%s", dir, "/");
00500       generate_asm_file (N_SO, dir2);
00501     }
00502   generate_asm_file (N_SO, file);
00503 }
00504 
00505 /* Generate stabs debugging information to denote the source file.
00506    TYPE is one of N_SO, N_SOL.  */
00507 
00508 static void
00509 generate_asm_file (int type, char *file)
00510 {
00511   static char *last_file;
00512   static int label_count;
00513   char *hold;
00514   char sym[30];
00515   char *buf;
00516   char *tmp = file;
00517   char *endp = file + strlen (file);
00518   char *bufp;
00519 
00520   if (last_file != NULL
00521       && strcmp (last_file, file) == 0)
00522     return;
00523 
00524   /* Rather than try to do this in some efficient fashion, we just
00525      generate a string and then parse it again.  That lets us use the
00526      existing stabs hook, which expect to see a string, rather than
00527      inventing new ones.  */
00528   hold = input_line_pointer;
00529 
00530   sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
00531   ++label_count;
00532 
00533   /* Allocate enough space for the file name (possibly extended with
00534      doubled up backslashes), the symbol name, and the other characters
00535      that make up a stabs file directive.  */
00536   bufp = buf = xmalloc (2 * strlen (file) + strlen (sym) + 12);
00537 
00538   *bufp++ = '"';
00539 
00540   while (tmp < endp)
00541     {
00542       char *bslash = strchr (tmp, '\\');
00543       size_t len = (bslash) ? (size_t) (bslash - tmp + 1) : strlen (tmp);
00544 
00545       /* Double all backslashes, since demand_copy_C_string (used by
00546         s_stab to extract the part in quotes) will try to replace them as
00547         escape sequences.  backslash may appear in a filespec.  */
00548       strncpy (bufp, tmp, len);
00549 
00550       tmp += len;
00551       bufp += len;
00552 
00553       if (bslash != NULL)
00554        *bufp++ = '\\';
00555     }
00556 
00557   sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
00558 
00559   input_line_pointer = buf;
00560   s_stab ('s');
00561   colon (sym);
00562 
00563   if (last_file != NULL)
00564     free (last_file);
00565   last_file = xstrdup (file);
00566 
00567   free (buf);
00568 
00569   input_line_pointer = hold;
00570 }
00571 
00572 /* Generate stabs debugging information for the current line.  This is
00573    used to produce debugging information for an assembler file.  */
00574 
00575 void
00576 stabs_generate_asm_lineno (void)
00577 {
00578   static int label_count;
00579   char *hold;
00580   char *file;
00581   unsigned int lineno;
00582   char *buf;
00583   char sym[30];
00584   /* Remember the last file/line and avoid duplicates.  */
00585   static unsigned int prev_lineno = -1;
00586   static char *prev_file = NULL;
00587 
00588   /* Rather than try to do this in some efficient fashion, we just
00589      generate a string and then parse it again.  That lets us use the
00590      existing stabs hook, which expect to see a string, rather than
00591      inventing new ones.  */
00592 
00593   hold = input_line_pointer;
00594 
00595   as_where (&file, &lineno);
00596 
00597   /* Don't emit sequences of stabs for the same line.  */
00598   if (prev_file == NULL)
00599     {
00600       /* First time thru.  */
00601       prev_file = xstrdup (file);
00602       prev_lineno = lineno;
00603     }
00604   else if (lineno == prev_lineno
00605           && strcmp (file, prev_file) == 0)
00606     {
00607       /* Same file/line as last time.  */
00608       return;
00609     }
00610   else
00611     {
00612       /* Remember file/line for next time.  */
00613       prev_lineno = lineno;
00614       if (strcmp (file, prev_file) != 0)
00615        {
00616          free (prev_file);
00617          prev_file = xstrdup (file);
00618        }
00619     }
00620 
00621   /* Let the world know that we are in the middle of generating a
00622      piece of stabs line debugging information.  */
00623   outputting_stabs_line_debug = 1;
00624 
00625   generate_asm_file (N_SOL, file);
00626 
00627   sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
00628   ++label_count;
00629 
00630   if (in_dot_func_p)
00631     {
00632       buf = (char *) alloca (100 + strlen (current_function_label));
00633       sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
00634               sym, current_function_label);
00635     }
00636   else
00637     {
00638       buf = (char *) alloca (100);
00639       sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
00640     }
00641   input_line_pointer = buf;
00642   s_stab ('n');
00643   colon (sym);
00644 
00645   input_line_pointer = hold;
00646   outputting_stabs_line_debug = 0;
00647 }
00648 
00649 /* Emit a function stab.
00650    All assembler functions are assumed to have return type `void'.  */
00651 
00652 void
00653 stabs_generate_asm_func (const char *funcname, const char *startlabname)
00654 {
00655   static int void_emitted_p;
00656   char *hold = input_line_pointer;
00657   char *buf;
00658   char *file;
00659   unsigned int lineno;
00660 
00661   if (! void_emitted_p)
00662     {
00663       input_line_pointer = "\"void:t1=1\",128,0,0,0";
00664       s_stab ('s');
00665       void_emitted_p = 1;
00666     }
00667 
00668   as_where (&file, &lineno);
00669   asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
00670            funcname, N_FUN, lineno + 1, startlabname);
00671   input_line_pointer = buf;
00672   s_stab ('s');
00673   free (buf);
00674 
00675   input_line_pointer = hold;
00676   current_function_label = xstrdup (startlabname);
00677   in_dot_func_p = 1;
00678 }
00679 
00680 /* Emit a stab to record the end of a function.  */
00681 
00682 void
00683 stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
00684                          const char *startlabname)
00685 {
00686   static int label_count;
00687   char *hold = input_line_pointer;
00688   char *buf;
00689   char sym[30];
00690 
00691   sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
00692   ++label_count;
00693   colon (sym);
00694 
00695   asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
00696   input_line_pointer = buf;
00697   s_stab ('s');
00698   free (buf);
00699 
00700   input_line_pointer = hold;
00701   in_dot_func_p = 0;
00702   current_function_label = NULL;
00703 }