blob: 2b3f39b24f36edd486f9e3b35f4d4e51a093615f [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DWARFDebugLine.h"
11
12//#define ENABLE_DEBUG_PRINTF // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!!
13#include <assert.h>
14
15#include "lldb/Core/FileSpecList.h"
16#include "lldb/Core/Log.h"
17#include "lldb/Core/Timer.h"
18
19#include "SymbolFileDWARF.h"
20#include "LogChannelDWARF.h"
21
22using namespace lldb_private;
23using namespace std;
24
25//----------------------------------------------------------------------
26// Parse
27//
28// Parse all information in the debug_line_data into an internal
29// representation.
30//----------------------------------------------------------------------
31void
32DWARFDebugLine::Parse(const DataExtractor& debug_line_data)
33{
34 m_lineTableMap.clear();
35 dw_offset_t offset = 0;
36 LineTable::shared_ptr line_table_sp(new LineTable);
37 while (debug_line_data.ValidOffset(offset))
38 {
39 const uint32_t debug_line_offset = offset;
40
41 if (line_table_sp.get() == NULL)
42 break;
43
44 if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get()))
45 {
46 // Make sure we don't don't loop infinitely
47 if (offset <= debug_line_offset)
48 break;
49 //DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", debug_line_offset);
50 m_lineTableMap[debug_line_offset] = line_table_sp;
51 line_table_sp.reset(new LineTable);
52 }
53 else
54 ++offset; // Try next byte in line table
55 }
56}
57
58void
59DWARFDebugLine::ParseIfNeeded(const DataExtractor& debug_line_data)
60{
61 if (m_lineTableMap.empty())
62 Parse(debug_line_data);
63}
64
65
66//----------------------------------------------------------------------
67// DWARFDebugLine::GetLineTable
68//----------------------------------------------------------------------
69DWARFDebugLine::LineTable::shared_ptr
70DWARFDebugLine::GetLineTable(const dw_offset_t offset) const
71{
72 DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr;
73 LineTableConstIter pos = m_lineTableMap.find(offset);
74 if (pos != m_lineTableMap.end())
75 line_table_shared_ptr = pos->second;
76 return line_table_shared_ptr;
77}
78
79
80//----------------------------------------------------------------------
81// DumpStateToFile
82//----------------------------------------------------------------------
83static void
84DumpStateToFile (dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
85{
86 Log *log = (Log *)userData;
87 if (state.row == DWARFDebugLine::State::StartParsingLineTable)
88 {
89 // If the row is zero we are being called with the prologue only
90 state.prologue->Dump (log);
91 log->PutCString ("Address Line Column File");
92 log->PutCString ("------------------ ------ ------ ------");
93 }
94 else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
95 {
96 // Done parsing line table
97 }
98 else
99 {
100 log->Printf( "0x%16.16llx %6u %6u %6u%s\n", state.address, state.line, state.column, state.file, state.end_sequence ? " END" : "");
101 }
102}
103
104//----------------------------------------------------------------------
105// DWARFDebugLine::DumpLineTableRows
106//----------------------------------------------------------------------
107bool
108DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset)
109{
110 const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
111
112 if (debug_line_offset == DW_INVALID_OFFSET)
113 {
114 // Dump line table to a single file only
115 debug_line_offset = 0;
116 while (debug_line_data.ValidOffset(debug_line_offset))
117 debug_line_offset = DumpStatementTable (log, debug_line_data, debug_line_offset);
118 }
119 else
120 {
121 // Dump line table to a single file only
122 DumpStatementTable (log, debug_line_data, debug_line_offset);
123 }
124 return false;
125}
126
127//----------------------------------------------------------------------
128// DWARFDebugLine::DumpStatementTable
129//----------------------------------------------------------------------
130dw_offset_t
131DWARFDebugLine::DumpStatementTable(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset)
132{
133 if (debug_line_data.ValidOffset(debug_line_offset))
134 {
135 uint32_t offset = debug_line_offset;
136 log->Printf( "----------------------------------------------------------------------\n"
137 "debug_line[0x%8.8x]\n"
138 "----------------------------------------------------------------------\n", debug_line_offset);
139
140 if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log))
141 return offset;
142 else
143 return debug_line_offset + 1; // Skip to next byte in .debug_line section
144 }
145
146 return DW_INVALID_OFFSET;
147}
148
149
150//----------------------------------------------------------------------
151// DumpOpcodes
152//----------------------------------------------------------------------
153bool
154DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset, uint32_t dump_flags)
155{
156 const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
157
158 if (debug_line_data.GetByteSize() == 0)
159 {
160 log->Printf( "< EMPTY >\n");
161 return false;
162 }
163
164 if (debug_line_offset == DW_INVALID_OFFSET)
165 {
166 // Dump line table to a single file only
167 debug_line_offset = 0;
168 while (debug_line_data.ValidOffset(debug_line_offset))
169 debug_line_offset = DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
170 }
171 else
172 {
173 // Dump line table to a single file only
174 DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
175 }
176 return false;
177}
178
179//----------------------------------------------------------------------
180// DumpStatementOpcodes
181//----------------------------------------------------------------------
182dw_offset_t
183DWARFDebugLine::DumpStatementOpcodes(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset, uint32_t flags)
184{
185 uint32_t offset = debug_line_offset;
186 if (debug_line_data.ValidOffset(offset))
187 {
188 Prologue prologue;
189
190 if (ParsePrologue(debug_line_data, &offset, &prologue))
191 {
192 log->PutCString ("----------------------------------------------------------------------");
193 log->Printf ("debug_line[0x%8.8x]", debug_line_offset);
194 log->PutCString ("----------------------------------------------------------------------\n");
195 prologue.Dump (log);
196 }
197 else
198 {
199 offset = debug_line_offset;
200 log->Printf( "0x%8.8x: skipping pad byte %2.2x", offset, debug_line_data.GetU8(&offset));
201 return offset;
202 }
203
204 Row row(prologue.default_is_stmt);
205 const dw_offset_t end_offset = debug_line_offset + prologue.total_length + sizeof(prologue.total_length);
206
207 assert(debug_line_data.ValidOffset(end_offset-1));
208
209 while (offset < end_offset)
210 {
211 const uint32_t op_offset = offset;
212 uint8_t opcode = debug_line_data.GetU8(&offset);
213 switch (opcode)
214 {
215 case 0: // Extended Opcodes always start with a zero opcode followed by
216 { // a uleb128 length so you can skip ones you don't know about
217
218 dw_offset_t ext_offset = offset;
219 dw_uleb128_t len = debug_line_data.GetULEB128(&offset);
220 dw_offset_t arg_size = len - (offset - ext_offset);
221 uint8_t sub_opcode = debug_line_data.GetU8(&offset);
222// if (verbose)
223// log->Printf( "Extended: <%u> %2.2x ", len, sub_opcode);
224
225 switch (sub_opcode)
226 {
227 case DW_LNE_end_sequence :
228 log->Printf( "0x%8.8x: DW_LNE_end_sequence", op_offset);
229 row.Dump(log);
230 row.Reset(prologue.default_is_stmt);
231 break;
232
233 case DW_LNE_set_address :
234 {
235 row.address = debug_line_data.GetMaxU64(&offset, arg_size);
236 log->Printf( "0x%8.8x: DW_LNE_set_address (0x%llx)", op_offset, row.address);
237 }
238 break;
239
240 case DW_LNE_define_file:
241 {
242 FileNameEntry fileEntry;
243 fileEntry.name = debug_line_data.GetCStr(&offset);
244 fileEntry.dir_idx = debug_line_data.GetULEB128(&offset);
245 fileEntry.mod_time = debug_line_data.GetULEB128(&offset);
246 fileEntry.length = debug_line_data.GetULEB128(&offset);
247 log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",
248 op_offset,
249 fileEntry.name.c_str(),
250 fileEntry.dir_idx,
251 fileEntry.mod_time,
252 fileEntry.length);
253 prologue.file_names.push_back(fileEntry);
254 }
255 break;
256
257 default:
258 log->Printf( "0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode", op_offset, opcode);
259 // Length doesn't include the zero opcode byte or the length itself, but
260 // it does include the sub_opcode, so we have to adjust for that below
261 offset += arg_size;
262 break;
263 }
264 }
265 break;
266
267 // Standard Opcodes
268 case DW_LNS_copy:
269 log->Printf( "0x%8.8x: DW_LNS_copy", op_offset);
270 row.Dump (log);
271 break;
272
273 case DW_LNS_advance_pc:
274 {
275 dw_uleb128_t addr_offset_n = debug_line_data.GetULEB128(&offset);
276 dw_uleb128_t addr_offset = addr_offset_n * prologue.min_inst_length;
277 log->Printf( "0x%8.8x: DW_LNS_advance_pc (0x%llx)", op_offset, addr_offset);
278 row.address += addr_offset;
279 }
280 break;
281
282 case DW_LNS_advance_line:
283 {
284 dw_sleb128_t line_offset = debug_line_data.GetSLEB128(&offset);
285 log->Printf( "0x%8.8x: DW_LNS_advance_line (%i)", op_offset, line_offset);
286 row.line += line_offset;
287 }
288 break;
289
290 case DW_LNS_set_file:
291 row.file = debug_line_data.GetULEB128(&offset);
292 log->Printf( "0x%8.8x: DW_LNS_set_file (%u)", op_offset, row.file);
293 break;
294
295 case DW_LNS_set_column:
296 row.column = debug_line_data.GetULEB128(&offset);
297 log->Printf( "0x%8.8x: DW_LNS_set_column (%u)", op_offset, row.column);
298 break;
299
300 case DW_LNS_negate_stmt:
301 row.is_stmt = !row.is_stmt;
302 log->Printf( "0x%8.8x: DW_LNS_negate_stmt", op_offset);
303 break;
304
305 case DW_LNS_set_basic_block:
306 row.basic_block = true;
307 log->Printf( "0x%8.8x: DW_LNS_set_basic_block", op_offset);
308 break;
309
310 case DW_LNS_const_add_pc:
311 {
312 uint8_t adjust_opcode = 255 - prologue.opcode_base;
313 dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
314 log->Printf( "0x%8.8x: DW_LNS_const_add_pc (0x%8.8llx)", op_offset, addr_offset);
315 row.address += addr_offset;
316 }
317 break;
318
319 case DW_LNS_fixed_advance_pc:
320 {
321 uint16_t pc_offset = debug_line_data.GetU16(&offset);
322 log->Printf( "0x%8.8x: DW_LNS_fixed_advance_pc (0x%4.4x)", op_offset, pc_offset);
323 row.address += pc_offset;
324 }
325 break;
326
327 case DW_LNS_set_prologue_end:
328 row.prologue_end = true;
329 log->Printf( "0x%8.8x: DW_LNS_set_prologue_end", op_offset);
330 break;
331
332 case DW_LNS_set_epilogue_begin:
333 row.epilogue_begin = true;
334 log->Printf( "0x%8.8x: DW_LNS_set_epilogue_begin", op_offset);
335 break;
336
337 case DW_LNS_set_isa:
338 row.isa = debug_line_data.GetULEB128(&offset);
339 log->Printf( "0x%8.8x: DW_LNS_set_isa (%u)", op_offset, row.isa);
340 break;
341
342 // Special Opcodes
343 default:
344 if (opcode < prologue.opcode_base)
345 {
346 // We have an opcode that this parser doesn't know about, skip
347 // the number of ULEB128 numbers that is says to skip in the
348 // prologue's standard_opcode_lengths array
349 uint8_t n = prologue.standard_opcode_lengths[opcode-1];
350 log->Printf( "0x%8.8x: Special : Unknown skipping %u ULEB128 values.", op_offset, n);
351 while (n > 0)
352 {
353 debug_line_data.GetULEB128(&offset);
354 --n;
355 }
356 }
357 else
358 {
359 uint8_t adjust_opcode = opcode - prologue.opcode_base;
360 dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
361 int32_t line_offset = prologue.line_base + (adjust_opcode % prologue.line_range);
362 log->Printf("0x%8.8x: address += 0x%llx, line += %i\n", op_offset, (uint64_t)addr_offset, line_offset);
363 row.address += addr_offset;
364 row.line += line_offset;
365 row.Dump (log);
366 }
367 break;
368 }
369 }
370 return end_offset;
371 }
372 return DW_INVALID_OFFSET;
373}
374
375
376
377
378//----------------------------------------------------------------------
379// Parse
380//
381// Parse the entire line table contents calling callback each time a
382// new prologue is parsed and every time a new row is to be added to
383// the line table.
384//----------------------------------------------------------------------
385void
386DWARFDebugLine::Parse(const DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData)
387{
388 uint32_t offset = 0;
389 if (debug_line_data.ValidOffset(offset))
390 {
391 if (!ParseStatementTable(debug_line_data, &offset, callback, userData))
392 ++offset; // Skip to next byte in .debug_line section
393 }
394}
395
396
397//----------------------------------------------------------------------
398// DWARFDebugLine::ParsePrologue
399//----------------------------------------------------------------------
400bool
401DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, dw_offset_t* offset_ptr, Prologue* prologue)
402{
403// const uint32_t prologue_offset = *offset_ptr;
404
405 //DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
406
407 prologue->Clear();
408 uint32_t i;
409 const char * s;
410 prologue->total_length = debug_line_data.GetU32(offset_ptr);
411 prologue->version = debug_line_data.GetU16(offset_ptr);
412 if (prologue->version != 2)
413 return false;
414
415 prologue->prologue_length = debug_line_data.GetU32(offset_ptr);
416 const dw_offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr;
417 prologue->min_inst_length = debug_line_data.GetU8(offset_ptr);
418 prologue->default_is_stmt = debug_line_data.GetU8(offset_ptr);
419 prologue->line_base = debug_line_data.GetU8(offset_ptr);
420 prologue->line_range = debug_line_data.GetU8(offset_ptr);
421 prologue->opcode_base = debug_line_data.GetU8(offset_ptr);
422
423 prologue->standard_opcode_lengths.reserve(prologue->opcode_base-1);
424
425 for (i=1; i<prologue->opcode_base; ++i)
426 {
427 uint8_t op_len = debug_line_data.GetU8(offset_ptr);
428 prologue->standard_opcode_lengths.push_back(op_len);
429 }
430
431 while (*offset_ptr < end_prologue_offset)
432 {
433 s = debug_line_data.GetCStr(offset_ptr);
434 if (s && s[0])
435 prologue->include_directories.push_back(s);
436 else
437 break;
438 }
439
440 while (*offset_ptr < end_prologue_offset)
441 {
442 const char* name = debug_line_data.GetCStr( offset_ptr );
443 if (name && name[0])
444 {
445 FileNameEntry fileEntry;
446 fileEntry.name = name;
447 fileEntry.dir_idx = debug_line_data.GetULEB128( offset_ptr );
448 fileEntry.mod_time = debug_line_data.GetULEB128( offset_ptr );
449 fileEntry.length = debug_line_data.GetULEB128( offset_ptr );
450 prologue->file_names.push_back(fileEntry);
451 }
452 else
453 break;
454 }
455
456 assert(*offset_ptr == end_prologue_offset);
457 return end_prologue_offset;
458}
459
460bool
461DWARFDebugLine::ParseSupportFiles(const DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, FileSpecList &support_files)
462{
463 uint32_t offset = stmt_list + 4; // Skip the total length
464 const char * s;
465 uint32_t version = debug_line_data.GetU16(&offset);
466 if (version != 2)
467 return false;
468
469 const dw_offset_t end_prologue_offset = debug_line_data.GetU32(&offset) + offset;
470 // Skip instruction length, default is stmt, line base, line range and
471 // opcode base, and all opcode lengths
472 offset += 4;
473 const uint8_t opcode_base = debug_line_data.GetU8(&offset);
474 offset += opcode_base - 1;
475 std::vector<std::string> include_directories;
476 include_directories.push_back(""); // Directory at index zero doesn't exist
477 while (offset < end_prologue_offset)
478 {
479 s = debug_line_data.GetCStr(&offset);
480 if (s && s[0])
481 include_directories.push_back(s);
482 else
483 break;
484 }
485 std::string fullpath;
486 while (offset < end_prologue_offset)
487 {
488 const char* path = debug_line_data.GetCStr( &offset );
489 if (path && path[0])
490 {
491 uint32_t dir_idx = debug_line_data.GetULEB128( &offset );
492 debug_line_data.Skip_LEB128(&offset); // Skip mod_time
493 debug_line_data.Skip_LEB128(&offset); // Skip length
494
495 if (path[0] == '/')
496 {
497 // The path starts with a directory delimiter, so we are done.
498 fullpath = path;
499 }
500 else
501 {
502 if (dir_idx > 0 && dir_idx < include_directories.size())
503 {
504 if (cu_comp_dir && include_directories[dir_idx][0] != '/')
505 {
506 fullpath = cu_comp_dir;
507
508 if (*fullpath.rbegin() != '/')
509 fullpath += '/';
510 fullpath += include_directories[dir_idx];
511
512 }
513 else
514 fullpath = include_directories[dir_idx];
515 }
516 else if (cu_comp_dir && cu_comp_dir[0])
517 {
518 fullpath = cu_comp_dir;
519 }
520
521 if (!fullpath.empty())
522 {
523 if (*fullpath.rbegin() != '/')
524 fullpath += '/';
525 }
526 fullpath += path;
527 }
528 FileSpec file_spec(fullpath.c_str());
529 support_files.Append(file_spec);
530 }
531 }
532
533 assert(offset == end_prologue_offset);
534 return end_prologue_offset;
535}
536
537//----------------------------------------------------------------------
538// ParseStatementTable
539//
540// Parse a single line table (prologue and all rows) and call the
541// callback function once for the prologue (row in state will be zero)
542// and each time a row is to be added to the line table.
543//----------------------------------------------------------------------
544bool
545DWARFDebugLine::ParseStatementTable
546(
547 const DataExtractor& debug_line_data,
548 dw_offset_t* offset_ptr,
549 DWARFDebugLine::State::Callback callback,
550 void* userData
551)
552{
553 Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE);
554 Prologue::shared_ptr prologue(new Prologue());
555
556
557 const dw_offset_t debug_line_offset = *offset_ptr;
558
559 Timer scoped_timer (__PRETTY_FUNCTION__,
560 "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
561 debug_line_offset);
562
563 if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get()))
564 {
565 if (log)
566 log->Error ("failed to parse DWARF line table prologue");
567 // Restore our offset and return false to indicate failure!
568 *offset_ptr = debug_line_offset;
569 return false;
570 }
571
572 if (log)
573 prologue->Dump (log);
574
575 const dw_offset_t end_offset = debug_line_offset + prologue->total_length + sizeof(prologue->total_length);
576
577 assert(debug_line_data.ValidOffset(end_offset-1));
578
579 State state(prologue, log, callback, userData);
580
581 while (*offset_ptr < end_offset)
582 {
583 //DEBUG_PRINTF("0x%8.8x: ", *offset_ptr);
584 uint8_t opcode = debug_line_data.GetU8(offset_ptr);
585
586 if (opcode == 0)
587 {
588 // Extended Opcodes always start with a zero opcode followed by
589 // a uleb128 length so you can skip ones you don't know about
590 dw_offset_t ext_offset = *offset_ptr;
591 dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
592 dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
593
594 //DEBUG_PRINTF("Extended: <%2u> ", len);
595 uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr);
596 switch (sub_opcode)
597 {
598 case DW_LNE_end_sequence:
599 // Set the end_sequence register of the state machine to true and
600 // append a row to the matrix using the current values of the
601 // state-machine registers. Then reset the registers to the initial
602 // values specified above. Every statement program sequence must end
603 // with a DW_LNE_end_sequence instruction which creates a row whose
604 // address is that of the byte after the last target machine instruction
605 // of the sequence.
606 state.end_sequence = true;
607 state.AppendRowToMatrix(*offset_ptr);
608 state.Reset();
609 break;
610
611 case DW_LNE_set_address:
612 // Takes a single relocatable address as an operand. The size of the
613 // operand is the size appropriate to hold an address on the target
614 // machine. Set the address register to the value given by the
615 // relocatable address. All of the other statement program opcodes
616 // that affect the address register add a delta to it. This instruction
617 // stores a relocatable value into it instead.
618 state.address = debug_line_data.GetAddress(offset_ptr);
619 break;
620
621 case DW_LNE_define_file:
622 // Takes 4 arguments. The first is a null terminated string containing
623 // a source file name. The second is an unsigned LEB128 number representing
624 // the directory index of the directory in which the file was found. The
625 // third is an unsigned LEB128 number representing the time of last
626 // modification of the file. The fourth is an unsigned LEB128 number
627 // representing the length in bytes of the file. The time and length
628 // fields may contain LEB128(0) if the information is not available.
629 //
630 // The directory index represents an entry in the include_directories
631 // section of the statement program prologue. The index is LEB128(0)
632 // if the file was found in the current directory of the compilation,
633 // LEB128(1) if it was found in the first directory in the
634 // include_directories section, and so on. The directory index is
635 // ignored for file names that represent full path names.
636 //
637 // The files are numbered, starting at 1, in the order in which they
638 // appear; the names in the prologue come before names defined by
639 // the DW_LNE_define_file instruction. These numbers are used in the
640 // the file register of the state machine.
641 {
642 FileNameEntry fileEntry;
643 fileEntry.name = debug_line_data.GetCStr(offset_ptr);
644 fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
645 fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
646 fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
647 state.prologue->file_names.push_back(fileEntry);
648 }
649 break;
650
651 default:
652 // Length doesn't include the zero opcode byte or the length itself, but
653 // it does include the sub_opcode, so we have to adjust for that below
654 (*offset_ptr) += arg_size;
655 break;
656 }
657 }
658 else if (opcode < prologue->opcode_base)
659 {
660 switch (opcode)
661 {
662 // Standard Opcodes
663 case DW_LNS_copy:
664 // Takes no arguments. Append a row to the matrix using the
665 // current values of the state-machine registers. Then set
666 // the basic_block register to false.
667 state.AppendRowToMatrix(*offset_ptr);
668 break;
669
670 case DW_LNS_advance_pc:
671 // Takes a single unsigned LEB128 operand, multiplies it by the
672 // min_inst_length field of the prologue, and adds the
673 // result to the address register of the state machine.
674 state.address += debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
675 break;
676
677 case DW_LNS_advance_line:
678 // Takes a single signed LEB128 operand and adds that value to
679 // the line register of the state machine.
680 state.line += debug_line_data.GetSLEB128(offset_ptr);
681 break;
682
683 case DW_LNS_set_file:
684 // Takes a single unsigned LEB128 operand and stores it in the file
685 // register of the state machine.
686 state.file = debug_line_data.GetULEB128(offset_ptr);
687 break;
688
689 case DW_LNS_set_column:
690 // Takes a single unsigned LEB128 operand and stores it in the
691 // column register of the state machine.
692 state.column = debug_line_data.GetULEB128(offset_ptr);
693 break;
694
695 case DW_LNS_negate_stmt:
696 // Takes no arguments. Set the is_stmt register of the state
697 // machine to the logical negation of its current value.
698 state.is_stmt = !state.is_stmt;
699 break;
700
701 case DW_LNS_set_basic_block:
702 // Takes no arguments. Set the basic_block register of the
703 // state machine to true
704 state.basic_block = true;
705 break;
706
707 case DW_LNS_const_add_pc:
708 // Takes no arguments. Add to the address register of the state
709 // machine the address increment value corresponding to special
710 // opcode 255. The motivation for DW_LNS_const_add_pc is this:
711 // when the statement program needs to advance the address by a
712 // small amount, it can use a single special opcode, which occupies
713 // a single byte. When it needs to advance the address by up to
714 // twice the range of the last special opcode, it can use
715 // DW_LNS_const_add_pc followed by a special opcode, for a total
716 // of two bytes. Only if it needs to advance the address by more
717 // than twice that range will it need to use both DW_LNS_advance_pc
718 // and a special opcode, requiring three or more bytes.
719 {
720 uint8_t adjust_opcode = 255 - prologue->opcode_base;
721 dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
722 state.address += addr_offset;
723 }
724 break;
725
726 case DW_LNS_fixed_advance_pc:
727 // Takes a single uhalf operand. Add to the address register of
728 // the state machine the value of the (unencoded) operand. This
729 // is the only extended opcode that takes an argument that is not
730 // a variable length number. The motivation for DW_LNS_fixed_advance_pc
731 // is this: existing assemblers cannot emit DW_LNS_advance_pc or
732 // special opcodes because they cannot encode LEB128 numbers or
733 // judge when the computation of a special opcode overflows and
734 // requires the use of DW_LNS_advance_pc. Such assemblers, however,
735 // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
736 state.address += debug_line_data.GetU16(offset_ptr);
737 break;
738
739 case DW_LNS_set_prologue_end:
740 // Takes no arguments. Set the prologue_end register of the
741 // state machine to true
742 state.prologue_end = true;
743 break;
744
745 case DW_LNS_set_epilogue_begin:
746 // Takes no arguments. Set the basic_block register of the
747 // state machine to true
748 state.epilogue_begin = true;
749 break;
750
751 case DW_LNS_set_isa:
752 // Takes a single unsigned LEB128 operand and stores it in the
753 // column register of the state machine.
754 state.isa = debug_line_data.GetULEB128(offset_ptr);
755 break;
756
757 default:
758 // Handle any unknown standard opcodes here. We know the lengths
759 // of such opcodes because they are specified in the prologue
760 // as a multiple of LEB128 operands for each opcode.
761 {
762 uint8_t i;
763 assert (opcode - 1 < prologue->standard_opcode_lengths.size());
764 const uint8_t opcode_length = prologue->standard_opcode_lengths[opcode - 1];
765 for (i=0; i<opcode_length; ++i)
766 debug_line_data.Skip_LEB128(offset_ptr);
767 }
768 break;
769 }
770 }
771 else
772 {
773 // Special Opcodes
774
775 // A special opcode value is chosen based on the amount that needs
776 // to be added to the line and address registers. The maximum line
777 // increment for a special opcode is the value of the line_base
778 // field in the header, plus the value of the line_range field,
779 // minus 1 (line base + line range - 1). If the desired line
780 // increment is greater than the maximum line increment, a standard
781 // opcode must be used instead of a special opcode. The “address
782 // advance” is calculated by dividing the desired address increment
783 // by the minimum_instruction_length field from the header. The
784 // special opcode is then calculated using the following formula:
785 //
786 // opcode = (desired line increment - line_base) + (line_range * address advance) + opcode_base
787 //
788 // If the resulting opcode is greater than 255, a standard opcode
789 // must be used instead.
790 //
791 // To decode a special opcode, subtract the opcode_base from the
792 // opcode itself to give the adjusted opcode. The amount to
793 // increment the address register is the result of the adjusted
794 // opcode divided by the line_range multiplied by the
795 // minimum_instruction_length field from the header. That is:
796 //
797 // address increment = (adjusted opcode / line_range) * minimim_instruction_length
798 //
799 // The amount to increment the line register is the line_base plus
800 // the result of the adjusted opcode modulo the line_range. That is:
801 //
802 // line increment = line_base + (adjusted opcode % line_range)
803
804 uint8_t adjust_opcode = opcode - prologue->opcode_base;
805 dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
806 int32_t line_offset = prologue->line_base + (adjust_opcode % prologue->line_range);
807 state.line += line_offset;
808 state.address += addr_offset;
809 state.AppendRowToMatrix(*offset_ptr);
810 }
811 }
812
813 state.Finalize( *offset_ptr );
814
815 return end_offset;
816}
817
818
819//----------------------------------------------------------------------
820// ParseStatementTableCallback
821//----------------------------------------------------------------------
822static void
823ParseStatementTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
824{
825 DWARFDebugLine::LineTable* line_table = (DWARFDebugLine::LineTable*)userData;
826 if (state.row == DWARFDebugLine::State::StartParsingLineTable)
827 {
828 // Just started parsing the line table, so lets keep a reference to
829 // the prologue using the supplied shared pointer
830 line_table->prologue = state.prologue;
831 }
832 else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
833 {
834 // Done parsing line table, nothing to do for the cleanup
835 }
836 else
837 {
838 // We have a new row, lets append it
839 line_table->AppendRow(state);
840 }
841}
842
843//----------------------------------------------------------------------
844// ParseStatementTable
845//
846// Parse a line table at offset and populate the LineTable class with
847// the prologue and all rows.
848//----------------------------------------------------------------------
849bool
850DWARFDebugLine::ParseStatementTable(const DataExtractor& debug_line_data, uint32_t* offset_ptr, LineTable* line_table)
851{
852 return ParseStatementTable(debug_line_data, offset_ptr, ParseStatementTableCallback, line_table);
853}
854
855
856inline bool
857DWARFDebugLine::Prologue::IsValid() const
858{
859 return SymbolFileDWARF::SupportedVersion(version);
860}
861
862//----------------------------------------------------------------------
863// DWARFDebugLine::Prologue::Dump
864//----------------------------------------------------------------------
865void
866DWARFDebugLine::Prologue::Dump(Log *log)
867{
868 uint32_t i;
869
870 log->Printf( "Line table prologue:");
871 log->Printf( " total_length: 0x%8.8x", total_length);
872 log->Printf( " version: %u", version);
873 log->Printf( "prologue_length: 0x%8.8x", prologue_length);
874 log->Printf( "min_inst_length: %u", min_inst_length);
875 log->Printf( "default_is_stmt: %u", default_is_stmt);
876 log->Printf( " line_base: %i", line_base);
877 log->Printf( " line_range: %u", line_range);
878 log->Printf( " opcode_base: %u", opcode_base);
879
880 for (i=0; i<standard_opcode_lengths.size(); ++i)
881 {
882 log->Printf( "standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i+1), standard_opcode_lengths[i]);
883 }
884
885 if (!include_directories.empty())
886 {
887 for (i=0; i<include_directories.size(); ++i)
888 {
889 log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str());
890 }
891 }
892
893 if (!file_names.empty())
894 {
895 log->PutCString (" Dir Mod Time File Len File Name");
896 log->PutCString (" ---- ---------- ---------- ---------------------------");
897 for (i=0; i<file_names.size(); ++i)
898 {
899 const FileNameEntry& fileEntry = file_names[i];
900 log->Printf ("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s",
901 i+1,
902 fileEntry.dir_idx,
903 fileEntry.mod_time,
904 fileEntry.length,
905 fileEntry.name.c_str());
906 }
907 }
908}
909
910
911//----------------------------------------------------------------------
912// DWARFDebugLine::ParsePrologue::Append
913//
914// Append the contents of the prologue to the binary stream buffer
915//----------------------------------------------------------------------
916//void
917//DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const
918//{
919// uint32_t i;
920//
921// buff.Append32(total_length);
922// buff.Append16(version);
923// buff.Append32(prologue_length);
924// buff.Append8(min_inst_length);
925// buff.Append8(default_is_stmt);
926// buff.Append8(line_base);
927// buff.Append8(line_range);
928// buff.Append8(opcode_base);
929//
930// for (i=0; i<standard_opcode_lengths.size(); ++i)
931// buff.Append8(standard_opcode_lengths[i]);
932//
933// for (i=0; i<include_directories.size(); ++i)
934// buff.AppendCStr(include_directories[i].c_str());
935// buff.Append8(0); // Terminate the include directory section with empty string
936//
937// for (i=0; i<file_names.size(); ++i)
938// {
939// buff.AppendCStr(file_names[i].name.c_str());
940// buff.Append32_as_ULEB128(file_names[i].dir_idx);
941// buff.Append32_as_ULEB128(file_names[i].mod_time);
942// buff.Append32_as_ULEB128(file_names[i].length);
943// }
944// buff.Append8(0); // Terminate the file names section with empty string
945//}
946
947
948bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const
949{
950 uint32_t idx = file_idx - 1; // File indexes are 1 based...
951 if (idx < file_names.size())
952 {
953 path = file_names[idx].name;
954 uint32_t dir_idx = file_names[idx].dir_idx - 1;
955 if (dir_idx < include_directories.size())
956 directory = include_directories[dir_idx];
957 else
958 directory.clear();
959 return true;
960 }
961 return false;
962}
963
964//----------------------------------------------------------------------
965// DWARFDebugLine::LineTable::Dump
966//----------------------------------------------------------------------
967void
968DWARFDebugLine::LineTable::Dump(Log *log) const
969{
970 if (prologue.get())
971 prologue->Dump (log);
972
973 if (!rows.empty())
974 {
975 log->PutCString ("Address Line Column File ISA Flags");
976 log->PutCString ("------------------ ------ ------ ------ --- -------------");
977 Row::const_iterator pos = rows.begin();
978 Row::const_iterator end = rows.end();
979 while (pos != end)
980 {
981 (*pos).Dump (log);
982 ++pos;
983 }
984 }
985}
986
987
988void
989DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row& state)
990{
991 rows.push_back(state);
992}
993
994
995
996//----------------------------------------------------------------------
997// Compare function for the binary search in DWARFDebugLine::LineTable::LookupAddress()
998//----------------------------------------------------------------------
999static bool FindMatchingAddress (const DWARFDebugLine::Row& row1, const DWARFDebugLine::Row& row2)
1000{
1001 return row1.address < row2.address;
1002}
1003
1004
1005//----------------------------------------------------------------------
1006// DWARFDebugLine::LineTable::LookupAddress
1007//----------------------------------------------------------------------
1008uint32_t
1009DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const
1010{
1011 uint32_t index = UINT_MAX;
1012 if (!rows.empty())
1013 {
1014 // Use the lower_bound algorithm to perform a binary search since we know
1015 // that our line table data is ordered by address.
1016 DWARFDebugLine::Row row;
1017 row.address = address;
1018 Row::const_iterator begin_pos = rows.begin();
1019 Row::const_iterator end_pos = rows.end();
1020 Row::const_iterator pos = lower_bound(begin_pos, end_pos, row, FindMatchingAddress);
1021 if (pos == end_pos)
1022 {
1023 if (address < cu_high_pc)
1024 return rows.size()-1;
1025 }
1026 else
1027 {
1028 // Rely on fact that we are using a std::vector and we can do
1029 // pointer arithmetic to find the row index (which will be one less
1030 // that what we found since it will find the first position after
1031 // the current address) since std::vector iterators are just
1032 // pointers to the container type.
1033 index = pos - begin_pos;
1034 if (pos->address > address)
1035 {
1036 if (index > 0)
1037 --index;
1038 else
1039 index = UINT_MAX;
1040 }
1041 }
1042 }
1043 return index; // Failed to find address
1044}
1045
1046
1047//----------------------------------------------------------------------
1048// DWARFDebugLine::Row::Row
1049//----------------------------------------------------------------------
1050DWARFDebugLine::Row::Row(bool default_is_stmt) :
1051 address(0),
1052 line(1),
1053 column(0),
1054 file(1),
1055 is_stmt(default_is_stmt),
1056 basic_block(false),
1057 end_sequence(false),
1058 prologue_end(false),
1059 epilogue_begin(false),
1060 isa(0)
1061{
1062}
1063
1064//----------------------------------------------------------------------
1065// Called after a row is appended to the matrix
1066//----------------------------------------------------------------------
1067void
1068DWARFDebugLine::Row::PostAppend()
1069{
1070 basic_block = false;
1071 prologue_end = false;
1072 epilogue_begin = false;
1073}
1074
1075
1076//----------------------------------------------------------------------
1077// DWARFDebugLine::Row::Reset
1078//----------------------------------------------------------------------
1079void
1080DWARFDebugLine::Row::Reset(bool default_is_stmt)
1081{
1082 address = 0;
1083 line = 1;
1084 column = 0;
1085 file = 1;
1086 is_stmt = default_is_stmt;
1087 basic_block = false;
1088 end_sequence = false;
1089 prologue_end = false;
1090 epilogue_begin = false;
1091 isa = 0;
1092}
1093//----------------------------------------------------------------------
1094// DWARFDebugLine::Row::Dump
1095//----------------------------------------------------------------------
1096void
1097DWARFDebugLine::Row::Dump(Log *log) const
1098{
1099 log->Printf( "0x%16.16llx %6u %6u %6u %3u %s%s%s%s%s",
1100 address,
1101 line,
1102 column,
1103 file,
1104 isa,
1105 is_stmt ? " is_stmt" : "",
1106 basic_block ? " basic_block" : "",
1107 prologue_end ? " prologue_end" : "",
1108 epilogue_begin ? " epilogue_begin" : "",
1109 end_sequence ? " end_sequence" : "");
1110}
1111
1112//----------------------------------------------------------------------
1113// Compare function LineTable structures
1114//----------------------------------------------------------------------
1115static bool AddressLessThan (const DWARFDebugLine::Row& a, const DWARFDebugLine::Row& b)
1116{
1117 return a.address < b.address;
1118}
1119
1120
1121
1122// Insert a row at the correct address if the addresses can be out of
1123// order which can only happen when we are linking a line table that
1124// may have had it's contents rearranged.
1125void
1126DWARFDebugLine::Row::Insert(Row::collection& state_coll, const Row& state)
1127{
1128 // If we don't have anything yet, or if the address of the last state in our
1129 // line table is less than the current one, just append the current state
1130 if (state_coll.empty() || AddressLessThan(state_coll.back(), state))
1131 {
1132 state_coll.push_back(state);
1133 }
1134 else
1135 {
1136 // Do a binary search for the correct entry
1137 pair<Row::iterator, Row::iterator> range(equal_range(state_coll.begin(), state_coll.end(), state, AddressLessThan));
1138
1139 // If the addresses are equal, we can safely replace the previous entry
1140 // with the current one if the one it is replacing is an end_sequence entry.
1141 // We currently always place an extra end sequence when ever we exit a valid
1142 // address range for a function in case the functions get rearranged by
1143 // optmimizations or by order specifications. These extra end sequences will
1144 // disappear by getting replaced with valid consecutive entries within a
1145 // compile unit if there are no gaps.
1146 if (range.first == range.second)
1147 {
1148 state_coll.insert(range.first, state);
1149 }
1150 else
1151 {
1152 if ((distance(range.first, range.second) == 1) && range.first->end_sequence == true)
1153 {
1154 *range.first = state;
1155 }
1156 else
1157 {
1158 state_coll.insert(range.second, state);
1159 }
1160 }
1161 }
1162}
1163
1164void
1165DWARFDebugLine::Row::Dump(Log *log, const Row::collection& state_coll)
1166{
1167 std::for_each (state_coll.begin(), state_coll.end(), bind2nd(std::mem_fun_ref(&Row::Dump),log));
1168}
1169
1170
1171//----------------------------------------------------------------------
1172// DWARFDebugLine::State::State
1173//----------------------------------------------------------------------
1174DWARFDebugLine::State::State(Prologue::shared_ptr& p, Log *l, DWARFDebugLine::State::Callback cb, void* userData) :
1175 Row (p->default_is_stmt),
1176 prologue (p),
1177 log (l),
1178 callback (cb),
1179 callbackUserData (userData),
1180 row (StartParsingLineTable)
1181{
1182 // Call the callback with the initial row state of zero for the prologue
1183 if (callback)
1184 callback(0, *this, callbackUserData);
1185}
1186
1187//----------------------------------------------------------------------
1188// DWARFDebugLine::State::Reset
1189//----------------------------------------------------------------------
1190void
1191DWARFDebugLine::State::Reset()
1192{
1193 Row::Reset(prologue->default_is_stmt);
1194}
1195
1196//----------------------------------------------------------------------
1197// DWARFDebugLine::State::AppendRowToMatrix
1198//----------------------------------------------------------------------
1199void
1200DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset)
1201{
1202 // Each time we are to add an entry into the line table matrix
1203 // call the callback funtion so that someone can do something with
1204 // the current state of the state machine (like build a line table
1205 // or dump the line table!)
1206 if (log)
1207 {
1208 if (row == 0)
1209 {
1210 log->PutCString ("Address Line Column File ISA Flags");
1211 log->PutCString ("------------------ ------ ------ ------ --- -------------");
1212 }
1213 Dump (log);
1214 }
1215
1216 ++row; // Increase the row number before we call our callback for a real row
1217 if (callback)
1218 callback(offset, *this, callbackUserData);
1219 PostAppend();
1220}
1221
1222//----------------------------------------------------------------------
1223// DWARFDebugLine::State::Finalize
1224//----------------------------------------------------------------------
1225void
1226DWARFDebugLine::State::Finalize(dw_offset_t offset)
1227{
1228 // Call the callback with a special row state when we are done parsing a
1229 // line table
1230 row = DoneParsingLineTable;
1231 if (callback)
1232 callback(offset, *this, callbackUserData);
1233}
1234
1235//void
1236//DWARFDebugLine::AppendLineTableData
1237//(
1238// const DWARFDebugLine::Prologue* prologue,
1239// const DWARFDebugLine::Row::collection& state_coll,
1240// const uint32_t addr_size,
1241// BinaryStreamBuf &debug_line_data
1242//)
1243//{
1244// if (state_coll.empty())
1245// {
1246// // We have no entries, just make an empty line table
1247// debug_line_data.Append8(0);
1248// debug_line_data.Append8(1);
1249// debug_line_data.Append8(DW_LNE_end_sequence);
1250// }
1251// else
1252// {
1253// DWARFDebugLine::Row::const_iterator pos;
1254// Row::const_iterator end = state_coll.end();
1255// bool default_is_stmt = prologue->default_is_stmt;
1256// const DWARFDebugLine::Row reset_state(default_is_stmt);
1257// const DWARFDebugLine::Row* prev_state = &reset_state;
1258// const int32_t max_line_increment_for_special_opcode = prologue->MaxLineIncrementForSpecialOpcode();
1259// for (pos = state_coll.begin(); pos != end; ++pos)
1260// {
1261// const DWARFDebugLine::Row& curr_state = *pos;
1262// int32_t line_increment = 0;
1263// dw_addr_t addr_offset = curr_state.address - prev_state->address;
1264// dw_addr_t addr_advance = (addr_offset) / prologue->min_inst_length;
1265// line_increment = (int32_t)(curr_state.line - prev_state->line);
1266//
1267// // If our previous state was the reset state, then let's emit the
1268// // address to keep GDB's DWARF parser happy. If we don't start each
1269// // sequence with a DW_LNE_set_address opcode, the line table won't
1270// // get slid properly in GDB.
1271//
1272// if (prev_state == &reset_state)
1273// {
1274// debug_line_data.Append8(0); // Extended opcode
1275// debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of opcode bytes
1276// debug_line_data.Append8(DW_LNE_set_address);
1277// debug_line_data.AppendMax64(curr_state.address, addr_size);
1278// addr_advance = 0;
1279// }
1280//
1281// if (prev_state->file != curr_state.file)
1282// {
1283// debug_line_data.Append8(DW_LNS_set_file);
1284// debug_line_data.Append32_as_ULEB128(curr_state.file);
1285// }
1286//
1287// if (prev_state->column != curr_state.column)
1288// {
1289// debug_line_data.Append8(DW_LNS_set_column);
1290// debug_line_data.Append32_as_ULEB128(curr_state.column);
1291// }
1292//
1293// // Don't do anything fancy if we are at the end of a sequence
1294// // as we don't want to push any extra rows since the DW_LNE_end_sequence
1295// // will push a row itself!
1296// if (curr_state.end_sequence)
1297// {
1298// if (line_increment != 0)
1299// {
1300// debug_line_data.Append8(DW_LNS_advance_line);
1301// debug_line_data.Append32_as_SLEB128(line_increment);
1302// }
1303//
1304// if (addr_advance > 0)
1305// {
1306// debug_line_data.Append8(DW_LNS_advance_pc);
1307// debug_line_data.Append32_as_ULEB128(addr_advance);
1308// }
1309//
1310// // Now push the end sequence on!
1311// debug_line_data.Append8(0);
1312// debug_line_data.Append8(1);
1313// debug_line_data.Append8(DW_LNE_end_sequence);
1314//
1315// prev_state = &reset_state;
1316// }
1317// else
1318// {
1319// if (line_increment || addr_advance)
1320// {
1321// if (line_increment > max_line_increment_for_special_opcode)
1322// {
1323// debug_line_data.Append8(DW_LNS_advance_line);
1324// debug_line_data.Append32_as_SLEB128(line_increment);
1325// line_increment = 0;
1326// }
1327//
1328// uint32_t special_opcode = (line_increment >= prologue->line_base) ? ((line_increment - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
1329// if (special_opcode > 255)
1330// {
1331// // Both the address and line won't fit in one special opcode
1332// // check to see if just the line advance will?
1333// uint32_t special_opcode_line = ((line_increment >= prologue->line_base) && (line_increment != 0)) ?
1334// ((line_increment - prologue->line_base) + prologue->opcode_base) : 256;
1335//
1336//
1337// if (special_opcode_line > 255)
1338// {
1339// // Nope, the line advance won't fit by itself, check the address increment by itself
1340// uint32_t special_opcode_addr = addr_advance ?
1341// ((0 - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
1342//
1343// if (special_opcode_addr > 255)
1344// {
1345// // Neither the address nor the line will fit in a
1346// // special opcode, we must manually enter both then
1347// // do a DW_LNS_copy to push a row (special opcode
1348// // automatically imply a new row is pushed)
1349// if (line_increment != 0)
1350// {
1351// debug_line_data.Append8(DW_LNS_advance_line);
1352// debug_line_data.Append32_as_SLEB128(line_increment);
1353// }
1354//
1355// if (addr_advance > 0)
1356// {
1357// debug_line_data.Append8(DW_LNS_advance_pc);
1358// debug_line_data.Append32_as_ULEB128(addr_advance);
1359// }
1360//
1361// // Now push a row onto the line table manually
1362// debug_line_data.Append8(DW_LNS_copy);
1363//
1364// }
1365// else
1366// {
1367// // The address increment alone will fit into a special opcode
1368// // so modify our line change, then issue a special opcode
1369// // for the address increment and it will push a row into the
1370// // line table
1371// if (line_increment != 0)
1372// {
1373// debug_line_data.Append8(DW_LNS_advance_line);
1374// debug_line_data.Append32_as_SLEB128(line_increment);
1375// }
1376//
1377// // Advance of line and address will fit into a single byte special opcode
1378// // and this will also push a row onto the line table
1379// debug_line_data.Append8(special_opcode_addr);
1380// }
1381// }
1382// else
1383// {
1384// // The line change alone will fit into a special opcode
1385// // so modify our address increment first, then issue a
1386// // special opcode for the line change and it will push
1387// // a row into the line table
1388// if (addr_advance > 0)
1389// {
1390// debug_line_data.Append8(DW_LNS_advance_pc);
1391// debug_line_data.Append32_as_ULEB128(addr_advance);
1392// }
1393//
1394// // Advance of line and address will fit into a single byte special opcode
1395// // and this will also push a row onto the line table
1396// debug_line_data.Append8(special_opcode_line);
1397// }
1398// }
1399// else
1400// {
1401// // Advance of line and address will fit into a single byte special opcode
1402// // and this will also push a row onto the line table
1403// debug_line_data.Append8(special_opcode);
1404// }
1405// }
1406// prev_state = &curr_state;
1407// }
1408// }
1409// }
1410//}