stabs.c revision 33965
1/* Generic stabs parsing for gas.
2   Copyright (C) 1989, 90, 91, 93, 94, 95, 96, 1997
3   Free Software Foundation, Inc.
4
5This file is part of GAS, the GNU Assembler.
6
7GAS is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 2,
10or (at your option) any later version.
11
12GAS is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15the GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GAS; see the file COPYING.  If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
21
22#include "as.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
32static void s_stab_generic PARAMS ((int, char *, char *));
33
34/* Allow backends to override the names used for the stab sections.  */
35#ifndef STAB_SECTION_NAME
36#define STAB_SECTION_NAME ".stab"
37#endif
38
39#ifndef STAB_STRING_SECTION_NAME
40#define STAB_STRING_SECTION_NAME ".stabstr"
41#endif
42
43/*
44 * Handle .stabX directives, which used to be open-coded.
45 * So much creeping featurism overloaded the semantics that we decided
46 * to put all .stabX thinking in one place. Here.
47 *
48 * We try to make any .stabX directive legal. Other people's AS will often
49 * do assembly-time consistency checks: eg assigning meaning to n_type bits
50 * and "protecting" you from setting them to certain values. (They also zero
51 * certain bits before emitting symbols. Tut tut.)
52 *
53 * If an expression is not absolute we either gripe or use the relocation
54 * information. Other people's assemblers silently forget information they
55 * don't need and invent information they need that you didn't supply.
56 */
57
58/*
59 * Build a string dictionary entry for a .stabX symbol.
60 * The symbol is added to the .<secname>str section.
61 */
62
63#ifndef SEPARATE_STAB_SECTIONS
64#define SEPARATE_STAB_SECTIONS 0
65#endif
66
67unsigned int
68get_stab_string_offset (string, stabstr_secname)
69     const char *string;
70     const char *stabstr_secname;
71{
72  unsigned int length;
73  unsigned int retval;
74
75  if (! SEPARATE_STAB_SECTIONS)
76    abort ();
77
78  retval = 0;
79  length = strlen (string);
80  if (length > 0)
81    {				/* Ordinary case. */
82      segT save_seg;
83      subsegT save_subseg;
84      segT seg;
85      char *p;
86
87      save_seg = now_seg;
88      save_subseg = now_subseg;
89
90      /* Create the stab string section.  */
91      seg = subseg_new (stabstr_secname, 0);
92
93      retval = seg_info (seg)->stabu.stab_string_size;
94      if (retval <= 0)
95	{
96	  /* Make sure the first string is empty.  */
97	  p = frag_more (1);
98	  *p = 0;
99	  retval = seg_info (seg)->stabu.stab_string_size = 1;
100#ifdef BFD_ASSEMBLER
101	  bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
102	  if (seg->name == stabstr_secname)
103	    seg->name = xstrdup (stabstr_secname);
104#endif
105	}
106
107      p = frag_more (length + 1);
108      strcpy (p, string);
109
110      seg_info (seg)->stabu.stab_string_size += length + 1;
111
112      subseg_set (save_seg, save_subseg);
113    }
114
115  return retval;
116}
117
118#ifdef AOUT_STABS
119#ifndef OBJ_PROCESS_STAB
120#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D)	aout_process_stab(W,S,T,O,D)
121#endif
122
123static void aout_process_stab PARAMS ((int, const char *, int, int, int));
124
125static void
126aout_process_stab (what, string, type, other, desc)
127     int what;
128     const char *string;
129     int type, other, desc;
130{
131  /* Put the stab information in the symbol table.  */
132  symbolS *symbol;
133
134  /* Create the symbol now, but only insert it into the symbol chain
135     after any symbols mentioned in the value expression get into the
136     symbol chain.  This is to avoid "continuation symbols" (where one
137     ends in "\" and the debug info is continued in the next .stabs
138     directive) from being separated by other random symbols.  */
139  symbol = symbol_create (string, undefined_section, 0,
140			  (struct frag *) NULL);
141  if (what == 's' || what == 'n')
142    {
143      /* Pick up the value from the input line.  */
144      symbol->sy_frag = &zero_address_frag;
145      pseudo_set (symbol);
146    }
147  else
148    {
149      /* .stabd sets the name to NULL.  Why?  */
150      S_SET_NAME (symbol, NULL);
151      symbol->sy_frag = frag_now;
152      S_SET_VALUE (symbol, (valueT) frag_now_fix ());
153    }
154
155  symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
156
157  S_SET_TYPE (symbol, type);
158  S_SET_OTHER (symbol, other);
159  S_SET_DESC (symbol, desc);
160}
161#endif
162
163/* This can handle different kinds of stabs (s,n,d) and different
164   kinds of stab sections. */
165
166static void
167s_stab_generic (what, stab_secname, stabstr_secname)
168     int what;
169     char *stab_secname;
170     char *stabstr_secname;
171{
172  long longint;
173  char *string;
174  int type;
175  int other;
176  int desc;
177
178  /* The general format is:
179     .stabs "STRING",TYPE,OTHER,DESC,VALUE
180     .stabn TYPE,OTHER,DESC,VALUE
181     .stabd TYPE,OTHER,DESC
182     At this point input_line_pointer points after the pseudo-op and
183     any trailing whitespace.  The argument what is one of 's', 'n' or
184     'd' indicating which type of .stab this is.  */
185
186  if (what != 's')
187    string = "";
188  else
189    {
190      int length;
191
192      string = demand_copy_C_string (&length);
193      SKIP_WHITESPACE ();
194      if (*input_line_pointer == ',')
195	input_line_pointer++;
196      else
197	{
198	  as_warn (".stabs: Missing comma");
199	  ignore_rest_of_line ();
200	  return;
201	}
202    }
203
204  if (get_absolute_expression_and_terminator (&longint) != ',')
205    {
206      as_warn (".stab%c: Missing comma", what);
207      ignore_rest_of_line ();
208      return;
209    }
210  type = longint;
211
212  if (get_absolute_expression_and_terminator (&longint) != ',')
213    {
214      as_warn (".stab%c: Missing comma", what);
215      ignore_rest_of_line ();
216      return;
217    }
218  other = longint;
219
220  desc = get_absolute_expression ();
221  if (what == 's' || what == 'n')
222    {
223      if (*input_line_pointer != ',')
224	{
225	  as_warn (".stab%c: Missing comma", what);
226	  ignore_rest_of_line ();
227	  return;
228	}
229      input_line_pointer++;
230      SKIP_WHITESPACE ();
231    }
232
233#ifdef TC_PPC
234#ifdef OBJ_ELF
235  /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
236     given 4 arguments, make it a .stabn */
237  else if (what == 'd')
238    {
239      char *save_location = input_line_pointer;
240
241      SKIP_WHITESPACE ();
242      if (*input_line_pointer == ',')
243	{
244	  input_line_pointer++;
245	  what = 'n';
246	}
247      else
248	input_line_pointer = save_location;
249    }
250#endif /* OBJ_ELF */
251#endif /* TC_PPC */
252
253#ifndef NO_LISTING
254  if (listing)
255    {
256      switch (type)
257	{
258	case N_SLINE:
259	  listing_source_line ((unsigned int) desc);
260	  break;
261	case N_SO:
262	case N_SOL:
263	  listing_source_file (string);
264	  break;
265	}
266    }
267#endif /* ! NO_LISTING */
268
269  /* We have now gathered the type, other, and desc information.  For
270     .stabs or .stabn, input_line_pointer is now pointing at the
271     value.  */
272
273  if (SEPARATE_STAB_SECTIONS)
274    /* Output the stab information in a separate section.  This is used
275       at least for COFF and ELF.  */
276    {
277      segT saved_seg = now_seg;
278      subsegT saved_subseg = now_subseg;
279      fragS *saved_frag = frag_now;
280      valueT dot;
281      segT seg;
282      unsigned int stroff;
283      char *p;
284
285      static segT cached_sec;
286      static char *cached_secname;
287
288      dot = frag_now_fix ();
289
290      if (cached_secname && !strcmp (cached_secname, stab_secname))
291	{
292	  seg = cached_sec;
293	  subseg_set (seg, 0);
294	}
295      else
296	{
297	  seg = subseg_new (stab_secname, 0);
298	  if (cached_secname)
299	    free (cached_secname);
300	  cached_secname = xstrdup (stab_secname);
301	  cached_sec = seg;
302	}
303
304      if (! seg_info (seg)->hadone)
305	{
306#ifdef BFD_ASSEMBLER
307	  bfd_set_section_flags (stdoutput, seg,
308				 SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
309#endif
310#ifdef INIT_STAB_SECTION
311	  INIT_STAB_SECTION (seg);
312#endif
313	  seg_info (seg)->hadone = 1;
314	}
315
316      stroff = get_stab_string_offset (string, stabstr_secname);
317      if (what == 's')
318	{
319	  /* release the string */
320	  obstack_free (&notes, string);
321	}
322
323      /* At least for now, stabs in a special stab section are always
324	 output as 12 byte blocks of information.  */
325      p = frag_more (8);
326      md_number_to_chars (p, (valueT) stroff, 4);
327      md_number_to_chars (p + 4, (valueT) type, 1);
328      md_number_to_chars (p + 5, (valueT) other, 1);
329      md_number_to_chars (p + 6, (valueT) desc, 2);
330
331      if (what == 's' || what == 'n')
332	{
333	  /* Pick up the value from the input line.  */
334	  cons (4);
335	  input_line_pointer--;
336	}
337      else
338	{
339	  const char *fake;
340	  symbolS *symbol;
341	  expressionS exp;
342
343	  /* Arrange for a value representing the current location.  */
344	  fake = FAKE_LABEL_NAME;
345	  symbol = symbol_new (fake, saved_seg, dot, saved_frag);
346
347	  exp.X_op = O_symbol;
348	  exp.X_add_symbol = symbol;
349	  exp.X_add_number = 0;
350
351	  emit_expr (&exp, 4);
352	}
353
354#ifdef OBJ_PROCESS_STAB
355      OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
356#endif
357
358      subseg_set (saved_seg, saved_subseg);
359    }
360  else
361    {
362#ifdef OBJ_PROCESS_STAB
363      OBJ_PROCESS_STAB (0, what, string, type, other, desc);
364#else
365      abort ();
366#endif
367    }
368
369  demand_empty_rest_of_line ();
370}
371
372/* Regular stab directive. */
373
374void
375s_stab (what)
376     int what;
377{
378  s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
379}
380
381/* "Extended stabs", used in Solaris only now. */
382
383void
384s_xstab (what)
385     int what;
386{
387  int length;
388  char *stab_secname, *stabstr_secname;
389  static char *saved_secname, *saved_strsecname;
390
391  /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
392     cases it will be the same string, so we could release the storage
393     back to the obstack it came from.  */
394  stab_secname = demand_copy_C_string (&length);
395  SKIP_WHITESPACE ();
396  if (*input_line_pointer == ',')
397    input_line_pointer++;
398  else
399    {
400      as_bad ("comma missing in .xstabs");
401      ignore_rest_of_line ();
402      return;
403    }
404
405  /* To get the name of the stab string section, simply add "str" to
406     the stab section name.  */
407  if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
408    {
409      stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
410      strcpy (stabstr_secname, stab_secname);
411      strcat (stabstr_secname, "str");
412      if (saved_secname)
413	{
414	  free (saved_secname);
415	  free (saved_strsecname);
416	}
417      saved_secname = stab_secname;
418      saved_strsecname = stabstr_secname;
419    }
420  s_stab_generic (what, saved_secname, saved_strsecname);
421}
422
423#ifdef S_SET_DESC
424
425/* Frob invented at RMS' request. Set the n_desc of a symbol.  */
426
427void
428s_desc (ignore)
429     int ignore;
430{
431  char *name;
432  char c;
433  char *p;
434  symbolS *symbolP;
435  int temp;
436
437  name = input_line_pointer;
438  c = get_symbol_end ();
439  p = input_line_pointer;
440  *p = c;
441  SKIP_WHITESPACE ();
442  if (*input_line_pointer != ',')
443    {
444      *p = 0;
445      as_bad ("Expected comma after name \"%s\"", name);
446      *p = c;
447      ignore_rest_of_line ();
448    }
449  else
450    {
451      input_line_pointer++;
452      temp = get_absolute_expression ();
453      *p = 0;
454      symbolP = symbol_find_or_make (name);
455      *p = c;
456      S_SET_DESC (symbolP, temp);
457    }
458  demand_empty_rest_of_line ();
459}				/* s_desc() */
460
461#endif /* defined (S_SET_DESC) */
462