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