1 | /* Generic stabs parsing for gas.
|
---|
2 | Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
|
---|
3 | Free Software Foundation, Inc.
|
---|
4 |
|
---|
5 | This file is part of GAS, the GNU Assembler.
|
---|
6 |
|
---|
7 | GAS is free software; you can redistribute it and/or modify
|
---|
8 | it under the terms of the GNU General Public License as
|
---|
9 | published by the Free Software Foundation; either version 2,
|
---|
10 | or (at your option) any later version.
|
---|
11 |
|
---|
12 | GAS is distributed in the hope that it will be useful, but
|
---|
13 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
---|
15 | the GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with GAS; see the file COPYING. If not, write to the Free
|
---|
19 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
---|
20 | 02111-1307, USA. */
|
---|
21 |
|
---|
22 | #include "as.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 PARAMS ((int, char *, char *));
|
---|
38 | static void generate_asm_file PARAMS ((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 .<secname>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 (string, stabstr_secname)
|
---|
84 | const char *string;
|
---|
85 | const char *stabstr_secname;
|
---|
86 | {
|
---|
87 | unsigned int length;
|
---|
88 | unsigned int retval;
|
---|
89 | segT save_seg;
|
---|
90 | subsegT save_subseg;
|
---|
91 | segT seg;
|
---|
92 | char *p;
|
---|
93 |
|
---|
94 | if (! SEPARATE_STAB_SECTIONS)
|
---|
95 | abort ();
|
---|
96 |
|
---|
97 | length = strlen (string);
|
---|
98 |
|
---|
99 | save_seg = now_seg;
|
---|
100 | save_subseg = now_subseg;
|
---|
101 |
|
---|
102 | /* Create the stab string section. */
|
---|
103 | seg = subseg_new (stabstr_secname, 0);
|
---|
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 | #ifdef BFD_ASSEMBLER
|
---|
113 | bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
|
---|
114 | if (seg->name == stabstr_secname)
|
---|
115 | seg->name = xstrdup (stabstr_secname);
|
---|
116 | #endif
|
---|
117 | }
|
---|
118 |
|
---|
119 | if (length > 0)
|
---|
120 | { /* Ordinary case. */
|
---|
121 | p = frag_more (length + 1);
|
---|
122 | strcpy (p, string);
|
---|
123 |
|
---|
124 | seg_info (seg)->stabu.stab_string_size += length + 1;
|
---|
125 | }
|
---|
126 | else
|
---|
127 | retval = 0;
|
---|
128 |
|
---|
129 | subseg_set (save_seg, save_subseg);
|
---|
130 |
|
---|
131 | return retval;
|
---|
132 | }
|
---|
133 |
|
---|
134 | #ifdef AOUT_STABS
|
---|
135 | #ifndef OBJ_PROCESS_STAB
|
---|
136 | #define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) aout_process_stab(W,S,T,O,D)
|
---|
137 | #endif
|
---|
138 |
|
---|
139 | /* Here instead of obj-aout.c because other formats use it too. */
|
---|
140 | void
|
---|
141 | aout_process_stab (what, string, type, other, desc)
|
---|
142 | int what;
|
---|
143 | const char *string;
|
---|
144 | int type, other, desc;
|
---|
145 | {
|
---|
146 | /* Put the stab information in the symbol table. */
|
---|
147 | symbolS *symbol;
|
---|
148 |
|
---|
149 | /* Create the symbol now, but only insert it into the symbol chain
|
---|
150 | after any symbols mentioned in the value expression get into the
|
---|
151 | symbol chain. This is to avoid "continuation symbols" (where one
|
---|
152 | ends in "\" and the debug info is continued in the next .stabs
|
---|
153 | directive) from being separated by other random symbols. */
|
---|
154 | symbol = symbol_create (string, undefined_section, 0,
|
---|
155 | (struct frag *) NULL);
|
---|
156 | if (what == 's' || what == 'n')
|
---|
157 | {
|
---|
158 | /* Pick up the value from the input line. */
|
---|
159 | symbol_set_frag (symbol, &zero_address_frag);
|
---|
160 | pseudo_set (symbol);
|
---|
161 | }
|
---|
162 | else
|
---|
163 | {
|
---|
164 | /* .stabd sets the name to NULL. Why? */
|
---|
165 | S_SET_NAME (symbol, NULL);
|
---|
166 | symbol_set_frag (symbol, frag_now);
|
---|
167 | S_SET_VALUE (symbol, (valueT) frag_now_fix ());
|
---|
168 | }
|
---|
169 |
|
---|
170 | symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
|
---|
171 |
|
---|
172 | S_SET_TYPE (symbol, type);
|
---|
173 | S_SET_OTHER (symbol, other);
|
---|
174 | S_SET_DESC (symbol, desc);
|
---|
175 | }
|
---|
176 | #endif
|
---|
177 |
|
---|
178 | /* This can handle different kinds of stabs (s,n,d) and different
|
---|
179 | kinds of stab sections. */
|
---|
180 |
|
---|
181 | static void
|
---|
182 | s_stab_generic (what, stab_secname, stabstr_secname)
|
---|
183 | int what;
|
---|
184 | char *stab_secname;
|
---|
185 | char *stabstr_secname;
|
---|
186 | {
|
---|
187 | long longint;
|
---|
188 | char *string, *saved_string_obstack_end;
|
---|
189 | int type;
|
---|
190 | int other;
|
---|
191 | int desc;
|
---|
192 |
|
---|
193 | /* The general format is:
|
---|
194 | .stabs "STRING",TYPE,OTHER,DESC,VALUE
|
---|
195 | .stabn TYPE,OTHER,DESC,VALUE
|
---|
196 | .stabd TYPE,OTHER,DESC
|
---|
197 | At this point input_line_pointer points after the pseudo-op and
|
---|
198 | any trailing whitespace. The argument what is one of 's', 'n' or
|
---|
199 | 'd' indicating which type of .stab this is. */
|
---|
200 |
|
---|
201 | if (what != 's')
|
---|
202 | {
|
---|
203 | string = "";
|
---|
204 | saved_string_obstack_end = 0;
|
---|
205 | }
|
---|
206 | else
|
---|
207 | {
|
---|
208 | int length;
|
---|
209 |
|
---|
210 | string = demand_copy_C_string (&length);
|
---|
211 | /* FIXME: We should probably find some other temporary storage
|
---|
212 | for string, rather than leaking memory if someone else
|
---|
213 | happens to use the notes obstack. */
|
---|
214 | saved_string_obstack_end = notes.next_free;
|
---|
215 | SKIP_WHITESPACE ();
|
---|
216 | if (*input_line_pointer == ',')
|
---|
217 | input_line_pointer++;
|
---|
218 | else
|
---|
219 | {
|
---|
220 | as_warn (_(".stabs: Missing comma"));
|
---|
221 | ignore_rest_of_line ();
|
---|
222 | return;
|
---|
223 | }
|
---|
224 | }
|
---|
225 |
|
---|
226 | if (get_absolute_expression_and_terminator (&longint) != ',')
|
---|
227 | {
|
---|
228 | as_warn (_(".stab%c: Missing comma"), what);
|
---|
229 | ignore_rest_of_line ();
|
---|
230 | return;
|
---|
231 | }
|
---|
232 | type = longint;
|
---|
233 |
|
---|
234 | if (get_absolute_expression_and_terminator (&longint) != ',')
|
---|
235 | {
|
---|
236 | as_warn (_(".stab%c: Missing comma"), what);
|
---|
237 | ignore_rest_of_line ();
|
---|
238 | return;
|
---|
239 | }
|
---|
240 | other = longint;
|
---|
241 |
|
---|
242 | desc = get_absolute_expression ();
|
---|
243 | if (what == 's' || what == 'n')
|
---|
244 | {
|
---|
245 | if (*input_line_pointer != ',')
|
---|
246 | {
|
---|
247 | as_warn (_(".stab%c: Missing comma"), what);
|
---|
248 | ignore_rest_of_line ();
|
---|
249 | return;
|
---|
250 | }
|
---|
251 | input_line_pointer++;
|
---|
252 | SKIP_WHITESPACE ();
|
---|
253 | }
|
---|
254 |
|
---|
255 | #ifdef TC_PPC
|
---|
256 | #ifdef OBJ_ELF
|
---|
257 | /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
|
---|
258 | given 4 arguments, make it a .stabn */
|
---|
259 | else if (what == 'd')
|
---|
260 | {
|
---|
261 | char *save_location = input_line_pointer;
|
---|
262 |
|
---|
263 | SKIP_WHITESPACE ();
|
---|
264 | if (*input_line_pointer == ',')
|
---|
265 | {
|
---|
266 | input_line_pointer++;
|
---|
267 | what = 'n';
|
---|
268 | }
|
---|
269 | else
|
---|
270 | input_line_pointer = save_location;
|
---|
271 | }
|
---|
272 | #endif /* OBJ_ELF */
|
---|
273 | #endif /* TC_PPC */
|
---|
274 |
|
---|
275 | #ifndef NO_LISTING
|
---|
276 | if (listing)
|
---|
277 | {
|
---|
278 | switch (type)
|
---|
279 | {
|
---|
280 | case N_SLINE:
|
---|
281 | listing_source_line ((unsigned int) desc);
|
---|
282 | break;
|
---|
283 | case N_SO:
|
---|
284 | case N_SOL:
|
---|
285 | listing_source_file (string);
|
---|
286 | break;
|
---|
287 | }
|
---|
288 | }
|
---|
289 | #endif /* ! NO_LISTING */
|
---|
290 |
|
---|
291 | /* We have now gathered the type, other, and desc information. For
|
---|
292 | .stabs or .stabn, input_line_pointer is now pointing at the
|
---|
293 | value. */
|
---|
294 |
|
---|
295 | if (SEPARATE_STAB_SECTIONS)
|
---|
296 | /* Output the stab information in a separate section. This is used
|
---|
297 | at least for COFF and ELF. */
|
---|
298 | {
|
---|
299 | segT saved_seg = now_seg;
|
---|
300 | subsegT saved_subseg = now_subseg;
|
---|
301 | fragS *saved_frag = frag_now;
|
---|
302 | valueT dot;
|
---|
303 | segT seg;
|
---|
304 | unsigned int stroff;
|
---|
305 | char *p;
|
---|
306 |
|
---|
307 | static segT cached_sec;
|
---|
308 | static char *cached_secname;
|
---|
309 |
|
---|
310 | dot = frag_now_fix ();
|
---|
311 |
|
---|
312 | #ifdef md_flush_pending_output
|
---|
313 | md_flush_pending_output ();
|
---|
314 | #endif
|
---|
315 |
|
---|
316 | if (cached_secname && !strcmp (cached_secname, stab_secname))
|
---|
317 | {
|
---|
318 | seg = cached_sec;
|
---|
319 | subseg_set (seg, 0);
|
---|
320 | }
|
---|
321 | else
|
---|
322 | {
|
---|
323 | seg = subseg_new (stab_secname, 0);
|
---|
324 | if (cached_secname)
|
---|
325 | free (cached_secname);
|
---|
326 | cached_secname = xstrdup (stab_secname);
|
---|
327 | cached_sec = seg;
|
---|
328 | }
|
---|
329 |
|
---|
330 | if (! seg_info (seg)->hadone)
|
---|
331 | {
|
---|
332 | #ifdef BFD_ASSEMBLER
|
---|
333 | bfd_set_section_flags (stdoutput, seg,
|
---|
334 | SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
|
---|
335 | #endif
|
---|
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 | const char *fake;
|
---|
367 | symbolS *symbol;
|
---|
368 | expressionS exp;
|
---|
369 |
|
---|
370 | /* Arrange for a value representing the current location. */
|
---|
371 | fake = FAKE_LABEL_NAME;
|
---|
372 | symbol = symbol_new (fake, saved_seg, dot, saved_frag);
|
---|
373 |
|
---|
374 | exp.X_op = O_symbol;
|
---|
375 | exp.X_add_symbol = symbol;
|
---|
376 | exp.X_add_number = 0;
|
---|
377 |
|
---|
378 | emit_expr (&exp, 4);
|
---|
379 | }
|
---|
380 |
|
---|
381 | #ifdef OBJ_PROCESS_STAB
|
---|
382 | OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
|
---|
383 | #endif
|
---|
384 |
|
---|
385 | subseg_set (saved_seg, saved_subseg);
|
---|
386 | }
|
---|
387 | else
|
---|
388 | {
|
---|
389 | #ifdef OBJ_PROCESS_STAB
|
---|
390 | OBJ_PROCESS_STAB (0, what, string, type, other, desc);
|
---|
391 | #else
|
---|
392 | abort ();
|
---|
393 | #endif
|
---|
394 | }
|
---|
395 |
|
---|
396 | demand_empty_rest_of_line ();
|
---|
397 | }
|
---|
398 |
|
---|
399 | /* Regular stab directive. */
|
---|
400 |
|
---|
401 | void
|
---|
402 | s_stab (what)
|
---|
403 | int what;
|
---|
404 | {
|
---|
405 | s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
|
---|
406 | }
|
---|
407 |
|
---|
408 | /* "Extended stabs", used in Solaris only now. */
|
---|
409 |
|
---|
410 | void
|
---|
411 | s_xstab (what)
|
---|
412 | int what;
|
---|
413 | {
|
---|
414 | int length;
|
---|
415 | char *stab_secname, *stabstr_secname;
|
---|
416 | static char *saved_secname, *saved_strsecname;
|
---|
417 |
|
---|
418 | /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
|
---|
419 | cases it will be the same string, so we could release the storage
|
---|
420 | back to the obstack it came from. */
|
---|
421 | stab_secname = demand_copy_C_string (&length);
|
---|
422 | SKIP_WHITESPACE ();
|
---|
423 | if (*input_line_pointer == ',')
|
---|
424 | input_line_pointer++;
|
---|
425 | else
|
---|
426 | {
|
---|
427 | as_bad (_("comma missing in .xstabs"));
|
---|
428 | ignore_rest_of_line ();
|
---|
429 | return;
|
---|
430 | }
|
---|
431 |
|
---|
432 | /* To get the name of the stab string section, simply add "str" to
|
---|
433 | the stab section name. */
|
---|
434 | if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
|
---|
435 | {
|
---|
436 | stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
|
---|
437 | strcpy (stabstr_secname, stab_secname);
|
---|
438 | strcat (stabstr_secname, "str");
|
---|
439 | if (saved_secname)
|
---|
440 | {
|
---|
441 | free (saved_secname);
|
---|
442 | free (saved_strsecname);
|
---|
443 | }
|
---|
444 | saved_secname = stab_secname;
|
---|
445 | saved_strsecname = stabstr_secname;
|
---|
446 | }
|
---|
447 | s_stab_generic (what, saved_secname, saved_strsecname);
|
---|
448 | }
|
---|
449 |
|
---|
450 | #ifdef S_SET_DESC
|
---|
451 |
|
---|
452 | /* Frob invented at RMS' request. Set the n_desc of a symbol. */
|
---|
453 |
|
---|
454 | void
|
---|
455 | s_desc (ignore)
|
---|
456 | int ignore ATTRIBUTE_UNUSED;
|
---|
457 | {
|
---|
458 | char *name;
|
---|
459 | char c;
|
---|
460 | char *p;
|
---|
461 | symbolS *symbolP;
|
---|
462 | int temp;
|
---|
463 |
|
---|
464 | name = input_line_pointer;
|
---|
465 | c = get_symbol_end ();
|
---|
466 | p = input_line_pointer;
|
---|
467 | *p = c;
|
---|
468 | SKIP_WHITESPACE ();
|
---|
469 | if (*input_line_pointer != ',')
|
---|
470 | {
|
---|
471 | *p = 0;
|
---|
472 | as_bad (_("Expected comma after name \"%s\""), name);
|
---|
473 | *p = c;
|
---|
474 | ignore_rest_of_line ();
|
---|
475 | }
|
---|
476 | else
|
---|
477 | {
|
---|
478 | input_line_pointer++;
|
---|
479 | temp = get_absolute_expression ();
|
---|
480 | *p = 0;
|
---|
481 | symbolP = symbol_find_or_make (name);
|
---|
482 | *p = c;
|
---|
483 | S_SET_DESC (symbolP, temp);
|
---|
484 | }
|
---|
485 | demand_empty_rest_of_line ();
|
---|
486 | } /* s_desc() */
|
---|
487 |
|
---|
488 | #endif /* defined (S_SET_DESC) */
|
---|
489 |
|
---|
490 | /* Generate stabs debugging information to denote the main source file. */
|
---|
491 |
|
---|
492 | void
|
---|
493 | stabs_generate_asm_file ()
|
---|
494 | {
|
---|
495 | char *file;
|
---|
496 | unsigned int lineno;
|
---|
497 |
|
---|
498 | as_where (&file, &lineno);
|
---|
499 | generate_asm_file (N_SO, file);
|
---|
500 | }
|
---|
501 |
|
---|
502 | /* Generate stabs debugging information to denote the source file.
|
---|
503 | TYPE is one of N_SO, N_SOL. */
|
---|
504 |
|
---|
505 | static void
|
---|
506 | generate_asm_file (type, file)
|
---|
507 | int type;
|
---|
508 | char *file;
|
---|
509 | {
|
---|
510 | static char *last_file;
|
---|
511 | static int label_count;
|
---|
512 | char *hold;
|
---|
513 | char sym[30];
|
---|
514 | char *buf;
|
---|
515 | char *tmp = file;
|
---|
516 | char *endp = file + strlen (file);
|
---|
517 | char *bufp = buf;
|
---|
518 |
|
---|
519 | if (last_file != NULL
|
---|
520 | && strcmp (last_file, file) == 0)
|
---|
521 | return;
|
---|
522 |
|
---|
523 | /* Rather than try to do this in some efficient fashion, we just
|
---|
524 | generate a string and then parse it again. That lets us use the
|
---|
525 | existing stabs hook, which expect to see a string, rather than
|
---|
526 | inventing new ones. */
|
---|
527 | hold = input_line_pointer;
|
---|
528 |
|
---|
529 | sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
|
---|
530 | ++label_count;
|
---|
531 |
|
---|
532 | /* Allocate enough space for the file name (possibly extended with
|
---|
533 | doubled up backslashes), the symbol name, and the other characters
|
---|
534 | that make up a stabs file directive. */
|
---|
535 | bufp = buf = xmalloc (2 * strlen (file) + strlen (sym) + 12);
|
---|
536 |
|
---|
537 | *bufp++ = '"';
|
---|
538 |
|
---|
539 | while (tmp < endp)
|
---|
540 | {
|
---|
541 | char *bslash = strchr (tmp, '\\');
|
---|
542 | int len = (bslash ? (bslash - tmp + 1) : strlen (tmp));
|
---|
543 |
|
---|
544 | /* Double all backslashes, since demand_copy_C_string (used by
|
---|
545 | s_stab to extract the part in quotes) will try to replace them as
|
---|
546 | escape sequences. backslash may appear in a filespec. */
|
---|
547 | strncpy (bufp, tmp, len);
|
---|
548 |
|
---|
549 | tmp += len;
|
---|
550 | bufp += len;
|
---|
551 |
|
---|
552 | if (bslash != NULL)
|
---|
553 | *bufp++ = '\\';
|
---|
554 | }
|
---|
555 |
|
---|
556 | sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
|
---|
557 |
|
---|
558 | input_line_pointer = buf;
|
---|
559 | s_stab ('s');
|
---|
560 | colon (sym);
|
---|
561 |
|
---|
562 | if (last_file != NULL)
|
---|
563 | free (last_file);
|
---|
564 | last_file = xstrdup (file);
|
---|
565 |
|
---|
566 | free (buf);
|
---|
567 |
|
---|
568 | input_line_pointer = hold;
|
---|
569 | }
|
---|
570 |
|
---|
571 | /* Generate stabs debugging information for the current line. This is
|
---|
572 | used to produce debugging information for an assembler file. */
|
---|
573 |
|
---|
574 | void
|
---|
575 | stabs_generate_asm_lineno ()
|
---|
576 | {
|
---|
577 | static int label_count;
|
---|
578 | char *hold;
|
---|
579 | char *file;
|
---|
580 | unsigned int lineno;
|
---|
581 | char *buf;
|
---|
582 | char sym[30];
|
---|
583 |
|
---|
584 | /* Let the world know that we are in the middle of generating a
|
---|
585 | piece of stabs line debugging information. */
|
---|
586 | outputting_stabs_line_debug = 1;
|
---|
587 |
|
---|
588 | /* Rather than try to do this in some efficient fashion, we just
|
---|
589 | generate a string and then parse it again. That lets us use the
|
---|
590 | existing stabs hook, which expect to see a string, rather than
|
---|
591 | inventing new ones. */
|
---|
592 |
|
---|
593 | hold = input_line_pointer;
|
---|
594 |
|
---|
595 | as_where (&file, &lineno);
|
---|
596 |
|
---|
597 | generate_asm_file (N_SOL, file);
|
---|
598 |
|
---|
599 | sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
|
---|
600 | ++label_count;
|
---|
601 |
|
---|
602 | if (in_dot_func_p)
|
---|
603 | {
|
---|
604 | buf = (char *) alloca (100 + strlen (current_function_label));
|
---|
605 | sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
|
---|
606 | sym, current_function_label);
|
---|
607 | }
|
---|
608 | else
|
---|
609 | {
|
---|
610 | buf = (char *) alloca (100);
|
---|
611 | sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
|
---|
612 | }
|
---|
613 | input_line_pointer = buf;
|
---|
614 | s_stab ('n');
|
---|
615 | colon (sym);
|
---|
616 |
|
---|
617 | input_line_pointer = hold;
|
---|
618 | outputting_stabs_line_debug = 0;
|
---|
619 | }
|
---|
620 |
|
---|
621 | /* Emit a function stab.
|
---|
622 | All assembler functions are assumed to have return type `void'. */
|
---|
623 |
|
---|
624 | void
|
---|
625 | stabs_generate_asm_func (funcname, startlabname)
|
---|
626 | const char *funcname;
|
---|
627 | const char *startlabname;
|
---|
628 | {
|
---|
629 | static int void_emitted_p;
|
---|
630 | char *hold = input_line_pointer;
|
---|
631 | char *buf;
|
---|
632 | char *file;
|
---|
633 | unsigned int lineno;
|
---|
634 |
|
---|
635 | if (! void_emitted_p)
|
---|
636 | {
|
---|
637 | input_line_pointer = "\"void:t1=1\",128,0,0,0";
|
---|
638 | s_stab ('s');
|
---|
639 | void_emitted_p = 1;
|
---|
640 | }
|
---|
641 |
|
---|
642 | as_where (&file, &lineno);
|
---|
643 | asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
|
---|
644 | funcname, N_FUN, lineno + 1, startlabname);
|
---|
645 | input_line_pointer = buf;
|
---|
646 | s_stab ('s');
|
---|
647 | free (buf);
|
---|
648 |
|
---|
649 | input_line_pointer = hold;
|
---|
650 | current_function_label = xstrdup (startlabname);
|
---|
651 | in_dot_func_p = 1;
|
---|
652 | }
|
---|
653 |
|
---|
654 | /* Emit a stab to record the end of a function. */
|
---|
655 |
|
---|
656 | void
|
---|
657 | stabs_generate_asm_endfunc (funcname, startlabname)
|
---|
658 | const char *funcname ATTRIBUTE_UNUSED;
|
---|
659 | const char *startlabname;
|
---|
660 | {
|
---|
661 | static int label_count;
|
---|
662 | char *hold = input_line_pointer;
|
---|
663 | char *buf;
|
---|
664 | char sym[30];
|
---|
665 |
|
---|
666 | sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
|
---|
667 | ++label_count;
|
---|
668 | colon (sym);
|
---|
669 |
|
---|
670 | asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
|
---|
671 | input_line_pointer = buf;
|
---|
672 | s_stab ('s');
|
---|
673 | free (buf);
|
---|
674 |
|
---|
675 | input_line_pointer = hold;
|
---|
676 | in_dot_func_p = 0;
|
---|
677 | current_function_label = NULL;
|
---|
678 | }
|
---|