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