Coverage Report

Created: 2023-08-28 06:31

/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
837
#define STAB_SECTION_NAME ".stab"
42
#endif
43
44
#ifndef STAB_STRING_SECTION_NAME
45
837
#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
323
{
101
323
  unsigned int length;
102
323
  unsigned int retval;
103
323
  segT save_seg;
104
323
  subsegT save_subseg;
105
323
  segT seg;
106
323
  char *p;
107
108
323
  if (! SEPARATE_STAB_SECTIONS)
109
0
    abort ();
110
111
323
  length = strlen (string);
112
113
323
  save_seg = now_seg;
114
323
  save_subseg = now_subseg;
115
116
  /* Create the stab string section, if it doesn't already exist.  */
117
323
  seg = subseg_new (stabstr_secname, 0);
118
323
  if (free_stabstr_secname && seg->name != stabstr_secname)
119
0
    free ((char *) stabstr_secname);
120
121
323
  retval = seg_info (seg)->stabu.stab_string_size;
122
323
  if (retval <= 0)
123
61
    {
124
      /* Make sure the first string is empty.  */
125
61
      p = frag_more (1);
126
61
      *p = 0;
127
61
      retval = seg_info (seg)->stabu.stab_string_size = 1;
128
61
      bfd_set_section_flags (seg, SEC_READONLY | SEC_DEBUGGING);
129
61
    }
130
131
323
  if (length > 0)
132
60
    {       /* Ordinary case.  */
133
60
      p = frag_more (length + 1);
134
60
      strcpy (p, string);
135
136
60
      seg_info (seg)->stabu.stab_string_size += length + 1;
137
60
    }
138
263
  else
139
263
    retval = 0;
140
141
323
  subseg_set (save_seg, save_subseg);
142
143
323
  return retval;
144
323
}
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
837
{
198
837
  long longint;
199
837
  const char *string;
200
837
  char *saved_string_obstack_end;
201
837
  int type;
202
837
  int other;
203
837
  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
837
  if (what != 's')
214
808
    {
215
808
      string = "";
216
808
      saved_string_obstack_end = 0;
217
808
    }
218
29
  else
219
29
    {
220
29
      int length;
221
222
29
      string = demand_copy_C_string (&length);
223
29
      if (string == NULL)
224
29
  {
225
29
    as_warn (_(".stab%c: missing string"), what);
226
29
    ignore_rest_of_line ();
227
29
    return;
228
29
  }
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
808
  if (get_absolute_expression_and_terminator (&longint) != ',')
245
5
    {
246
5
      as_warn (_(".stab%c: missing comma"), what);
247
5
      ignore_rest_of_line ();
248
5
      return;
249
5
    }
250
803
  type = longint;
251
252
803
  if (get_absolute_expression_and_terminator (&longint) != ',')
253
86
    {
254
86
      as_warn (_(".stab%c: missing comma"), what);
255
86
      ignore_rest_of_line ();
256
86
      return;
257
86
    }
258
717
  other = longint;
259
260
717
  desc = get_absolute_expression ();
261
262
717
  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
1
    as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
267
1
       what, desc);
268
269
717
  if (what == 's' || what == 'n')
270
717
    {
271
717
      if (*input_line_pointer != ',')
272
455
  {
273
455
    as_warn (_(".stab%c: missing comma"), what);
274
455
    ignore_rest_of_line ();
275
455
    return;
276
455
  }
277
262
      input_line_pointer++;
278
262
      SKIP_WHITESPACE ();
279
262
    }
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
262
#ifndef NO_LISTING
302
262
  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
262
#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
262
  if (SEPARATE_STAB_SECTIONS)
322
    /* Output the stab information in a separate section.  This is used
323
       at least for COFF and ELF.  */
324
262
    {
325
262
      segT saved_seg = now_seg;
326
262
      subsegT saved_subseg = now_subseg;
327
262
      fragS *saved_frag = frag_now;
328
262
      valueT dot;
329
262
      segT seg;
330
262
      unsigned int stroff;
331
262
      char *p;
332
333
262
      dot = frag_now_fix ();
334
335
#ifdef md_flush_pending_output
336
      md_flush_pending_output ();
337
#endif
338
339
262
      if (cached_sec && strcmp (cached_sec->name, stab_secname) == 0)
340
201
  {
341
201
    seg = cached_sec;
342
201
    subseg_set (seg, 0);
343
201
  }
344
61
      else
345
61
  {
346
61
    seg = subseg_new (stab_secname, 0);
347
61
    cached_sec = seg;
348
61
  }
349
350
262
      if (! seg_info (seg)->hadone)
351
61
  {
352
61
    bfd_set_section_flags (seg,
353
61
         SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
354
61
#ifdef INIT_STAB_SECTION
355
61
    INIT_STAB_SECTION (seg);
356
61
#endif
357
61
    seg_info (seg)->hadone = 1;
358
61
  }
359
360
262
      stroff = get_stab_string_offset (string, stabstr_secname,
361
262
               stab_secname_obstack_end != NULL);
362
363
      /* Release the string, if nobody else has used the obstack.  */
364
262
      if (saved_string_obstack_end != NULL
365
262
    && 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
262
      if (seg->name != stab_secname
370
262
    && stab_secname_obstack_end != NULL
371
262
    && 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
262
      p = frag_more (8);
377
262
      md_number_to_chars (p, (valueT) stroff, 4);
378
262
      md_number_to_chars (p + 4, (valueT) type, 1);
379
262
      md_number_to_chars (p + 5, (valueT) other, 1);
380
262
      md_number_to_chars (p + 6, (valueT) desc, 2);
381
382
262
      if (what == 's' || what == 'n')
383
262
  {
384
    /* Pick up the value from the input line.  */
385
262
    cons (4);
386
262
    input_line_pointer--;
387
262
  }
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
262
      subseg_set (saved_seg, saved_subseg);
408
262
    }
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
262
  demand_empty_rest_of_line ();
425
262
}
426
427
/* Regular stab directive.  */
428
429
void
430
s_stab (int what)
431
837
{
432
837
  s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME, NULL);
433
837
}
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
1.15k
{
709
1.15k
  current_function_label = NULL;
710
1.15k
  cached_sec = NULL;
711
1.15k
  last_asm_file = NULL;
712
1.15k
  file_label_count = 0;
713
1.15k
  line_label_count = 0;
714
1.15k
  prev_lineno = -1u;
715
1.15k
  prev_line_file = NULL;
716
1.15k
  void_emitted_p = false;
717
1.15k
  endfunc_label_count = 0;
718
1.15k
}
719
720
void
721
stabs_end (void)
722
1.15k
{
723
1.15k
  free ((char *) current_function_label);
724
1.15k
  free (last_asm_file);
725
1.15k
  free (prev_line_file);
726
1.15k
}