Coverage Report

Created: 2023-06-29 07:09

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