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