2 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
29 #include "debugline.h"
31 struct line_reader_data
35 /* From the line number information header. */
36 uint8_t minimum_instruction_length
;
40 const uint8_t * standard_opcode_lengths
;
42 const uint8_t * * dirnames
;
44 size_t numfile
; /* As updated during execution of the table. */
45 const uint8_t * * filenames
;
47 /* Current position in the line table. */
49 /* End of this part of the line table. */
51 /* Start of the line table. */
57 /* Read in a word of fixed size, which may be unaligned, in the
58 appropriate endianness. */
59 #define read_16(p) (lnd->little_endian \
60 ? ((p)[1] << 8 | (p)[0]) \
61 : ((p)[0] << 8 | (p)[1]))
62 #define read_32(p) (lnd->little_endian \
63 ? ((p)[3] << 24 | (p)[2] << 16 | (p)[1] << 8 | (p)[0]) \
64 : ((p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3]))
65 #define read_64(p) (lnd->little_endian \
66 ? ((uint64_t) (p)[7] << 56 | (uint64_t) (p)[6] << 48 \
67 | (uint64_t) (p)[5] << 40 | (uint64_t) (p)[4] << 32 \
68 | (uint64_t) (p)[3] << 24 | (uint64_t) (p)[2] << 16u \
69 | (uint64_t) (p)[1] << 8 | (uint64_t) (p)[0]) \
70 : ((uint64_t) (p)[0] << 56 | (uint64_t) (p)[1] << 48 \
71 | (uint64_t) (p)[2] << 40 | (uint64_t) (p)[3] << 32 \
72 | (uint64_t) (p)[4] << 24 | (uint64_t) (p)[5] << 16u \
73 | (uint64_t) (p)[6] << 8 | (uint64_t) (p)[7]))
75 /* Skip over a LEB128 value (signed or unsigned). */
77 skip_leb128 (struct line_reader_data
* leb
)
79 while (leb
->cpos
!= leb
->end
&& *leb
->cpos
>= 0x80)
81 if (leb
->cpos
!= leb
->end
)
85 /* Read a ULEB128 into a 64-bit word. Return (uint64_t)-1 on overflow
86 or error. On overflow, skip past the rest of the uleb128. */
88 read_uleb128 (struct line_reader_data
* leb
)
96 if (leb
->cpos
== leb
->end
)
99 b
= *leb
->cpos
& 0x7f;
101 if (bit
>= 64 || b
<< bit
>> bit
!= b
)
102 result
= (uint64_t) -1;
104 result
|= b
<< bit
, bit
+= 7;
105 } while (*leb
->cpos
++ >= 0x80);
110 /* Read a SLEB128 into a 64-bit word. Return 0 on overflow or error
111 (which is not very helpful). On overflow, skip past the rest of
112 the SLEB128. For negative numbers, this actually overflows when
113 under -2^62, but since this is used for line numbers that ought to
116 read_sleb128 (struct line_reader_data
* leb
)
118 const uint8_t * start_pos
= leb
->cpos
;
119 uint64_t v
= read_uleb128 (leb
);
124 if (leb
->cpos
- start_pos
> 9)
127 signbit
= 1ull << ((leb
->cpos
- start_pos
) * 7 - 1);
129 return v
| -(v
& signbit
);
132 /* Free a line_reader_data structure. */
134 line_free (struct line_reader_data
* lnd
)
139 free (lnd
->dirnames
);
141 free (lnd
->filenames
);
145 /* Return the pathname of the file in S, or NULL on error.
146 The result will have been allocated with malloc. */
149 line_file (struct line_reader_data
*lnd
, uint64_t n
)
151 const uint8_t * prev_pos
= lnd
->cpos
;
152 size_t filelen
, dirlen
;
156 /* I'm not sure if this is actually an error. */
161 filelen
= strlen ((const char *)lnd
->filenames
[n
- 1]);
162 lnd
->cpos
= lnd
->filenames
[n
- 1] + filelen
+ 1;
163 dir
= read_uleb128 (lnd
);
164 lnd
->cpos
= prev_pos
;
166 || lnd
->filenames
[n
- 1][0] == '/')
167 return strdup ((const char *)lnd
->filenames
[n
- 1]);
168 else if (dir
> lnd
->numdir
)
171 dirlen
= strlen ((const char *) lnd
->dirnames
[dir
- 1]);
172 result
= malloc (dirlen
+ filelen
+ 2);
173 memcpy (result
, lnd
->dirnames
[dir
- 1], dirlen
);
174 result
[dirlen
] = '/';
175 memcpy (result
+ dirlen
+ 1, lnd
->filenames
[n
- 1], filelen
);
176 result
[dirlen
+ 1 + filelen
] = '\0';
180 /* Initialize a state S. Return FALSE on error. */
183 init_state (struct line_info
*s
)
189 s
->end_of_sequence
= false;
192 /* Read a debug_line section. */
194 struct line_reader_data
*
195 line_open (const uint8_t * debug_line
, size_t debug_line_size
,
198 struct line_reader_data
* lnd
= NULL
;
201 uint64_t lnd_length
, header_length
;
202 const uint8_t * table_start
;
204 if (debug_line_size
< 12)
207 lnd
= malloc (sizeof (struct line_reader_data
));
210 bzero(lnd
, sizeof(struct line_reader_data
));
212 lnd
->little_endian
= little_endian
;
213 lnd
->cpos
= debug_line
;
215 lnd_length
= read_32 (lnd
->cpos
);
217 if (lnd_length
== 0xffffffff)
219 lnd_length
= read_64 (lnd
->cpos
);
221 dwarf_size_64
= true;
223 else if (lnd_length
> 0xfffffff0)
224 /* Not a format we understand. */
227 dwarf_size_64
= false;
229 if (debug_line_size
< lnd_length
+ (dwarf_size_64
? 12 : 4)
230 || lnd_length
< (dwarf_size_64
? 15 : 11))
234 if (read_16 (lnd
->cpos
) != 2)
235 /* Unknown line number format. */
239 header_length
= dwarf_size_64
? (uint64_t)read_64(lnd
->cpos
) : (uint64_t)read_32(lnd
->cpos
);
240 lnd
->cpos
+= dwarf_size_64
? 8 : 4;
241 if (lnd_length
< header_length
+ (lnd
->cpos
- debug_line
)
242 || header_length
< 7)
245 lnd
->minimum_instruction_length
= lnd
->cpos
[0];
246 /* Ignore default_is_stmt. */
247 lnd
->line_base
= lnd
->cpos
[2];
248 lnd
->line_range
= lnd
->cpos
[3];
249 lnd
->opcode_base
= lnd
->cpos
[4];
251 if (lnd
->opcode_base
== 0)
252 /* Every valid line number program must use at least opcode 0
253 for DW_LNE_end_sequence. */
256 lnd
->standard_opcode_lengths
= lnd
->cpos
+ 5;
257 if (header_length
< (uint64_t)(5 + (lnd
->opcode_base
- 1)))
258 /* Header not long enough. */
260 lnd
->cpos
+= 5 + lnd
->opcode_base
- 1;
261 lnd
->end
= debug_line
+ header_length
+ (dwarf_size_64
? 22 : 10);
263 /* Make table of offsets to directory names. */
264 table_start
= lnd
->cpos
;
266 while (lnd
->cpos
!= lnd
->end
&& *lnd
->cpos
)
268 lnd
->cpos
= memchr (lnd
->cpos
, 0, lnd
->end
- lnd
->cpos
);
274 if (lnd
->cpos
== lnd
->end
)
276 lnd
->dirnames
= malloc (lnd
->numdir
* sizeof (const uint8_t *));
280 lnd
->cpos
= table_start
;
283 lnd
->dirnames
[lnd
->numdir
++] = lnd
->cpos
;
284 lnd
->cpos
= memchr (lnd
->cpos
, 0, lnd
->end
- lnd
->cpos
) + 1;
288 /* Make table of offsets to file entries. */
289 table_start
= lnd
->cpos
;
291 while (lnd
->cpos
!= lnd
->end
&& *lnd
->cpos
)
293 lnd
->cpos
= memchr (lnd
->cpos
, 0, lnd
->end
- lnd
->cpos
);
302 if (lnd
->cpos
== lnd
->end
)
304 lnd
->filenames
= malloc (lnd
->numfile
* sizeof (const uint8_t *));
305 if (! lnd
->filenames
)
308 lnd
->cpos
= table_start
;
311 lnd
->filenames
[lnd
->numfile
++] = lnd
->cpos
;
312 lnd
->cpos
= memchr (lnd
->cpos
, 0, lnd
->end
- lnd
->cpos
) + 1;
319 lnd
->numfile_orig
= lnd
->numfile
;
320 lnd
->cpos
= lnd
->init
= lnd
->end
;
321 lnd
->end
= debug_line
+ lnd_length
+ (dwarf_size_64
? 12 : 4);
323 init_state (&lnd
->cur
);
332 /* Reset back to the beginning. */
334 line_reset (struct line_reader_data
* lnd
)
336 lnd
->cpos
= lnd
->init
;
337 lnd
->numfile
= lnd
->numfile_orig
;
338 init_state (&lnd
->cur
);
341 /* Is there no more line data available? */
343 line_at_eof (struct line_reader_data
* lnd
)
345 return lnd
->cpos
== lnd
->end
;
349 next_state (struct line_reader_data
*lnd
)
351 if (lnd
->cur
.end_of_sequence
)
352 init_state (&lnd
->cur
);
359 if (lnd
->cpos
== lnd
->end
)
362 if (op
>= lnd
->opcode_base
)
364 op
-= lnd
->opcode_base
;
366 lnd
->cur
.line
+= op
% lnd
->line_range
+ lnd
->line_base
;
367 lnd
->cur
.pc
+= (op
/ lnd
->line_range
368 * lnd
->minimum_instruction_length
);
373 case DW_LNS_extended_op
:
375 uint64_t sz
= read_uleb128 (lnd
);
376 const uint8_t * op
= lnd
->cpos
;
378 if ((uint64_t)(lnd
->end
- op
) < sz
|| sz
== 0)
383 case DW_LNE_end_sequence
:
384 lnd
->cur
.end_of_sequence
= true;
387 case DW_LNE_set_address
:
389 lnd
->cur
.pc
= read_64 (op
);
391 lnd
->cur
.pc
= read_32 (op
);
396 case DW_LNE_define_file
:
398 const uint8_t * * filenames
;
401 (lnd
->numfile
+ 1) * sizeof (const uint8_t *));
404 /* Check for zero-termination. */
405 if (! memchr (op
, 0, lnd
->cpos
- op
))
407 filenames
[lnd
->numfile
++] = op
;
408 lnd
->filenames
= filenames
;
410 /* There's other data here, like file sizes and modification
411 times, but we don't need to read it so skip it. */
416 /* Don't understand it, so skip it. */
423 //fprintf(stderr, "DW_LNS_copy\n");
425 case DW_LNS_advance_pc
:
426 //fprintf(stderr, "DW_LNS_advance_pc\n");
427 tmp
= read_uleb128 (lnd
);
428 if (tmp
== (uint64_t) -1)
430 lnd
->cur
.pc
+= tmp
* lnd
->minimum_instruction_length
;
432 case DW_LNS_advance_line
:
433 //fprintf(stderr, "DW_LNS_advance_line\n");
434 lnd
->cur
.line
+= read_sleb128 (lnd
);
436 case DW_LNS_set_file
:
437 //fprintf(stderr, "DW_LNS_set_file\n");
438 lnd
->cur
.file
= read_uleb128 (lnd
);
440 case DW_LNS_set_column
:
441 //fprintf(stderr, "DW_LNS_set_column\n");
442 lnd
->cur
.col
= read_uleb128 (lnd
);
444 case DW_LNS_const_add_pc
:
445 //fprintf(stderr, "DW_LNS_const_add_pc\n");
446 lnd
->cur
.pc
+= ((255 - lnd
->opcode_base
) / lnd
->line_range
447 * lnd
->minimum_instruction_length
);
449 case DW_LNS_fixed_advance_pc
:
450 //fprintf(stderr, "DW_LNS_fixed_advance_pc\n");
451 if (lnd
->end
- lnd
->cpos
< 2)
453 lnd
->cur
.pc
+= read_16 (lnd
->cpos
);
458 /* Don't know what it is, so skip it. */
460 for (i
= 0; i
< lnd
->standard_opcode_lengths
[op
- 1]; i
++)
469 /* Set RESULT to the next 'interesting' line state, as indicated
470 by STOP, or return FALSE on error. The final (end-of-sequence)
471 line state is always considered interesting. */
473 line_next (struct line_reader_data
* lnd
,
474 struct line_info
* result
,
475 enum line_stop_constants stop
)
479 struct line_info prev
= lnd
->cur
;
481 if (! next_state (lnd
))
484 if (lnd
->cur
.end_of_sequence
)
486 if (stop
== line_stop_always
)
488 if ((stop
& line_stop_pc
) && lnd
->cur
.pc
!= prev
.pc
)
490 if ((stop
& line_stop_pos_mask
) && lnd
->cur
.file
!= prev
.file
)
492 if ((stop
& line_stop_pos_mask
) >= line_stop_line
493 && lnd
->cur
.line
!= prev
.line
)
495 if ((stop
& line_stop_pos_mask
) >= line_stop_col
496 && lnd
->cur
.col
!= prev
.col
)
503 /* Find the region (START->pc through END->pc) in the debug_line
504 information which contains PC. This routine starts searching at
505 the current position (which is returned as END), and will go all
506 the way around the debug_line information. It will return false if
507 an error occurs or if there is no matching region; these may be
508 distinguished by looking at START->end_of_sequence, which will be
509 false on error and true if there was no matching region.
510 You could write this routine using line_next, but this version
511 will be slightly more efficient, and of course more convenient. */
514 line_find_addr (struct line_reader_data
* lnd
,
515 struct line_info
* start
,
516 struct line_info
* end
,
519 const uint8_t * startpos
;
520 struct line_info prev
;
522 if (lnd
->cur
.end_of_sequence
&& lnd
->cpos
== lnd
->end
)
525 startpos
= lnd
->cpos
;
529 if (! next_state (lnd
))
531 start
->end_of_sequence
= false;
534 if (lnd
->cur
.end_of_sequence
&& lnd
->cpos
== lnd
->end
)
536 if (lnd
->cpos
== startpos
)
538 start
->end_of_sequence
= true;
541 } while (lnd
->cur
.pc
<= pc
|| prev
.pc
> pc
|| prev
.end_of_sequence
);