Subversion Repositories Kolibri OS

Rev

Rev 5222 | Details | Compare with Previous | Last modification | View Log | RSS feed

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