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 (_(".stab%c: missing comma"), what);
|
---|
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 |
|
---|
244 | if ((desc > 0xffff) || (desc < -0x8000))
|
---|
245 | /* This could happen for example with a source file with a huge
|
---|
246 | number of lines. The only cure is to use a different debug
|
---|
247 | format, probably DWARF. */
|
---|
248 | as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
|
---|
249 | what, desc);
|
---|
250 |
|
---|
251 | if (what == 's' || what == 'n')
|
---|
252 | {
|
---|
253 | if (*input_line_pointer != ',')
|
---|
254 | {
|
---|
255 | as_warn (_(".stab%c: missing comma"), what);
|
---|
256 | ignore_rest_of_line ();
|
---|
257 | return;
|
---|
258 | }
|
---|
259 | input_line_pointer++;
|
---|
260 | SKIP_WHITESPACE ();
|
---|
261 | }
|
---|
262 |
|
---|
263 | #ifdef TC_PPC
|
---|
264 | #ifdef OBJ_ELF
|
---|
265 | /* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
|
---|
266 | given 4 arguments, make it a .stabn */
|
---|
267 | else if (what == 'd')
|
---|
268 | {
|
---|
269 | char *save_location = input_line_pointer;
|
---|
270 |
|
---|
271 | SKIP_WHITESPACE ();
|
---|
272 | if (*input_line_pointer == ',')
|
---|
273 | {
|
---|
274 | input_line_pointer++;
|
---|
275 | what = 'n';
|
---|
276 | }
|
---|
277 | else
|
---|
278 | input_line_pointer = save_location;
|
---|
279 | }
|
---|
280 | #endif /* OBJ_ELF */
|
---|
281 | #endif /* TC_PPC */
|
---|
282 |
|
---|
283 | #ifndef NO_LISTING
|
---|
284 | if (listing)
|
---|
285 | {
|
---|
286 | switch (type)
|
---|
287 | {
|
---|
288 | case N_SLINE:
|
---|
289 | listing_source_line ((unsigned int) desc);
|
---|
290 | break;
|
---|
291 | case N_SO:
|
---|
292 | case N_SOL:
|
---|
293 | listing_source_file (string);
|
---|
294 | break;
|
---|
295 | }
|
---|
296 | }
|
---|
297 | #endif /* ! NO_LISTING */
|
---|
298 |
|
---|
299 | /* We have now gathered the type, other, and desc information. For
|
---|
300 | .stabs or .stabn, input_line_pointer is now pointing at the
|
---|
301 | value. */
|
---|
302 |
|
---|
303 | if (SEPARATE_STAB_SECTIONS)
|
---|
304 | /* Output the stab information in a separate section. This is used
|
---|
305 | at least for COFF and ELF. */
|
---|
306 | {
|
---|
307 | segT saved_seg = now_seg;
|
---|
308 | subsegT saved_subseg = now_subseg;
|
---|
309 | fragS *saved_frag = frag_now;
|
---|
310 | valueT dot;
|
---|
311 | segT seg;
|
---|
312 | unsigned int stroff;
|
---|
313 | char *p;
|
---|
314 |
|
---|
315 | static segT cached_sec;
|
---|
316 | static char *cached_secname;
|
---|
317 |
|
---|
318 | dot = frag_now_fix ();
|
---|
319 |
|
---|
320 | #ifdef md_flush_pending_output
|
---|
321 | md_flush_pending_output ();
|
---|
322 | #endif
|
---|
323 |
|
---|
324 | if (cached_secname && !strcmp (cached_secname, stab_secname))
|
---|
325 | {
|
---|
326 | seg = cached_sec;
|
---|
327 | subseg_set (seg, 0);
|
---|
328 | }
|
---|
329 | else
|
---|
330 | {
|
---|
331 | seg = subseg_new (stab_secname, 0);
|
---|
332 | if (cached_secname)
|
---|
333 | free (cached_secname);
|
---|
334 | cached_secname = xstrdup (stab_secname);
|
---|
335 | cached_sec = seg;
|
---|
336 | }
|
---|
337 |
|
---|
338 | if (! seg_info (seg)->hadone)
|
---|
339 | {
|
---|
340 | #ifdef BFD_ASSEMBLER
|
---|
341 | bfd_set_section_flags (stdoutput, seg,
|
---|
342 | SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
|
---|
343 | #endif
|
---|
344 | #ifdef INIT_STAB_SECTION
|
---|
345 | INIT_STAB_SECTION (seg);
|
---|
346 | #endif
|
---|
347 | seg_info (seg)->hadone = 1;
|
---|
348 | }
|
---|
349 |
|
---|
350 | stroff = get_stab_string_offset (string, stabstr_secname);
|
---|
351 | if (what == 's')
|
---|
352 | {
|
---|
353 | /* Release the string, if nobody else has used the obstack. */
|
---|
354 | if (saved_string_obstack_end == notes.next_free)
|
---|
355 | obstack_free (¬es, string);
|
---|
356 | }
|
---|
357 |
|
---|
358 | /* At least for now, stabs in a special stab section are always
|
---|
359 | output as 12 byte blocks of information. */
|
---|
360 | p = frag_more (8);
|
---|
361 | md_number_to_chars (p, (valueT) stroff, 4);
|
---|
362 | md_number_to_chars (p + 4, (valueT) type, 1);
|
---|
363 | md_number_to_chars (p + 5, (valueT) other, 1);
|
---|
364 | md_number_to_chars (p + 6, (valueT) desc, 2);
|
---|
365 |
|
---|
366 | if (what == 's' || what == 'n')
|
---|
367 | {
|
---|
368 | /* Pick up the value from the input line. */
|
---|
369 | cons (4);
|
---|
370 | input_line_pointer--;
|
---|
371 | }
|
---|
372 | else
|
---|
373 | {
|
---|
374 | const char *fake;
|
---|
375 | symbolS *symbol;
|
---|
376 | expressionS exp;
|
---|
377 |
|
---|
378 | /* Arrange for a value representing the current location. */
|
---|
379 | fake = FAKE_LABEL_NAME;
|
---|
380 | symbol = symbol_new (fake, saved_seg, dot, saved_frag);
|
---|
381 |
|
---|
382 | exp.X_op = O_symbol;
|
---|
383 | exp.X_add_symbol = symbol;
|
---|
384 | exp.X_add_number = 0;
|
---|
385 |
|
---|
386 | emit_expr (&exp, 4);
|
---|
387 | }
|
---|
388 |
|
---|
389 | #ifdef OBJ_PROCESS_STAB
|
---|
390 | OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
|
---|
391 | #endif
|
---|
392 |
|
---|
393 | subseg_set (saved_seg, saved_subseg);
|
---|
394 | }
|
---|
395 | else
|
---|
396 | {
|
---|
397 | #ifdef OBJ_PROCESS_STAB
|
---|
398 | OBJ_PROCESS_STAB (0, what, string, type, other, desc);
|
---|
399 | #else
|
---|
400 | abort ();
|
---|
401 | #endif
|
---|
402 | }
|
---|
403 |
|
---|
404 | demand_empty_rest_of_line ();
|
---|
405 | }
|
---|
406 |
|
---|
407 | /* Regular stab directive. */
|
---|
408 |
|
---|
409 | void
|
---|
410 | s_stab (what)
|
---|
411 | int what;
|
---|
412 | {
|
---|
413 | s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
|
---|
414 | }
|
---|
415 |
|
---|
416 | /* "Extended stabs", used in Solaris only now. */
|
---|
417 |
|
---|
418 | void
|
---|
419 | s_xstab (what)
|
---|
420 | int what;
|
---|
421 | {
|
---|
422 | int length;
|
---|
423 | char *stab_secname, *stabstr_secname;
|
---|
424 | static char *saved_secname, *saved_strsecname;
|
---|
425 |
|
---|
426 | /* @@ MEMORY LEAK: This allocates a copy of the string, but in most
|
---|
427 | cases it will be the same string, so we could release the storage
|
---|
428 | back to the obstack it came from. */
|
---|
429 | stab_secname = demand_copy_C_string (&length);
|
---|
430 | SKIP_WHITESPACE ();
|
---|
431 | if (*input_line_pointer == ',')
|
---|
432 | input_line_pointer++;
|
---|
433 | else
|
---|
434 | {
|
---|
435 | as_bad (_("comma missing in .xstabs"));
|
---|
436 | ignore_rest_of_line ();
|
---|
437 | return;
|
---|
438 | }
|
---|
439 |
|
---|
440 | /* To get the name of the stab string section, simply add "str" to
|
---|
441 | the stab section name. */
|
---|
442 | if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
|
---|
443 | {
|
---|
444 | stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
|
---|
445 | strcpy (stabstr_secname, stab_secname);
|
---|
446 | strcat (stabstr_secname, "str");
|
---|
447 | if (saved_secname)
|
---|
448 | {
|
---|
449 | free (saved_secname);
|
---|
450 | free (saved_strsecname);
|
---|
451 | }
|
---|
452 | saved_secname = stab_secname;
|
---|
453 | saved_strsecname = stabstr_secname;
|
---|
454 | }
|
---|
455 | s_stab_generic (what, saved_secname, saved_strsecname);
|
---|
456 | }
|
---|
457 |
|
---|
458 | #ifdef S_SET_DESC
|
---|
459 |
|
---|
460 | /* Frob invented at RMS' request. Set the n_desc of a symbol. */
|
---|
461 |
|
---|
462 | void
|
---|
463 | s_desc (ignore)
|
---|
464 | int ignore ATTRIBUTE_UNUSED;
|
---|
465 | {
|
---|
466 | char *name;
|
---|
467 | char c;
|
---|
468 | char *p;
|
---|
469 | symbolS *symbolP;
|
---|
470 | int temp;
|
---|
471 |
|
---|
472 | name = input_line_pointer;
|
---|
473 | c = get_symbol_end ();
|
---|
474 | p = input_line_pointer;
|
---|
475 | *p = c;
|
---|
476 | SKIP_WHITESPACE ();
|
---|
477 | if (*input_line_pointer != ',')
|
---|
478 | {
|
---|
479 | *p = 0;
|
---|
480 | as_bad (_("expected comma after \"%s\""), name);
|
---|
481 | *p = c;
|
---|
482 | ignore_rest_of_line ();
|
---|
483 | }
|
---|
484 | else
|
---|
485 | {
|
---|
486 | input_line_pointer++;
|
---|
487 | temp = get_absolute_expression ();
|
---|
488 | *p = 0;
|
---|
489 | symbolP = symbol_find_or_make (name);
|
---|
490 | *p = c;
|
---|
491 | S_SET_DESC (symbolP, temp);
|
---|
492 | }
|
---|
493 | demand_empty_rest_of_line ();
|
---|
494 | } /* s_desc() */
|
---|
495 |
|
---|
496 | #endif /* defined (S_SET_DESC) */
|
---|
497 |
|
---|
498 | /* Generate stabs debugging information to denote the main source file. */
|
---|
499 |
|
---|
500 | void
|
---|
501 | stabs_generate_asm_file ()
|
---|
502 | {
|
---|
503 | char *file;
|
---|
504 | unsigned int lineno;
|
---|
505 |
|
---|
506 | as_where (&file, &lineno);
|
---|
507 | generate_asm_file (N_SO, file);
|
---|
508 | }
|
---|
509 |
|
---|
510 | /* Generate stabs debugging information to denote the source file.
|
---|
511 | TYPE is one of N_SO, N_SOL. */
|
---|
512 |
|
---|
513 | static void
|
---|
514 | generate_asm_file (type, file)
|
---|
515 | int type;
|
---|
516 | char *file;
|
---|
517 | {
|
---|
518 | static char *last_file;
|
---|
519 | static int label_count;
|
---|
520 | char *hold;
|
---|
521 | char sym[30];
|
---|
522 | char *buf;
|
---|
523 | char *tmp = file;
|
---|
524 | char *endp = file + strlen (file);
|
---|
525 | char *bufp = buf;
|
---|
526 |
|
---|
527 | if (last_file != NULL
|
---|
528 | && strcmp (last_file, file) == 0)
|
---|
529 | return;
|
---|
530 |
|
---|
531 | /* Rather than try to do this in some efficient fashion, we just
|
---|
532 | generate a string and then parse it again. That lets us use the
|
---|
533 | existing stabs hook, which expect to see a string, rather than
|
---|
534 | inventing new ones. */
|
---|
535 | hold = input_line_pointer;
|
---|
536 |
|
---|
537 | sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
|
---|
538 | ++label_count;
|
---|
539 |
|
---|
540 | /* Allocate enough space for the file name (possibly extended with
|
---|
541 | doubled up backslashes), the symbol name, and the other characters
|
---|
542 | that make up a stabs file directive. */
|
---|
543 | bufp = buf = xmalloc (2 * strlen (file) + strlen (sym) + 12);
|
---|
544 |
|
---|
545 | *bufp++ = '"';
|
---|
546 |
|
---|
547 | while (tmp < endp)
|
---|
548 | {
|
---|
549 | char *bslash = strchr (tmp, '\\');
|
---|
550 | size_t len = (bslash) ? (size_t) (bslash - tmp + 1) : strlen (tmp);
|
---|
551 |
|
---|
552 | /* Double all backslashes, since demand_copy_C_string (used by
|
---|
553 | s_stab to extract the part in quotes) will try to replace them as
|
---|
554 | escape sequences. backslash may appear in a filespec. */
|
---|
555 | strncpy (bufp, tmp, len);
|
---|
556 |
|
---|
557 | tmp += len;
|
---|
558 | bufp += len;
|
---|
559 |
|
---|
560 | if (bslash != NULL)
|
---|
561 | *bufp++ = '\\';
|
---|
562 | }
|
---|
563 |
|
---|
564 | sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
|
---|
565 |
|
---|
566 | input_line_pointer = buf;
|
---|
567 | s_stab ('s');
|
---|
568 | colon (sym);
|
---|
569 |
|
---|
570 | if (last_file != NULL)
|
---|
571 | free (last_file);
|
---|
572 | last_file = xstrdup (file);
|
---|
573 |
|
---|
574 | free (buf);
|
---|
575 |
|
---|
576 | input_line_pointer = hold;
|
---|
577 | }
|
---|
578 |
|
---|
579 | /* Generate stabs debugging information for the current line. This is
|
---|
580 | used to produce debugging information for an assembler file. */
|
---|
581 |
|
---|
582 | void
|
---|
583 | stabs_generate_asm_lineno ()
|
---|
584 | {
|
---|
585 | static int label_count;
|
---|
586 | char *hold;
|
---|
587 | char *file;
|
---|
588 | unsigned int lineno;
|
---|
589 | char *buf;
|
---|
590 | char sym[30];
|
---|
591 | /* Remember the last file/line and avoid duplicates. */
|
---|
592 | static unsigned int prev_lineno = -1;
|
---|
593 | static char *prev_file = NULL;
|
---|
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 | hold = input_line_pointer;
|
---|
601 |
|
---|
602 | as_where (&file, &lineno);
|
---|
603 |
|
---|
604 | /* Don't emit sequences of stabs for the same line. */
|
---|
605 | if (prev_file == NULL)
|
---|
606 | {
|
---|
607 | /* First time thru. */
|
---|
608 | prev_file = xstrdup (file);
|
---|
609 | prev_lineno = lineno;
|
---|
610 | }
|
---|
611 | else if (lineno == prev_lineno
|
---|
612 | && strcmp (file, prev_file) == 0)
|
---|
613 | {
|
---|
614 | /* Same file/line as last time. */
|
---|
615 | return;
|
---|
616 | }
|
---|
617 | else
|
---|
618 | {
|
---|
619 | /* Remember file/line for next time. */
|
---|
620 | prev_lineno = lineno;
|
---|
621 | if (strcmp (file, prev_file) != 0)
|
---|
622 | {
|
---|
623 | free (prev_file);
|
---|
624 | prev_file = xstrdup (file);
|
---|
625 | }
|
---|
626 | }
|
---|
627 |
|
---|
628 | /* Let the world know that we are in the middle of generating a
|
---|
629 | piece of stabs line debugging information. */
|
---|
630 | outputting_stabs_line_debug = 1;
|
---|
631 |
|
---|
632 | generate_asm_file (N_SOL, file);
|
---|
633 |
|
---|
634 | sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
|
---|
635 | ++label_count;
|
---|
636 |
|
---|
637 | if (in_dot_func_p)
|
---|
638 | {
|
---|
639 | buf = (char *) alloca (100 + strlen (current_function_label));
|
---|
640 | sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
|
---|
641 | sym, current_function_label);
|
---|
642 | }
|
---|
643 | else
|
---|
644 | {
|
---|
645 | buf = (char *) alloca (100);
|
---|
646 | sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
|
---|
647 | }
|
---|
648 | input_line_pointer = buf;
|
---|
649 | s_stab ('n');
|
---|
650 | colon (sym);
|
---|
651 |
|
---|
652 | input_line_pointer = hold;
|
---|
653 | outputting_stabs_line_debug = 0;
|
---|
654 | }
|
---|
655 |
|
---|
656 | /* Emit a function stab.
|
---|
657 | All assembler functions are assumed to have return type `void'. */
|
---|
658 |
|
---|
659 | void
|
---|
660 | stabs_generate_asm_func (funcname, startlabname)
|
---|
661 | const char *funcname;
|
---|
662 | const char *startlabname;
|
---|
663 | {
|
---|
664 | static int void_emitted_p;
|
---|
665 | char *hold = input_line_pointer;
|
---|
666 | char *buf;
|
---|
667 | char *file;
|
---|
668 | unsigned int lineno;
|
---|
669 |
|
---|
670 | if (! void_emitted_p)
|
---|
671 | {
|
---|
672 | input_line_pointer = "\"void:t1=1\",128,0,0,0";
|
---|
673 | s_stab ('s');
|
---|
674 | void_emitted_p = 1;
|
---|
675 | }
|
---|
676 |
|
---|
677 | as_where (&file, &lineno);
|
---|
678 | asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
|
---|
679 | funcname, N_FUN, lineno + 1, startlabname);
|
---|
680 | input_line_pointer = buf;
|
---|
681 | s_stab ('s');
|
---|
682 | free (buf);
|
---|
683 |
|
---|
684 | input_line_pointer = hold;
|
---|
685 | current_function_label = xstrdup (startlabname);
|
---|
686 | in_dot_func_p = 1;
|
---|
687 | }
|
---|
688 |
|
---|
689 | /* Emit a stab to record the end of a function. */
|
---|
690 |
|
---|
691 | void
|
---|
692 | stabs_generate_asm_endfunc (funcname, startlabname)
|
---|
693 | const char *funcname ATTRIBUTE_UNUSED;
|
---|
694 | const char *startlabname;
|
---|
695 | {
|
---|
696 | static int label_count;
|
---|
697 | char *hold = input_line_pointer;
|
---|
698 | char *buf;
|
---|
699 | char sym[30];
|
---|
700 |
|
---|
701 | sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
|
---|
702 | ++label_count;
|
---|
703 | colon (sym);
|
---|
704 |
|
---|
705 | asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname);
|
---|
706 | input_line_pointer = buf;
|
---|
707 | s_stab ('s');
|
---|
708 | free (buf);
|
---|
709 |
|
---|
710 | input_line_pointer = hold;
|
---|
711 | in_dot_func_p = 0;
|
---|
712 | current_function_label = NULL;
|
---|
713 | }
|
---|