]>
Commit | Line | Data |
---|---|---|
fac0d250 | 1 | /* dwarf2dbg.c - DWARF2 debug support |
52454417 | 2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. |
fac0d250 RH |
3 | Contributed by David Mosberger-Tang <[email protected]> |
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 | |
89b66cde | 20 | 02111-1307, USA. */ |
fac0d250 | 21 | |
89b66cde | 22 | /* Logical line numbers can be controlled by the compiler via the |
fac0d250 RH |
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 | ||
d9ac5a3b | 36 | #include "elf/dwarf2.h" |
fac0d250 | 37 | |
fac0d250 RH |
38 | /* Since we can't generate the prolog until the body is complete, we |
39 | use three different subsegments for .debug_line: one holding the | |
40 | prolog, one for the directory and filename info, and one for the | |
41 | body ("statement program"). */ | |
42 | #define DL_PROLOG 0 | |
43 | #define DL_FILES 1 | |
44 | #define DL_BODY 2 | |
45 | ||
46 | /* First special line opcde - leave room for the standard opcodes. | |
47 | Note: If you want to change this, you'll have to update the | |
48 | "standard_opcode_lengths" table that is emitted below in | |
49 | dwarf2_finish(). */ | |
50 | #define DWARF2_LINE_OPCODE_BASE 10 | |
51 | ||
52 | #ifndef DWARF2_LINE_BASE | |
53 | /* Minimum line offset in a special line info. opcode. This value | |
54 | was chosen to give a reasonable range of values. */ | |
55 | # define DWARF2_LINE_BASE -5 | |
56 | #endif | |
57 | ||
58 | /* Range of line offsets in a special line info. opcode. */ | |
59 | #ifndef DWARF2_LINE_RANGE | |
60 | # define DWARF2_LINE_RANGE 14 | |
61 | #endif | |
62 | ||
63 | #ifndef DWARF2_LINE_MIN_INSN_LENGTH | |
64 | /* Define the architecture-dependent minimum instruction length (in | |
65 | bytes). This value should be rather too small than too big. */ | |
4dc7ead9 | 66 | # define DWARF2_LINE_MIN_INSN_LENGTH 1 |
fac0d250 RH |
67 | #endif |
68 | ||
69 | /* Flag that indicates the initial value of the is_stmt_start flag. | |
70 | In the present implementation, we do not mark any lines as | |
71 | the beginning of a source statement, because that information | |
72 | is not made available by the GCC front-end. */ | |
73 | #define DWARF2_LINE_DEFAULT_IS_STMT 1 | |
74 | ||
75 | /* Flag that indicates the initial value of the is_stmt_start flag. | |
76 | In the present implementation, we do not mark any lines as | |
77 | the beginning of a source statement, because that information | |
78 | is not made available by the GCC front-end. */ | |
79 | #define DWARF2_LINE_DEFAULT_IS_STMT 1 | |
80 | ||
cb30237e | 81 | /* Given a special op, return the line skip amount. */ |
fac0d250 RH |
82 | #define SPECIAL_LINE(op) \ |
83 | (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE) | |
84 | ||
85 | /* Given a special op, return the address skip amount (in units of | |
86 | DWARF2_LINE_MIN_INSN_LENGTH. */ | |
87 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) | |
88 | ||
cb30237e | 89 | /* The maximum address skip amount that can be encoded with a special op. */ |
fac0d250 RH |
90 | #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) |
91 | ||
92 | #define INITIAL_STATE \ | |
cb30237e | 93 | /* Initialize as per DWARF2.0 standard. */ \ |
fac0d250 RH |
94 | 0, /* address */ \ |
95 | 1, /* file */ \ | |
96 | 1, /* line */ \ | |
97 | 0, /* column */ \ | |
98 | DWARF2_LINE_DEFAULT_IS_STMT, /* is_stmt */ \ | |
99 | 0, /* basic_block */ \ | |
100 | 1 /* empty_sequence */ | |
101 | ||
e6c774b4 | 102 | static struct { |
fac0d250 | 103 | /* state machine state as per DWARF2 manual: */ |
e6c774b4 | 104 | struct dwarf2_sm { |
9e3af0e7 | 105 | addressT addr; |
fac0d250 RH |
106 | unsigned int filenum; |
107 | unsigned int line; | |
108 | unsigned int column; | |
109 | unsigned int | |
110 | is_stmt : 1, | |
111 | basic_block : 1, | |
112 | empty_sequence : 1; /* current code sequence has no DWARF2 directives? */ | |
e6c774b4 | 113 | } sm; |
fac0d250 RH |
114 | |
115 | unsigned int | |
116 | any_dwarf2_directives : 1; /* did we emit any DWARF2 line debug directives? */ | |
117 | ||
cb30237e | 118 | fragS * frag; /* frag that "addr" is relative to */ |
fac0d250 RH |
119 | segT text_seg; /* text segment "addr" is relative to */ |
120 | subsegT text_subseg; | |
121 | segT line_seg; /* ".debug_line" segment */ | |
122 | int last_filename; /* index of last filename that was used */ | |
123 | int num_filenames; /* index of last filename in use */ | |
124 | int filename_len; /* length of the filename array */ | |
e6c774b4 | 125 | struct { |
fac0d250 RH |
126 | int dir; /* valid after gen_dir_list() only */ |
127 | char *name; /* full path before gen_dir_list(), filename afterwards */ | |
e6c774b4 | 128 | } *file; |
fac0d250 | 129 | |
353e2c69 | 130 | struct dwarf2_line_info current; /* current source info */ |
fac0d250 | 131 | |
353e2c69 | 132 | /* counters for statistical purposes */ |
fac0d250 RH |
133 | unsigned int num_line_entries; |
134 | unsigned int opcode_hist[256]; /* histogram of opcode frequencies */ | |
e6c774b4 | 135 | } ls = { |
fac0d250 RH |
136 | { |
137 | INITIAL_STATE | |
138 | }, | |
ab9da554 ILT |
139 | 0, |
140 | 0, | |
141 | 0, | |
142 | 0, | |
143 | 0, | |
144 | 0, | |
145 | 0, | |
cb30237e | 146 | 0, |
ab9da554 ILT |
147 | NULL, |
148 | { NULL, 0, 0, 0, 0 }, | |
149 | 0, | |
150 | { | |
151 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
152 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
153 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
154 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
155 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
156 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
157 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
158 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
159 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
160 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
161 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
162 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
163 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
164 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
165 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
166 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
167 | } | |
e6c774b4 | 168 | }; |
fac0d250 | 169 | |
353e2c69 | 170 | /* Function prototypes. */ |
9e3af0e7 ILT |
171 | static void out_uleb128 PARAMS ((addressT)); |
172 | static void out_sleb128 PARAMS ((offsetT)); | |
173 | static void gen_addr_line PARAMS ((int, addressT)); | |
58b5739a | 174 | static void reset_state_machine PARAMS ((void)); |
9e3af0e7 | 175 | static void out_set_addr PARAMS ((addressT)); |
58b5739a RH |
176 | static void out_end_sequence PARAMS ((void)); |
177 | static int get_filenum PARAMS ((int, char *)); | |
178 | static void gen_dir_list PARAMS ((void)); | |
179 | static void gen_file_list PARAMS ((void)); | |
180 | static void print_stats PARAMS ((unsigned long)); | |
4dc7ead9 | 181 | static addressT now_subseg_size PARAMS ((void)); |
58b5739a | 182 | |
fac0d250 RH |
183 | #define out_byte(byte) FRAG_APPEND_1_CHAR(byte) |
184 | #define out_opcode(opc) (out_byte ((opc)), ++ls.opcode_hist[(opc) & 0xff]) | |
185 | ||
186 | /* Output an unsigned "little-endian base 128" number. */ | |
353e2c69 | 187 | |
fac0d250 | 188 | static void |
58b5739a | 189 | out_uleb128 (value) |
9e3af0e7 | 190 | addressT value; |
fac0d250 RH |
191 | { |
192 | unsigned char byte, more = 0x80; | |
193 | ||
194 | do | |
195 | { | |
196 | byte = value & 0x7f; | |
197 | value >>= 7; | |
198 | if (value == 0) | |
199 | more = 0; | |
200 | out_byte (more | byte); | |
201 | } | |
202 | while (more); | |
203 | } | |
204 | ||
205 | /* Output a signed "little-endian base 128" number. */ | |
353e2c69 | 206 | |
fac0d250 | 207 | static void |
58b5739a | 208 | out_sleb128 (value) |
9e3af0e7 | 209 | offsetT value; |
fac0d250 RH |
210 | { |
211 | unsigned char byte, more = 0x80; | |
212 | ||
213 | do | |
214 | { | |
215 | byte = value & 0x7f; | |
216 | value >>= 7; | |
217 | if (((value == 0) && ((byte & 0x40) == 0)) | |
218 | || ((value == -1) && ((byte & 0x40) != 0))) | |
219 | more = 0; | |
220 | out_byte (more | byte); | |
221 | } | |
222 | while (more); | |
223 | } | |
224 | ||
225 | /* Encode a pair of line and address skips as efficiently as possible. | |
226 | Note that the line skip is signed, whereas the address skip is | |
227 | unsigned. */ | |
353e2c69 | 228 | |
fac0d250 | 229 | static void |
58b5739a RH |
230 | gen_addr_line (line_delta, addr_delta) |
231 | int line_delta; | |
9e3af0e7 | 232 | addressT addr_delta; |
fac0d250 RH |
233 | { |
234 | unsigned int tmp, opcode; | |
235 | ||
236 | tmp = line_delta - DWARF2_LINE_BASE; | |
237 | ||
238 | if (tmp >= DWARF2_LINE_RANGE) | |
239 | { | |
240 | out_opcode (DW_LNS_advance_line); | |
241 | out_sleb128 (line_delta); | |
242 | tmp = 0 - DWARF2_LINE_BASE; | |
243 | line_delta = 0; | |
244 | } | |
245 | ||
246 | tmp += DWARF2_LINE_OPCODE_BASE; | |
247 | ||
353e2c69 | 248 | /* Try using a special opcode. */ |
e6c774b4 | 249 | opcode = tmp + addr_delta * DWARF2_LINE_RANGE; |
fac0d250 RH |
250 | if (opcode <= 255) |
251 | { | |
252 | out_opcode (opcode); | |
253 | return; | |
254 | } | |
255 | ||
353e2c69 KH |
256 | /* Try using DW_LNS_const_add_pc followed by special op. */ |
257 | opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; | |
fac0d250 RH |
258 | if (opcode <= 255) |
259 | { | |
260 | out_opcode (DW_LNS_const_add_pc); | |
261 | out_opcode (opcode); | |
262 | return; | |
263 | } | |
264 | ||
265 | out_opcode (DW_LNS_advance_pc); | |
266 | out_uleb128 (addr_delta); | |
267 | ||
268 | if (line_delta) | |
353e2c69 KH |
269 | /* Output line-delta. */ |
270 | out_opcode (tmp); | |
fac0d250 | 271 | else |
353e2c69 KH |
272 | /* Append new row with current info. */ |
273 | out_opcode (DW_LNS_copy); | |
fac0d250 RH |
274 | } |
275 | ||
276 | static void | |
58b5739a | 277 | reset_state_machine () |
fac0d250 RH |
278 | { |
279 | static const struct dwarf2_sm initial_state = { INITIAL_STATE }; | |
280 | ||
281 | ls.sm = initial_state; | |
282 | } | |
283 | ||
353e2c69 KH |
284 | /* Set an absolute address (may results in a relocation entry). */ |
285 | ||
fac0d250 | 286 | static void |
58b5739a | 287 | out_set_addr (addr) |
9e3af0e7 | 288 | addressT addr; |
fac0d250 RH |
289 | { |
290 | subsegT saved_subseg; | |
291 | segT saved_seg; | |
292 | expressionS expr; | |
293 | symbolS *sym; | |
9e3af0e7 | 294 | int bytes_per_address; |
fac0d250 RH |
295 | |
296 | saved_seg = now_seg; | |
297 | saved_subseg = now_subseg; | |
298 | ||
299 | subseg_set (ls.text_seg, ls.text_subseg); | |
300 | sym = symbol_new (".L0\001", now_seg, addr, frag_now); | |
301 | ||
302 | subseg_set (saved_seg, saved_subseg); | |
303 | ||
9e3af0e7 ILT |
304 | #ifdef BFD_ASSEMBLER |
305 | bytes_per_address = bfd_arch_bits_per_address (stdoutput) / 8; | |
306 | #else | |
307 | /* FIXME. */ | |
308 | bytes_per_address = 4; | |
309 | #endif | |
310 | ||
fac0d250 | 311 | out_opcode (DW_LNS_extended_op); |
9e3af0e7 | 312 | out_uleb128 (bytes_per_address + 1); |
fac0d250 RH |
313 | |
314 | out_opcode (DW_LNE_set_address); | |
315 | expr.X_op = O_symbol; | |
316 | expr.X_add_symbol = sym; | |
317 | expr.X_add_number = 0; | |
9e3af0e7 | 318 | emit_expr (&expr, bytes_per_address); |
fac0d250 RH |
319 | } |
320 | ||
321 | /* Emit DW_LNS_end_sequence and reset state machine. Does not | |
322 | preserve the current segment/sub-segment! */ | |
353e2c69 | 323 | |
fac0d250 | 324 | static void |
58b5739a | 325 | out_end_sequence () |
fac0d250 | 326 | { |
9e3af0e7 | 327 | addressT addr, delta; |
cb30237e | 328 | fragS *text_frag; |
fac0d250 RH |
329 | |
330 | if (ls.text_seg) | |
331 | { | |
332 | subseg_set (ls.text_seg, ls.text_subseg); | |
333 | #ifdef md_current_text_addr | |
334 | addr = md_current_text_addr (); | |
335 | #else | |
336 | addr = frag_now_fix (); | |
337 | #endif | |
cb30237e | 338 | text_frag = frag_now; |
fac0d250 | 339 | subseg_set (ls.line_seg, DL_BODY); |
cb30237e | 340 | if (text_frag != ls.frag) |
fac0d250 RH |
341 | { |
342 | out_set_addr (addr); | |
343 | ls.sm.addr = addr; | |
cb30237e | 344 | ls.frag = text_frag; |
fac0d250 RH |
345 | } |
346 | else | |
347 | { | |
09a798ea | 348 | delta = (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH; |
fac0d250 | 349 | if (delta > 0) |
09a798ea NC |
350 | { |
351 | /* Advance address without updating the line-debug | |
352 | matrix---the end_sequence entry is used only to tell | |
353e2c69 | 353 | the debugger the end of the sequence. */ |
09a798ea NC |
354 | out_opcode (DW_LNS_advance_pc); |
355 | out_uleb128 (delta); | |
356 | } | |
fac0d250 RH |
357 | } |
358 | } | |
359 | else | |
360 | subseg_set (ls.line_seg, DL_BODY); | |
361 | ||
362 | out_opcode (DW_LNS_extended_op); | |
363 | out_uleb128 (1); | |
364 | out_byte (DW_LNE_end_sequence); | |
365 | ||
366 | reset_state_machine (); | |
367 | } | |
368 | ||
369 | /* Look up a filenumber either by filename or by filenumber. If both | |
370 | a filenumber and a filename are specified, lookup by filename takes | |
371 | precedence. If the filename cannot be found, it is added to the | |
e1c05f12 | 372 | filetable and the filenumber for the new entry is returned. */ |
353e2c69 | 373 | |
fac0d250 | 374 | static int |
58b5739a RH |
375 | get_filenum (filenum, file) |
376 | int filenum; | |
377 | char *file; | |
fac0d250 RH |
378 | { |
379 | int i, last = filenum - 1; | |
380 | char char0 = file[0]; | |
381 | ||
e1c05f12 NC |
382 | /* If filenum is out of range of the filename table, then try using the |
383 | table entry returned from the previous call. */ | |
384 | if (last >= ls.num_filenames || last < 0) | |
fac0d250 RH |
385 | last = ls.last_filename; |
386 | ||
e1c05f12 | 387 | /* Do a quick check against the specified or previously used filenum. */ |
fac0d250 RH |
388 | if (ls.num_filenames > 0 && ls.file[last].name[0] == char0 |
389 | && strcmp (ls.file[last].name + 1, file + 1) == 0) | |
390 | return last + 1; | |
391 | ||
353e2c69 | 392 | /* No match, fall back to simple linear scan. */ |
fac0d250 RH |
393 | for (i = 0; i < ls.num_filenames; ++i) |
394 | { | |
395 | if (ls.file[i].name[0] == char0 | |
396 | && strcmp (ls.file[i].name + 1, file + 1) == 0) | |
397 | { | |
398 | ls.last_filename = i; | |
399 | return i + 1; | |
400 | } | |
401 | } | |
402 | ||
353e2c69 | 403 | /* No match, enter new filename. */ |
fac0d250 RH |
404 | if (ls.num_filenames >= ls.filename_len) |
405 | { | |
406 | ls.filename_len += 13; | |
407 | ls.file = xrealloc (ls.file, ls.filename_len * sizeof (ls.file[0])); | |
408 | } | |
409 | ls.file[ls.num_filenames].dir = 0; | |
410 | ls.file[ls.num_filenames].name = file; | |
e1c05f12 | 411 | ls.last_filename = ls.num_filenames; |
fac0d250 RH |
412 | return ++ls.num_filenames; |
413 | } | |
414 | ||
cb30237e NC |
415 | /* Emit an entry in the line number table if the address or line has changed. |
416 | ADDR is relative to the current frag in the text section. */ | |
417 | ||
fac0d250 | 418 | void |
58b5739a | 419 | dwarf2_gen_line_info (addr, l) |
9e3af0e7 | 420 | addressT addr; |
58b5739a | 421 | struct dwarf2_line_info *l; |
fac0d250 RH |
422 | { |
423 | unsigned int filenum = l->filenum; | |
424 | unsigned int any_output = 0; | |
425 | subsegT saved_subseg; | |
426 | segT saved_seg; | |
cb30237e | 427 | fragS *saved_frag; |
fac0d250 RH |
428 | |
429 | if (flag_debug) | |
966ed0b4 ILT |
430 | fprintf (stderr, "line: addr %lx file `%s' line %u col %u flags %x\n", |
431 | (unsigned long) addr, l->filename, l->line, l->column, l->flags); | |
fac0d250 RH |
432 | |
433 | if (filenum > 0 && !l->filename) | |
434 | { | |
ab9da554 | 435 | if (filenum >= (unsigned int) ls.num_filenames) |
fac0d250 RH |
436 | { |
437 | as_warn ("Encountered bad file number in line number debug info!"); | |
438 | return; | |
439 | } | |
440 | } | |
441 | else if (l->filename) | |
442 | filenum = get_filenum (filenum, l->filename); | |
443 | else | |
353e2c69 KH |
444 | /* No filename, no filnum => no play. */ |
445 | return; | |
fac0d250 | 446 | |
e1c05f12 NC |
447 | /* Must save these before the subseg_new call, as that call will change |
448 | them. */ | |
449 | saved_seg = now_seg; | |
450 | saved_subseg = now_subseg; | |
cb30237e | 451 | saved_frag = frag_now; |
e1c05f12 | 452 | |
fac0d250 RH |
453 | if (!ls.line_seg) |
454 | { | |
9e3af0e7 | 455 | #ifdef BFD_ASSEMBLER |
9de8d8f1 | 456 | symbolS *secsym; |
9e3af0e7 | 457 | #endif |
9de8d8f1 | 458 | |
6576f0b5 | 459 | ls.line_seg = subseg_new (".debug_line", 0); |
9e3af0e7 ILT |
460 | |
461 | #ifdef BFD_ASSEMBLER | |
fac0d250 | 462 | bfd_set_section_flags (stdoutput, ls.line_seg, SEC_READONLY); |
6576f0b5 RH |
463 | |
464 | /* We're going to need this symbol. */ | |
9de8d8f1 RH |
465 | secsym = symbol_find (".debug_line"); |
466 | if (secsym != NULL) | |
353e2c69 | 467 | symbol_set_bfdsym (secsym, ls.line_seg->symbol); |
9de8d8f1 | 468 | else |
353e2c69 | 469 | symbol_table_insert (section_symbol (ls.line_seg)); |
9e3af0e7 | 470 | #endif |
fac0d250 RH |
471 | } |
472 | ||
fac0d250 RH |
473 | subseg_set (ls.line_seg, DL_BODY); |
474 | ||
475 | if (ls.text_seg != saved_seg || ls.text_subseg != saved_subseg) | |
476 | { | |
477 | if (!ls.sm.empty_sequence) | |
478 | { | |
353e2c69 KH |
479 | /* Terminate previous sequence. */ |
480 | out_end_sequence (); | |
fac0d250 RH |
481 | ls.sm.empty_sequence = 1; |
482 | } | |
483 | any_output = 1; | |
484 | ls.text_seg = saved_seg; | |
485 | ls.text_subseg = saved_subseg; | |
486 | out_set_addr (addr); | |
487 | ls.sm.addr = addr; | |
cb30237e | 488 | ls.frag = saved_frag; |
fac0d250 RH |
489 | } |
490 | ||
491 | if (ls.sm.filenum != filenum) | |
492 | { | |
493 | any_output = 1; | |
494 | out_opcode (DW_LNS_set_file); | |
495 | out_uleb128 (filenum); | |
496 | ls.sm.filenum = filenum; | |
497 | } | |
498 | ||
499 | if (ls.sm.column != l->column) | |
500 | { | |
501 | any_output = 1; | |
502 | out_opcode (DW_LNS_set_column); | |
503 | out_uleb128 (l->column); | |
504 | ls.sm.column = l->column; | |
505 | } | |
506 | ||
507 | if (((l->flags & DWARF2_FLAG_BEGIN_STMT) != 0) != ls.sm.is_stmt) | |
508 | { | |
509 | any_output = 1; | |
510 | out_opcode (DW_LNS_negate_stmt); | |
511 | } | |
512 | ||
513 | if (l->flags & DWARF2_FLAG_BEGIN_BLOCK) | |
514 | { | |
515 | any_output = 1; | |
516 | out_opcode (DW_LNS_set_basic_block); | |
517 | } | |
518 | ||
519 | if (ls.sm.line != l->line) | |
520 | { | |
521 | any_output = 1; | |
cb30237e | 522 | if (saved_frag != ls.frag) |
fac0d250 | 523 | { |
cb30237e NC |
524 | /* If a new frag got allocated (for whatever reason), then |
525 | deal with it by generating a reference symbol. Note: no | |
526 | end_sequence needs to be generated because the address did | |
527 | not really decrease (only the reference point changed). */ | |
fac0d250 RH |
528 | out_set_addr (addr); |
529 | ls.sm.addr = addr; | |
cb30237e | 530 | ls.frag = saved_frag; |
fac0d250 RH |
531 | } |
532 | gen_addr_line (l->line - ls.sm.line, | |
533 | (addr - ls.sm.addr) / DWARF2_LINE_MIN_INSN_LENGTH); | |
534 | ls.sm.basic_block = 0; | |
535 | ls.sm.line = l->line; | |
536 | ls.sm.addr = addr; | |
537 | } | |
538 | ||
539 | subseg_set (saved_seg, saved_subseg); | |
540 | ||
541 | ls.num_line_entries += any_output; | |
542 | if (any_output) | |
543 | ls.sm.empty_sequence = 0; | |
544 | } | |
545 | ||
546 | static void | |
58b5739a | 547 | gen_dir_list () |
fac0d250 RH |
548 | { |
549 | char *str, *slash, *dir_list, *dp, *cp; | |
550 | int i, j, num_dirs; | |
551 | ||
552 | dir_list = frag_more (0); | |
553 | num_dirs = 0; | |
554 | ||
555 | for (i = 0; i < ls.num_filenames; ++i) | |
556 | { | |
557 | str = ls.file[i].name; | |
558 | slash = strrchr (str, '/'); | |
559 | if (slash) | |
560 | { | |
561 | *slash = '\0'; | |
562 | for (j = 0, dp = dir_list; j < num_dirs; ++j) | |
563 | { | |
564 | if (strcmp (str, dp) == 0) | |
565 | { | |
a340d270 | 566 | ls.file[i].dir = j + 1; |
fac0d250 RH |
567 | break; |
568 | } | |
569 | dp += strlen (dp); | |
570 | } | |
571 | if (j >= num_dirs) | |
572 | { | |
353e2c69 | 573 | /* Didn't find this directory: append it to the list. */ |
fac0d250 RH |
574 | size_t size = strlen (str) + 1; |
575 | cp = frag_more (size); | |
576 | memcpy (cp, str, size); | |
577 | ls.file[i].dir = ++num_dirs; | |
578 | } | |
579 | *slash = '/'; | |
580 | ls.file[i].name = slash + 1; | |
581 | } | |
582 | } | |
353e2c69 KH |
583 | |
584 | /* Terminate directory list. */ | |
585 | out_byte ('\0'); | |
fac0d250 RH |
586 | } |
587 | ||
588 | static void | |
58b5739a | 589 | gen_file_list () |
fac0d250 RH |
590 | { |
591 | size_t size; | |
592 | char *cp; | |
593 | int i; | |
594 | ||
595 | for (i = 0; i < ls.num_filenames; ++i) | |
596 | { | |
597 | size = strlen (ls.file[i].name) + 1; | |
598 | cp = frag_more (size); | |
599 | memcpy (cp, ls.file[i].name, size); | |
600 | ||
601 | out_uleb128 (ls.file[i].dir); /* directory number */ | |
602 | out_uleb128 (0); /* last modification timestamp */ | |
603 | out_uleb128 (0); /* filesize */ | |
604 | } | |
353e2c69 KH |
605 | |
606 | /* Terminate filename list. */ | |
607 | out_byte (0); | |
fac0d250 RH |
608 | } |
609 | ||
58b5739a RH |
610 | static void |
611 | print_stats (total_size) | |
612 | unsigned long total_size; | |
fac0d250 | 613 | { |
e6c774b4 KH |
614 | static const char *opc_name[] = { |
615 | "extended", "copy", "advance_pc", "advance_line", "set_file", | |
616 | "set_column", "negate_stmt", "set_basic_block", "const_add_pc", | |
617 | "fixed_advance_pc" | |
618 | }; | |
ab9da554 ILT |
619 | size_t i; |
620 | int j; | |
fac0d250 RH |
621 | |
622 | fprintf (stderr, "Average size: %g bytes/line\n", | |
623 | total_size / (double) ls.num_line_entries); | |
624 | ||
625 | fprintf (stderr, "\nStandard opcode histogram:\n"); | |
626 | ||
353e2c69 | 627 | for (i = 0; i < sizeof (opc_name) / sizeof (opc_name[0]); ++i) |
fac0d250 RH |
628 | { |
629 | fprintf (stderr, "%s", opc_name[i]); | |
630 | for (j = strlen (opc_name[i]); j < 16; ++j) | |
631 | fprintf (stderr, " "); | |
632 | fprintf (stderr, ": %u\n", ls.opcode_hist[i]); | |
633 | } | |
634 | ||
635 | fprintf (stderr, "\nSpecial opcodes:\naddr\t\t\t\tline skip\n"); | |
636 | ||
637 | fprintf (stderr, "skip: "); | |
638 | for (j = DWARF2_LINE_BASE; j < DWARF2_LINE_BASE + DWARF2_LINE_RANGE; ++j) | |
639 | fprintf (stderr, "%3d", j); | |
640 | fprintf (stderr, "\n-----"); | |
641 | ||
642 | for (; i < 256; ++i) | |
643 | { | |
644 | j = SPECIAL_LINE (i); | |
645 | if (j == DWARF2_LINE_BASE) | |
646 | fprintf (stderr, "\n%4u: ", | |
4dc7ead9 RH |
647 | (unsigned int) (DWARF2_LINE_MIN_INSN_LENGTH |
648 | * SPECIAL_ADDR (i))); | |
fac0d250 RH |
649 | fprintf (stderr, " %2u", ls.opcode_hist[i]); |
650 | } | |
651 | fprintf (stderr, "\n"); | |
652 | } | |
653 | ||
4dc7ead9 RH |
654 | /* Compute the size of the current subsegment, taking all fragments |
655 | into account. Note that we don't generate variant frags, so the | |
656 | fixed portion is all we need to consider. */ | |
657 | ||
658 | static addressT | |
659 | now_subseg_size () | |
660 | { | |
661 | struct frag *f; | |
662 | addressT size = 0; | |
663 | ||
664 | for (f = frchain_now->frch_root; f ; f = f->fr_next) | |
665 | size += f->fr_fix; | |
666 | ||
667 | return size + frag_now_fix_octets (); | |
668 | } | |
669 | ||
fac0d250 | 670 | void |
58b5739a | 671 | dwarf2_finish () |
fac0d250 | 672 | { |
9e3af0e7 | 673 | addressT body_size, total_size, prolog_size; |
58b5739a | 674 | subsegT saved_subseg; |
fac0d250 RH |
675 | segT saved_seg; |
676 | char *cp; | |
677 | ||
678 | if (!ls.line_seg) | |
353e2c69 | 679 | /* No .debug_line segment, no work to do. */ |
fac0d250 RH |
680 | return; |
681 | ||
682 | saved_seg = now_seg; | |
683 | saved_subseg = now_subseg; | |
684 | ||
685 | if (!ls.sm.empty_sequence) | |
686 | out_end_sequence (); | |
4dc7ead9 RH |
687 | subseg_set (ls.line_seg, DL_BODY); |
688 | total_size = body_size = now_subseg_size (); | |
fac0d250 | 689 | |
353e2c69 | 690 | /* Now generate the directory and file lists. */ |
fac0d250 RH |
691 | subseg_set (ls.line_seg, DL_FILES); |
692 | gen_dir_list (); | |
693 | gen_file_list (); | |
4dc7ead9 | 694 | total_size += now_subseg_size (); |
fac0d250 | 695 | |
353e2c69 | 696 | /* And now the header ("statement program prolog", in DWARF2 lingo...). */ |
fac0d250 RH |
697 | subseg_set (ls.line_seg, DL_PROLOG); |
698 | ||
699 | cp = frag_more (15 + DWARF2_LINE_OPCODE_BASE - 1); | |
700 | ||
4dc7ead9 | 701 | total_size += now_subseg_size (); |
fac0d250 RH |
702 | prolog_size = total_size - body_size - 10; |
703 | ||
4dc7ead9 RH |
704 | #define STUFF(val,size) \ |
705 | do { \ | |
706 | md_number_to_chars (cp, val, size); \ | |
707 | cp += size; \ | |
708 | } while (0) | |
709 | ||
fac0d250 RH |
710 | STUFF (total_size - 4, 4); /* length */ |
711 | STUFF (2, 2); /* version */ | |
712 | STUFF (prolog_size, 4); /* prologue_length */ | |
713 | STUFF (DWARF2_LINE_MIN_INSN_LENGTH, 1); | |
714 | STUFF (DWARF2_LINE_DEFAULT_IS_STMT, 1); | |
715 | STUFF (DWARF2_LINE_BASE, 1); | |
716 | STUFF (DWARF2_LINE_RANGE, 1); | |
717 | STUFF (DWARF2_LINE_OPCODE_BASE, 1); | |
718 | ||
719 | /* standard_opcode_lengths: */ | |
720 | STUFF (0, 1); /* DW_LNS_copy */ | |
721 | STUFF (1, 1); /* DW_LNS_advance_pc */ | |
722 | STUFF (1, 1); /* DW_LNS_advance_line */ | |
723 | STUFF (1, 1); /* DW_LNS_set_file */ | |
724 | STUFF (1, 1); /* DW_LNS_set_column */ | |
725 | STUFF (0, 1); /* DW_LNS_negate_stmt */ | |
726 | STUFF (0, 1); /* DW_LNS_set_basic_block */ | |
727 | STUFF (0, 1); /* DW_LNS_const_add_pc */ | |
728 | STUFF (1, 1); /* DW_LNS_fixed_advance_pc */ | |
729 | ||
4dc7ead9 RH |
730 | #undef STUFF |
731 | ||
732 | /* If this is assembler generated line info, add a .debug_info | |
733 | section as well. */ | |
734 | if (debug_type == DEBUG_DWARF2) | |
735 | { | |
736 | segT info_seg = subseg_new (".debug_info", 0); | |
737 | segT abbrev_seg = subseg_new (".debug_abbrev", 0); | |
738 | char *len; | |
739 | ||
740 | #ifdef BFD_ASSEMBLER | |
741 | bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY); | |
742 | bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY); | |
743 | #endif | |
744 | ||
745 | subseg_set (info_seg, 0); | |
746 | len = frag_more (4); | |
747 | ||
748 | #define STUFF(val, size) \ | |
749 | do { \ | |
750 | cp = frag_more (size); \ | |
751 | md_number_to_chars (cp, (val), (size)); \ | |
752 | } while(0) | |
753 | ||
754 | STUFF (2, 2); /* Dwarf version */ | |
755 | STUFF (0, 4); /* Offset into (final!) .debug_abbrev. */ | |
756 | ||
757 | /* Pointer size. */ | |
758 | #ifdef BFD_ASSEMBLER | |
759 | STUFF (bfd_arch_bits_per_address (stdoutput) / 8, 1); | |
760 | #else | |
761 | STUFF (4, 1); | |
762 | #endif | |
763 | ||
764 | /* FIXME: Add a DW_TAG_compile_unit DIE. The line info cannot | |
765 | even be seen without it. */ | |
766 | ||
767 | /* Set size of debug_info. */ | |
768 | md_number_to_chars (len, now_subseg_size () - 4, 4); | |
769 | } | |
770 | ||
fac0d250 RH |
771 | subseg_set (saved_seg, saved_subseg); |
772 | ||
773 | if (flag_debug) | |
774 | print_stats (total_size); | |
775 | } | |
776 | ||
777 | void | |
58b5739a | 778 | dwarf2_directive_file (dummy) |
ab9da554 | 779 | int dummy ATTRIBUTE_UNUSED; |
fac0d250 RH |
780 | { |
781 | int len; | |
782 | ||
58b5739a RH |
783 | /* Continue to accept a bare string and pass it off. */ |
784 | SKIP_WHITESPACE (); | |
785 | if (*input_line_pointer == '"') | |
786 | { | |
787 | s_app_file (0); | |
788 | return; | |
789 | } | |
790 | ||
fac0d250 RH |
791 | ls.any_dwarf2_directives = 1; |
792 | ||
fac0d250 RH |
793 | ls.current.filenum = get_absolute_expression (); |
794 | ls.current.filename = demand_copy_C_string (&len); | |
795 | ||
796 | demand_empty_rest_of_line (); | |
797 | } | |
798 | ||
799 | void | |
58b5739a | 800 | dwarf2_directive_loc (dummy) |
ab9da554 | 801 | int dummy ATTRIBUTE_UNUSED; |
fac0d250 RH |
802 | { |
803 | ls.any_dwarf2_directives = 1; | |
804 | ||
805 | ls.current.filenum = get_absolute_expression (); | |
806 | SKIP_WHITESPACE (); | |
807 | ls.current.line = get_absolute_expression (); | |
808 | SKIP_WHITESPACE (); | |
809 | ls.current.column = get_absolute_expression (); | |
810 | demand_empty_rest_of_line (); | |
811 | ||
812 | ls.current.flags = DWARF2_FLAG_BEGIN_STMT; | |
813 | ||
814 | #ifndef NO_LISTING | |
815 | if (listing) | |
816 | listing_source_line (ls.current.line); | |
817 | #endif | |
818 | } | |
819 | ||
820 | void | |
58b5739a RH |
821 | dwarf2_where (line) |
822 | struct dwarf2_line_info *line; | |
fac0d250 | 823 | { |
4dc7ead9 | 824 | if (debug_type == DEBUG_DWARF2) |
fac0d250 | 825 | { |
fac0d250 RH |
826 | as_where (&line->filename, &line->line); |
827 | line->filenum = 0; | |
828 | line->column = 0; | |
829 | line->flags = DWARF2_FLAG_BEGIN_STMT; | |
830 | } | |
4dc7ead9 RH |
831 | else |
832 | *line = ls.current; | |
fac0d250 | 833 | } |
85a39694 | 834 | |
4dc7ead9 RH |
835 | /* Called for each machine instruction, or relatively atomic group of |
836 | machine instructions (ie built-in macro). The instruction or group | |
837 | is SIZE bytes in length. If dwarf2 line number generation is called | |
838 | for, emit a line statement appropriately. */ | |
85a39694 NC |
839 | |
840 | void | |
4dc7ead9 | 841 | dwarf2_emit_insn (size) |
85a39694 NC |
842 | int size; |
843 | { | |
f585997b | 844 | addressT addr; |
4dc7ead9 RH |
845 | struct dwarf2_line_info debug_line; |
846 | ||
847 | if (debug_type != DEBUG_DWARF2 && ! ls.any_dwarf2_directives) | |
848 | return; | |
ef99799a | 849 | |
4dc7ead9 RH |
850 | /* Reset any_dwarf2_directives so that we won't waste time |
851 | determining that no information has changed between insns. */ | |
852 | ls.any_dwarf2_directives = 0; | |
853 | ||
85a39694 | 854 | /* First update the notion of the current source line. */ |
ef99799a KH |
855 | dwarf2_where (&debug_line); |
856 | ||
85a39694 NC |
857 | /* We want the offset of the start of this |
858 | instruction within the the current frag. */ | |
4dc7ead9 | 859 | addr = frag_now_fix () - size; |
ef99799a | 860 | |
85a39694 | 861 | /* And record the information. */ |
ef99799a | 862 | dwarf2_gen_line_info (addr, &debug_line); |
85a39694 | 863 | } |