Commit | Line | Data |
---|---|---|
fac0d250 RH |
1 | /* dwarf2dbg.c - DWARF2 debug support |
2 | Copyright (C) 1999 Hewlett-Packard Co | |
3 | Contributed by David Mosberger-Tang <davidm@hpl.hp.com> | |
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 published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GAS is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | 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 | Logical line numbers can be controlled by the compiler via the | |
23 | following two directives: | |
24 | ||
25 | .file FILENO "file.c" | |
26 | .loc FILENO LINENO [COLUMN] | |
27 | ||
28 | FILENO is the filenumber. */ | |
29 | ||
30 | #include "ansidecl.h" | |
31 | ||
32 | #include "as.h" | |
33 | #include "dwarf2dbg.h" | |
34 | #include "subsegs.h" | |
35 | ||
36 | #include <elf/dwarf2.h> | |
37 | ||
38 | #define BYTES_PER_ADDRESS (BFD_ARCH_SIZE / 8) | |
39 | ||
40 | /* Since we can't generate the prolog until the body is complete, we | |
41 | use three different subsegments for .debug_line: one holding the | |
42 | prolog, one for the directory and filename info, and one for the | |
43 | body ("statement program"). */ | |
44 | #define DL_PROLOG 0 | |
45 | #define DL_FILES 1 | |
46 | #define DL_BODY 2 | |
47 | ||
48 | /* First special line opcde - leave room for the standard opcodes. | |
49 | Note: If you want to change this, you'll have to update the | |
50 | "standard_opcode_lengths" table that is emitted below in | |
51 | dwarf2_finish(). */ | |
52 | #define DWARF2_LINE_OPCODE_BASE 10 | |
53 | ||
54 | #ifndef DWARF2_LINE_BASE | |
55 | /* Minimum line offset in a special line info. opcode. This value | |
56 | was chosen to give a reasonable range of values. */ | |
57 | # define DWARF2_LINE_BASE -5 | |
58 | #endif | |
59 | ||
60 | /* Range of line offsets in a special line info. opcode. */ | |
61 | #ifndef DWARF2_LINE_RANGE | |
62 | # define DWARF2_LINE_RANGE 14 | |
63 | #endif | |
64 | ||
65 | #ifndef DWARF2_LINE_MIN_INSN_LENGTH | |
66 | /* Define the architecture-dependent minimum instruction length (in | |
67 | bytes). This value should be rather too small than too big. */ | |
68 | # define DWARF2_LINE_MIN_INSN_LENGTH 4 | |
69 | #endif | |
70 | ||
71 | /* Flag that indicates the initial value of the is_stmt_start flag. | |
72 | In the present implementation, we do not mark any lines as | |
73 | the beginning of a source statement, because that information | |
74 | is not made available by the GCC front-end. */ | |
75 | #define DWARF2_LINE_DEFAULT_IS_STMT 1 | |
76 | ||
77 | /* Flag that indicates the initial value of the is_stmt_start flag. | |
78 | In the present implementation, we do not mark any lines as | |
79 | the beginning of a source statement, because that information | |
80 | is not made available by the GCC front-end. */ | |
81 | #define DWARF2_LINE_DEFAULT_IS_STMT 1 | |
82 | ||
83 | /* Given a special op, return the line skip amount: */ | |
84 | #define SPECIAL_LINE(op) \ | |
85 | (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE) | |
86 | ||
87 | /* Given a special op, return the address skip amount (in units of | |
88 | DWARF2_LINE_MIN_INSN_LENGTH. */ | |
89 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) | |
90 | ||
91 | /* The maximum address skip amont that can be encoded with a special op: */ | |
92 | #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) | |
93 | ||
94 | #define INITIAL_STATE \ | |
95 | /* initialize as per DWARF2.0 standard: */ \ | |
96 | 0, /* address */ \ | |
97 | 1, /* file */ \ | |
98 | 1, /* line */ \ | |
99 | 0, /* column */ \ | |
100 | DWARF2_LINE_DEFAULT_IS_STMT, /* is_stmt */ \ | |
101 | 0, /* basic_block */ \ | |
102 | 1 /* empty_sequence */ | |
103 | ||
104 | static struct | |
105 | { | |
106 | /* state machine state as per DWARF2 manual: */ | |
107 | struct dwarf2_sm | |
108 | { | |
109 | bfd_vma addr; | |
110 | unsigned int filenum; | |
111 | unsigned int line; | |
112 | unsigned int column; | |
113 | unsigned int | |
114 | is_stmt : 1, | |
115 | basic_block : 1, | |
116 | empty_sequence : 1; /* current code sequence has no DWARF2 directives? */ | |
117 | } | |
118 | sm; | |
119 | ||
120 | unsigned int | |
121 | any_dwarf2_directives : 1; /* did we emit any DWARF2 line debug directives? */ | |
122 | ||
123 | segT text_seg; /* text segment "addr" is relative to */ | |
124 | subsegT text_subseg; | |
125 | segT line_seg; /* ".debug_line" segment */ | |
126 | int last_filename; /* index of last filename that was used */ | |
127 | int num_filenames; /* index of last filename in use */ | |
128 | int filename_len; /* length of the filename array */ | |
129 | struct | |
130 | { | |
131 | int dir; /* valid after gen_dir_list() only */ | |
132 | char *name; /* full path before gen_dir_list(), filename afterwards */ | |
133 | } | |
134 | *file; | |
135 | ||
136 | struct dwarf2_line_info current; /* current source info: */ | |
137 | ||
138 | /* counters for statistical purposes: */ | |
139 | unsigned int num_line_entries; | |
140 | unsigned int opcode_hist[256]; /* histogram of opcode frequencies */ | |
141 | } | |
142 | ls = | |
143 | { | |
144 | { | |
145 | INITIAL_STATE | |
146 | }, | |
147 | }; | |
148 | ||
58b5739a RH |
149 | |
150 | /* Function prototypes: */ | |
151 | static void out_uleb128 PARAMS ((bfd_vma)); | |
152 | static void out_sleb128 PARAMS ((bfd_signed_vma)); | |
153 | static void gen_addr_line PARAMS ((int, bfd_vma)); | |
154 | static void reset_state_machine PARAMS ((void)); | |
155 | static void out_set_addr PARAMS ((bfd_vma)); | |
156 | static void out_end_sequence PARAMS ((void)); | |
157 | static int get_filenum PARAMS ((int, char *)); | |
158 | static void gen_dir_list PARAMS ((void)); | |
159 | static void gen_file_list PARAMS ((void)); | |
160 | static void print_stats PARAMS ((unsigned long)); | |
161 | ||
162 | ||
fac0d250 RH |
163 | #define out_byte(byte) FRAG_APPEND_1_CHAR(byte) |
164 | #define out_opcode(opc) (out_byte ((opc)), ++ls.opcode_hist[(opc) & 0xff]) | |
165 | ||
166 | /* Output an unsigned "little-endian base 128" number. */ | |
167 | static void | |
58b5739a RH |
168 | out_uleb128 (value) |
169 | bfd_vma value; | |
fac0d250 RH |
170 | { |
171 | unsigned char byte, more = 0x80; | |
172 | ||
173 | do | |
174 | { | |
175 | byte = value & 0x7f; | |
176 | value >>= 7; | |
177 | if (value == 0) | |
178 | more = 0; | |
179 | out_byte (more | byte); | |
180 | } | |
181 | while (more); | |
182 | } | |
183 | ||
184 | /* Output a signed "little-endian base 128" number. */ | |
185 | static void | |
58b5739a RH |
186 | out_sleb128 (value) |
187 | bfd_signed_vma value; | |
fac0d250 RH |
188 | { |
189 | unsigned char byte, more = 0x80; | |
190 | ||
191 | do | |
192 | { | |
193 | byte = value & 0x7f; | |
194 | value >>= 7; | |
195 | if (((value == 0) && ((byte & 0x40) == 0)) | |
196 | || ((value == -1) && ((byte & 0x40) != 0))) | |
197 | more = 0; | |
198 | out_byte (more | byte); | |
199 | } | |
200 | while (more); | |
201 | } | |
202 | ||
203 | /* Encode a pair of line and address skips as efficiently as possible. | |
204 | Note that the line skip is signed, whereas the address skip is | |
205 | unsigned. */ | |
206 | static void | |
58b5739a RH |
207 | gen_addr_line (line_delta, addr_delta) |
208 | int line_delta; | |
209 | bfd_vma addr_delta; | |
fac0d250 RH |
210 | { |
211 | unsigned int tmp, opcode; | |
212 | ||
213 | tmp = line_delta - DWARF2_LINE_BASE; | |
214 | ||
215 | if (tmp >= DWARF2_LINE_RANGE) | |
216 | { | |
217 | out_opcode (DW_LNS_advance_line); | |
218 | out_sleb128 (line_delta); | |
219 | tmp = 0 - DWARF2_LINE_BASE; | |
220 | line_delta = 0; | |
221 | } | |
222 | ||
223 | tmp += DWARF2_LINE_OPCODE_BASE; | |
224 | ||
225 | /* try using a special opcode: */ | |
226 | opcode = tmp + addr_delta*DWARF2_LINE_RANGE; | |
227 | if (opcode <= 255) | |
228 | { | |
229 | out_opcode (opcode); | |
230 | return; | |
231 | } | |
232 | ||
233 | /* try using DW_LNS_const_add_pc followed by special op: */ | |
234 | opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA)*DWARF2_LINE_RANGE; | |
235 | if (opcode <= 255) | |
236 | { | |
237 | out_opcode (DW_LNS_const_add_pc); | |
238 | out_opcode (opcode); | |
239 | return; | |
240 | } | |
241 | ||
242 | out_opcode (DW_LNS_advance_pc); | |
243 | out_uleb128 (addr_delta); | |
244 | ||
245 | if (line_delta) | |
246 | out_opcode (tmp); /* output line-delta */ | |
247 | else | |
248 | out_opcode (DW_LNS_copy); /* append new row with current info */ | |
249 | } | |
250 | ||
251 | static void | |
58b5739a | 252 | reset_state_machine () |
fac0d250 RH |
253 | { |
254 | static const struct dwarf2_sm initial_state = { INITIAL_STATE }; | |
255 | ||
256 | ls.sm = initial_state; | |
257 | } | |
258 | ||
259 | /* Set an absolute address (may results in a relocation entry): */ | |
260 | static void | |
58b5739a RH |
261 | out_set_addr (addr) |
262 | bfd_vma addr; | |
fac0d250 RH |
263 | { |
264 | subsegT saved_subseg; | |
265 | segT saved_seg; | |
266 | expressionS expr; | |
267 | symbolS *sym; | |
268 | ||
269 | saved_seg = now_seg; | |
270 | saved_subseg = now_subseg; | |
271 | ||
272 | subseg_set (ls.text_seg, ls.text_subseg); | |
273 | sym = symbol_new (".L0\001", now_seg, addr, frag_now); | |
274 | ||
275 | subseg_set (saved_seg, saved_subseg); | |
276 | ||
277 | out_opcode (DW_LNS_extended_op); | |
278 | out_uleb128 (BYTES_PER_ADDRESS + 1); | |
279 | ||
280 | out_opcode (DW_LNE_set_address); | |
281 | expr.X_op = O_symbol; | |
282 | expr.X_add_symbol = sym; | |
283 | expr.X_add_number = 0; | |
284 | emit_expr (&expr, BYTES_PER_ADDRESS); | |
285 | } | |
286 | ||
287 | /* Emit DW_LNS_end_sequence and reset state machine. Does not | |
288 | preserve the current segment/sub-segment! */ | |
289 | static void | |
58b5739a | 290 | out_end_sequence () |
fac0d250 RH |
291 | { |
292 | bfd_vma addr, delta; | |
293 | ||
294 | if (ls.text_seg) | |
295 | { | |
296 | subseg_set (ls.text_seg, ls.text_subseg); | |
297 | #ifdef md_current_text_addr | |
298 | addr = md_current_text_addr (); | |
299 | #else | |
300 | addr = frag_now_fix (); | |
301 | #endif | |
302 | subseg_set (ls.line_seg, DL_BODY); | |
303 | if (addr < ls.sm.addr) | |
304 | { | |
305 | out_set_addr (addr); | |
306 | ls.sm.addr = addr; | |
307 | } | |
308 | else | |
309 | { | |
310 | delta = addr - ls.sm.addr; | |
311 | if (delta > 0) | |
312 | gen_addr_line (0, delta / DWARF2_LINE_MIN_INSN_LENGTH); | |
313 | } | |
314 | } | |
315 | else | |
316 | subseg_set (ls.line_seg, DL_BODY); | |
317 | ||
318 | out_opcode (DW_LNS_extended_op); | |
319 | out_uleb128 (1); | |
320 | out_byte (DW_LNE_end_sequence); | |
321 | ||
322 | reset_state_machine (); | |
323 | } | |
324 | ||
325 | /* Look up a filenumber either by filename or by filenumber. If both | |
326 | a filenumber and a filename are specified, lookup by filename takes | |
327 | precedence. If the filename cannot be found, it is added to the | |
328 | filetable the filenumber for the new entry is returned. */ | |
329 | static int | |
58b5739a RH |
330 | get_filenum (filenum, file) |
331 | int filenum; | |
332 | char *file; | |
fac0d250 RH |
333 | { |
334 | int i, last = filenum - 1; | |
335 | char char0 = file[0]; | |
336 | ||
337 | if ((unsigned) last >= ls.num_filenames) | |
338 | last = ls.last_filename; | |
339 | ||
340 | /* do a quick check against the previously used filename: */ | |
341 | if (ls.num_filenames > 0 && ls.file[last].name[0] == char0 | |
342 | && strcmp (ls.file[last].name + 1, file + 1) == 0) | |
343 | return last + 1; | |
344 | ||
345 | /* no match, fall back to simple linear scan: */ | |
346 | for (i = 0; i < ls.num_filenames; ++i) | |
347 | { | |
348 | if (ls.file[i].name[0] == char0 | |
349 | && strcmp (ls.file[i].name + 1, file + 1) == 0) | |
350 | { | |
351 | ls.last_filename = i; | |
352 | return i + 1; | |
353 | } | |
354 | } | |
355 | ||
356 | /* no match: enter new filename */ | |
357 | if (ls.num_filenames >= ls.filename_len) | |
358 | { | |
359 | ls.filename_len += 13; | |
360 | ls.file = xrealloc (ls.file, ls.filename_len * sizeof (ls.file[0])); | |
361 | } | |
362 | ls.file[ls.num_filenames].dir = 0; | |
363 | ls.file[ls.num_filenames].name = file; | |
364 | return ++ls.num_filenames; | |
365 | } | |
366 | ||
367 | void | |
58b5739a RH |
368 | dwarf2_gen_line_info (addr, l) |
369 | bfd_vma addr; | |
370 | struct dwarf2_line_info *l; | |
fac0d250 RH |
371 | { |
372 | unsigned int filenum = l->filenum; | |
373 | unsigned int any_output = 0; | |
374 | subsegT saved_subseg; | |
375 | segT saved_seg; | |
fac0d250 RH |
376 | |
377 | if (flag_debug) | |
58b5739a | 378 | fprintf (stderr, "line: addr %llx file `%s' line %u col %u flags %x\n", |
fac0d250 RH |
379 | (long long) addr, l->filename, l->line, l->column, l->flags); |
380 | ||
381 | if (filenum > 0 && !l->filename) | |
382 | { | |
383 | if (filenum >= ls.num_filenames) | |
384 | { | |
385 | as_warn ("Encountered bad file number in line number debug info!"); | |
386 | return; | |
387 | } | |
388 | } | |
389 | else if (l->filename) | |
390 | filenum = get_filenum (filenum, l->filename); | |
391 | else | |
392 | return; /* no filename, no filnum => no play */ | |
393 | ||
394 | if (!ls.line_seg) | |
395 | { | |
9de8d8f1 RH |
396 | symbolS *secsym; |
397 | ||
6576f0b5 | 398 | ls.line_seg = subseg_new (".debug_line", 0); |
fac0d250 | 399 | bfd_set_section_flags (stdoutput, ls.line_seg, SEC_READONLY); |
6576f0b5 RH |
400 | |
401 | /* We're going to need this symbol. */ | |
9de8d8f1 RH |
402 | secsym = symbol_find (".debug_line"); |
403 | if (secsym != NULL) | |
404 | symbol_set_bfdsym (secsym, ls.line_seg->symbol); | |
405 | else | |
406 | symbol_table_insert (section_symbol (ls.line_seg)); | |
fac0d250 RH |
407 | } |
408 | ||
409 | saved_seg = now_seg; | |
410 | saved_subseg = now_subseg; | |
411 | subseg_set (ls.line_seg, DL_BODY); | |
412 | ||
413 | if (ls.text_seg != saved_seg || ls.text_subseg != saved_subseg) | |
414 | { | |
415 | if (!ls.sm.empty_sequence) | |
416 | { | |
417 | out_end_sequence (); /* terminate previous sequence */ | |
418 | ls.sm.empty_sequence = 1; | |
419 | } | |
420 | any_output = 1; | |
421 | ls.text_seg = saved_seg; | |
422 | ls.text_subseg = saved_subseg; | |
423 | out_set_addr (addr); | |
424 | ls.sm.addr = addr; | |
425 | } | |
426 | ||
427 | if (ls.sm.filenum != filenum) | |
428 | { | |
429 | any_output = 1; | |
430 | out_opcode (DW_LNS_set_file); | |
431 | out_uleb128 (filenum); | |
432 | ls.sm.filenum = filenum; | |
433 | } | |
434 | ||
435 | if (ls.sm.column != l->column) | |
436 | { | |
437 | any_output = 1; | |
438 | out_opcode (DW_LNS_set_column); | |
439 | out_uleb128 (l->column); | |
440 | ls.sm.column = l->column; | |
441 | } | |
442 | ||
443 | if (((l->flags & DWARF2_FLAG_BEGIN_STMT) != 0) != ls.sm.is_stmt) | |
444 | { | |
445 | any_output = 1; | |
446 | out_opcode (DW_LNS_negate_stmt); | |
447 | } | |
448 | ||
449 | if (l->flags & DWARF2_FLAG_BEGIN_BLOCK) | |
450 | { | |
451 | any_output = 1; | |
452 | out_opcode (DW_LNS_set_basic_block); | |
453 | } | |
454 | ||
455 | if (ls.sm.line != l->line) | |
456 | { | |
457 | any_output = 1; | |
458 | if (addr < ls.sm.addr) | |
459 | { | |
460 | if (!ls.sm.empty_sequence) | |
461 | { | |
462 | out_end_sequence (); | |
463 | ls.sm.empty_sequence = 1; | |
464 | } | |
465 | out_set_addr (addr); | |
466 | ls.sm.addr = addr; | |
467 | } | |
468 | gen_addr_line (l->line - ls.sm.line, | |
469 | (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH); | |
470 | ls.sm.basic_block = 0; | |
471 | ls.sm.line = l->line; | |
472 | ls.sm.addr = addr; | |
473 | } | |
474 | ||
475 | subseg_set (saved_seg, saved_subseg); | |
476 | ||
477 | ls.num_line_entries += any_output; | |
478 | if (any_output) | |
479 | ls.sm.empty_sequence = 0; | |
480 | } | |
481 | ||
482 | static void | |
58b5739a | 483 | gen_dir_list () |
fac0d250 RH |
484 | { |
485 | char *str, *slash, *dir_list, *dp, *cp; | |
486 | int i, j, num_dirs; | |
487 | ||
488 | dir_list = frag_more (0); | |
489 | num_dirs = 0; | |
490 | ||
491 | for (i = 0; i < ls.num_filenames; ++i) | |
492 | { | |
493 | str = ls.file[i].name; | |
494 | slash = strrchr (str, '/'); | |
495 | if (slash) | |
496 | { | |
497 | *slash = '\0'; | |
498 | for (j = 0, dp = dir_list; j < num_dirs; ++j) | |
499 | { | |
500 | if (strcmp (str, dp) == 0) | |
501 | { | |
502 | ls.file[i].dir = j; | |
503 | break; | |
504 | } | |
505 | dp += strlen (dp); | |
506 | } | |
507 | if (j >= num_dirs) | |
508 | { | |
509 | /* didn't find this directory: append it to the list */ | |
510 | size_t size = strlen (str) + 1; | |
511 | cp = frag_more (size); | |
512 | memcpy (cp, str, size); | |
513 | ls.file[i].dir = ++num_dirs; | |
514 | } | |
515 | *slash = '/'; | |
516 | ls.file[i].name = slash + 1; | |
517 | } | |
518 | } | |
519 | out_byte ('\0'); /* terminate directory list */ | |
520 | } | |
521 | ||
522 | static void | |
58b5739a | 523 | gen_file_list () |
fac0d250 RH |
524 | { |
525 | size_t size; | |
526 | char *cp; | |
527 | int i; | |
528 | ||
529 | for (i = 0; i < ls.num_filenames; ++i) | |
530 | { | |
531 | size = strlen (ls.file[i].name) + 1; | |
532 | cp = frag_more (size); | |
533 | memcpy (cp, ls.file[i].name, size); | |
534 | ||
535 | out_uleb128 (ls.file[i].dir); /* directory number */ | |
536 | out_uleb128 (0); /* last modification timestamp */ | |
537 | out_uleb128 (0); /* filesize */ | |
538 | } | |
539 | out_byte (0); /* terminate filename list */ | |
540 | } | |
541 | ||
58b5739a RH |
542 | static void |
543 | print_stats (total_size) | |
544 | unsigned long total_size; | |
fac0d250 RH |
545 | { |
546 | static const char *opc_name[] = | |
547 | { | |
548 | "extended", "copy", "advance_pc", "advance_line", "set_file", | |
549 | "set_column", "negate_stmt", "set_basic_block", "const_add_pc", | |
550 | "fixed_advance_pc" | |
551 | }; | |
552 | int i, j; | |
553 | ||
554 | fprintf (stderr, "Average size: %g bytes/line\n", | |
555 | total_size / (double) ls.num_line_entries); | |
556 | ||
557 | fprintf (stderr, "\nStandard opcode histogram:\n"); | |
558 | ||
559 | for (i = 0; i < sizeof (opc_name)/sizeof (opc_name[0]); ++i) | |
560 | { | |
561 | fprintf (stderr, "%s", opc_name[i]); | |
562 | for (j = strlen (opc_name[i]); j < 16; ++j) | |
563 | fprintf (stderr, " "); | |
564 | fprintf (stderr, ": %u\n", ls.opcode_hist[i]); | |
565 | } | |
566 | ||
567 | fprintf (stderr, "\nSpecial opcodes:\naddr\t\t\t\tline skip\n"); | |
568 | ||
569 | fprintf (stderr, "skip: "); | |
570 | for (j = DWARF2_LINE_BASE; j < DWARF2_LINE_BASE + DWARF2_LINE_RANGE; ++j) | |
571 | fprintf (stderr, "%3d", j); | |
572 | fprintf (stderr, "\n-----"); | |
573 | ||
574 | for (; i < 256; ++i) | |
575 | { | |
576 | j = SPECIAL_LINE (i); | |
577 | if (j == DWARF2_LINE_BASE) | |
578 | fprintf (stderr, "\n%4u: ", | |
579 | DWARF2_LINE_MIN_INSN_LENGTH*SPECIAL_ADDR (i)); | |
580 | fprintf (stderr, " %2u", ls.opcode_hist[i]); | |
581 | } | |
582 | fprintf (stderr, "\n"); | |
583 | } | |
584 | ||
585 | void | |
58b5739a | 586 | dwarf2_finish () |
fac0d250 | 587 | { |
58b5739a RH |
588 | bfd_vma body_size, total_size, prolog_size; |
589 | subsegT saved_subseg; | |
fac0d250 RH |
590 | segT saved_seg; |
591 | char *cp; | |
592 | ||
593 | if (!ls.line_seg) | |
594 | /* no .debug_line segment, no work to do... */ | |
595 | return; | |
596 | ||
597 | saved_seg = now_seg; | |
598 | saved_subseg = now_subseg; | |
599 | ||
600 | if (!ls.sm.empty_sequence) | |
601 | out_end_sequence (); | |
602 | total_size = body_size = frag_now_fix (); | |
603 | ||
604 | /* now generate the directory and file lists: */ | |
605 | subseg_set (ls.line_seg, DL_FILES); | |
606 | gen_dir_list (); | |
607 | gen_file_list (); | |
608 | total_size += frag_now_fix (); | |
609 | ||
610 | /* and now the header ("statement program prolog", in DWARF2 lingo...) */ | |
611 | subseg_set (ls.line_seg, DL_PROLOG); | |
612 | ||
613 | cp = frag_more (15 + DWARF2_LINE_OPCODE_BASE - 1); | |
614 | ||
615 | total_size += frag_now_fix (); | |
616 | prolog_size = total_size - body_size - 10; | |
617 | ||
618 | # define STUFF(val,size) md_number_to_chars (cp, val, size); cp += size; | |
619 | STUFF (total_size - 4, 4); /* length */ | |
620 | STUFF (2, 2); /* version */ | |
621 | STUFF (prolog_size, 4); /* prologue_length */ | |
622 | STUFF (DWARF2_LINE_MIN_INSN_LENGTH, 1); | |
623 | STUFF (DWARF2_LINE_DEFAULT_IS_STMT, 1); | |
624 | STUFF (DWARF2_LINE_BASE, 1); | |
625 | STUFF (DWARF2_LINE_RANGE, 1); | |
626 | STUFF (DWARF2_LINE_OPCODE_BASE, 1); | |
627 | ||
628 | /* standard_opcode_lengths: */ | |
629 | STUFF (0, 1); /* DW_LNS_copy */ | |
630 | STUFF (1, 1); /* DW_LNS_advance_pc */ | |
631 | STUFF (1, 1); /* DW_LNS_advance_line */ | |
632 | STUFF (1, 1); /* DW_LNS_set_file */ | |
633 | STUFF (1, 1); /* DW_LNS_set_column */ | |
634 | STUFF (0, 1); /* DW_LNS_negate_stmt */ | |
635 | STUFF (0, 1); /* DW_LNS_set_basic_block */ | |
636 | STUFF (0, 1); /* DW_LNS_const_add_pc */ | |
637 | STUFF (1, 1); /* DW_LNS_fixed_advance_pc */ | |
638 | ||
639 | subseg_set (saved_seg, saved_subseg); | |
640 | ||
641 | if (flag_debug) | |
642 | print_stats (total_size); | |
643 | } | |
644 | ||
645 | void | |
58b5739a RH |
646 | dwarf2_directive_file (dummy) |
647 | int dummy; | |
fac0d250 RH |
648 | { |
649 | int len; | |
650 | ||
58b5739a RH |
651 | /* Continue to accept a bare string and pass it off. */ |
652 | SKIP_WHITESPACE (); | |
653 | if (*input_line_pointer == '"') | |
654 | { | |
655 | s_app_file (0); | |
656 | return; | |
657 | } | |
658 | ||
fac0d250 RH |
659 | ls.any_dwarf2_directives = 1; |
660 | ||
661 | if (debug_type == DEBUG_NONE) | |
662 | /* Automatically turn on DWARF2 debug info unless something else | |
663 | has been selected. */ | |
664 | debug_type = DEBUG_DWARF2; | |
665 | ||
666 | ls.current.filenum = get_absolute_expression (); | |
667 | ls.current.filename = demand_copy_C_string (&len); | |
668 | ||
669 | demand_empty_rest_of_line (); | |
670 | } | |
671 | ||
672 | void | |
58b5739a RH |
673 | dwarf2_directive_loc (dummy) |
674 | int dummy; | |
fac0d250 RH |
675 | { |
676 | ls.any_dwarf2_directives = 1; | |
677 | ||
678 | ls.current.filenum = get_absolute_expression (); | |
679 | SKIP_WHITESPACE (); | |
680 | ls.current.line = get_absolute_expression (); | |
681 | SKIP_WHITESPACE (); | |
682 | ls.current.column = get_absolute_expression (); | |
683 | demand_empty_rest_of_line (); | |
684 | ||
685 | ls.current.flags = DWARF2_FLAG_BEGIN_STMT; | |
686 | ||
687 | #ifndef NO_LISTING | |
688 | if (listing) | |
689 | listing_source_line (ls.current.line); | |
690 | #endif | |
691 | } | |
692 | ||
693 | void | |
58b5739a RH |
694 | dwarf2_where (line) |
695 | struct dwarf2_line_info *line; | |
fac0d250 RH |
696 | { |
697 | if (ls.any_dwarf2_directives) | |
698 | *line = ls.current; | |
699 | else | |
700 | { | |
fac0d250 RH |
701 | as_where (&line->filename, &line->line); |
702 | line->filenum = 0; | |
703 | line->column = 0; | |
704 | line->flags = DWARF2_FLAG_BEGIN_STMT; | |
705 | } | |
706 | } |