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 (¬es, 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 (¬es, 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 (¬es);
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 (¬es))
329 {
330 obstack_free (¬es, 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 (¬es))
379 obstack_free (¬es, 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