forked from OSchip/llvm-project
				
			Add a verbose mode to "image dump line-table" and use it to write a .debug_line test
Summary: The motivation for this is being able to write tests for the upcoming breakpad line table parser, but this could be useful for testing the low-level workings of any line table format. Or simply for viewing the line table information with more detail (the brief format doesn't include any of the flags for end_of_prologue and similar). I've also removed the load_addresses argument from the DumpCompileUnitLineTable function, as it wasn't being used anywhere. Reviewers: clayborg, zturner Subscribers: JDevlieghere, lldb-commits Differential Revision: https://reviews.llvm.org/D56315 llvm-svn: 350802
This commit is contained in:
		
							parent
							
								
									7208221452
								
							
						
					
					
						commit
						1c69ab2860
					
				| 
						 | 
					@ -0,0 +1,75 @@
 | 
				
			||||||
 | 
					# REQUIRES: lld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
 | 
				
			||||||
 | 
					# RUN: ld.lld %t.o -o %t
 | 
				
			||||||
 | 
					# RUN: %lldb %t -o "image dump line-table -v a.c" -o exit | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.text
 | 
				
			||||||
 | 
						.globl	_start
 | 
				
			||||||
 | 
					_start:
 | 
				
			||||||
 | 
					# CHECK: Line table for /tmp/a.c
 | 
				
			||||||
 | 
						.file	1 "/tmp/b.c"
 | 
				
			||||||
 | 
						.loc	1 0 0
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201000: /tmp/b.c, is_start_of_statement = TRUE{{$}}
 | 
				
			||||||
 | 
						.loc	1 1 0
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201001: /tmp/b.c:1, is_start_of_statement = TRUE{{$}}
 | 
				
			||||||
 | 
					        .loc   1 1 1
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201002: /tmp/b.c:1:1, is_start_of_statement = TRUE{{$}}
 | 
				
			||||||
 | 
					        .loc   1 2 0 is_stmt 0
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201003: /tmp/b.c:2{{$}}
 | 
				
			||||||
 | 
					        .loc   1 2 0 is_stmt 0 basic_block
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201004: /tmp/b.c:2, is_start_of_basic_block = TRUE{{$}}
 | 
				
			||||||
 | 
					        .loc   1 2 0 is_stmt 0 prologue_end
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201005: /tmp/b.c:2, is_prologue_end = TRUE{{$}}
 | 
				
			||||||
 | 
					        .loc   1 2 0 is_stmt 0 epilogue_begin
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201006: /tmp/b.c:2, is_epilogue_begin = TRUE{{$}}
 | 
				
			||||||
 | 
						.file  2 "/tmp/c.c"
 | 
				
			||||||
 | 
						.loc   2 1 0 is_stmt 0
 | 
				
			||||||
 | 
					        nop
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201007: /tmp/c.c:1{{$}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK-NEXT: 0x0000000000201008: /tmp/c.c:1, is_terminal_entry = TRUE{{$}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.section	.debug_str,"MS",@progbits,1
 | 
				
			||||||
 | 
					.Linfo_string1:
 | 
				
			||||||
 | 
						.asciz	"a.c"
 | 
				
			||||||
 | 
					.Linfo_string2:
 | 
				
			||||||
 | 
						.asciz	"/tmp"
 | 
				
			||||||
 | 
						.section	.debug_abbrev,"",@progbits
 | 
				
			||||||
 | 
						.byte	1                       # Abbreviation Code
 | 
				
			||||||
 | 
						.byte	17                      # DW_TAG_compile_unit
 | 
				
			||||||
 | 
						.byte	0                       # DW_CHILDREN_no
 | 
				
			||||||
 | 
						.byte	19                      # DW_AT_language
 | 
				
			||||||
 | 
						.byte	5                       # DW_FORM_data2
 | 
				
			||||||
 | 
						.byte	3                       # DW_AT_name
 | 
				
			||||||
 | 
						.byte	14                      # DW_FORM_strp
 | 
				
			||||||
 | 
						.byte	16                      # DW_AT_stmt_list
 | 
				
			||||||
 | 
						.byte	23                      # DW_FORM_sec_offset
 | 
				
			||||||
 | 
						.byte	27                      # DW_AT_comp_dir
 | 
				
			||||||
 | 
						.byte	14                      # DW_FORM_strp
 | 
				
			||||||
 | 
						.byte	0                       # EOM(1)
 | 
				
			||||||
 | 
						.byte	0                       # EOM(2)
 | 
				
			||||||
 | 
						.byte	0                       # EOM(3)
 | 
				
			||||||
 | 
						.section	.debug_info,"",@progbits
 | 
				
			||||||
 | 
					.Lcu_begin0:
 | 
				
			||||||
 | 
						.long	.Lcu_end0-.Lcu_start0   # Length of Unit
 | 
				
			||||||
 | 
					.Lcu_start0:
 | 
				
			||||||
 | 
						.short	4                       # DWARF version number
 | 
				
			||||||
 | 
						.long	.debug_abbrev           # Offset Into Abbrev. Section
 | 
				
			||||||
 | 
						.byte	8                       # Address Size (in bytes)
 | 
				
			||||||
 | 
						.byte	1                       # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
 | 
				
			||||||
 | 
						.short	12                      # DW_AT_language
 | 
				
			||||||
 | 
						.long	.Linfo_string1          # DW_AT_name
 | 
				
			||||||
 | 
						.long	.Lline_table_start0     # DW_AT_stmt_list
 | 
				
			||||||
 | 
						.long	.Linfo_string2          # DW_AT_comp_dir
 | 
				
			||||||
 | 
					.Lcu_end0:
 | 
				
			||||||
 | 
						.section	.debug_line,"",@progbits
 | 
				
			||||||
 | 
					.Lline_table_start0:
 | 
				
			||||||
| 
						 | 
					@ -1348,7 +1348,7 @@ static void DumpModuleUUID(Stream &strm, Module *module) {
 | 
				
			||||||
static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
 | 
					static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
 | 
				
			||||||
                                         Stream &strm, Module *module,
 | 
					                                         Stream &strm, Module *module,
 | 
				
			||||||
                                         const FileSpec &file_spec,
 | 
					                                         const FileSpec &file_spec,
 | 
				
			||||||
                                         bool load_addresses) {
 | 
					                                         lldb::DescriptionLevel desc_level) {
 | 
				
			||||||
  uint32_t num_matches = 0;
 | 
					  uint32_t num_matches = 0;
 | 
				
			||||||
  if (module) {
 | 
					  if (module) {
 | 
				
			||||||
    SymbolContextList sc_list;
 | 
					    SymbolContextList sc_list;
 | 
				
			||||||
| 
						 | 
					@ -1367,7 +1367,7 @@ static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
 | 
				
			||||||
        if (line_table)
 | 
					        if (line_table)
 | 
				
			||||||
          line_table->GetDescription(
 | 
					          line_table->GetDescription(
 | 
				
			||||||
              &strm, interpreter.GetExecutionContext().GetTargetPtr(),
 | 
					              &strm, interpreter.GetExecutionContext().GetTargetPtr(),
 | 
				
			||||||
              lldb::eDescriptionLevelBrief);
 | 
					              desc_level);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          strm << "No line table";
 | 
					          strm << "No line table";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -2411,6 +2411,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ~CommandObjectTargetModulesDumpLineTable() override = default;
 | 
					  ~CommandObjectTargetModulesDumpLineTable() override = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Options *GetOptions() override { return &m_options; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
  bool DoExecute(Args &command, CommandReturnObject &result) override {
 | 
					  bool DoExecute(Args &command, CommandReturnObject &result) override {
 | 
				
			||||||
    Target *target = m_exe_ctx.GetTargetPtr();
 | 
					    Target *target = m_exe_ctx.GetTargetPtr();
 | 
				
			||||||
| 
						 | 
					@ -2443,8 +2445,9 @@ protected:
 | 
				
			||||||
            if (DumpCompileUnitLineTable(
 | 
					            if (DumpCompileUnitLineTable(
 | 
				
			||||||
                    m_interpreter, result.GetOutputStream(),
 | 
					                    m_interpreter, result.GetOutputStream(),
 | 
				
			||||||
                    target_modules.GetModulePointerAtIndexUnlocked(i),
 | 
					                    target_modules.GetModulePointerAtIndexUnlocked(i),
 | 
				
			||||||
                    file_spec, m_exe_ctx.GetProcessPtr() &&
 | 
					                    file_spec,
 | 
				
			||||||
                                   m_exe_ctx.GetProcessRef().IsAlive()))
 | 
					                    m_options.m_verbose ? eDescriptionLevelFull
 | 
				
			||||||
 | 
					                                        : eDescriptionLevelBrief))
 | 
				
			||||||
              num_dumped++;
 | 
					              num_dumped++;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          if (num_dumped == 0)
 | 
					          if (num_dumped == 0)
 | 
				
			||||||
| 
						 | 
					@ -2464,6 +2467,43 @@ protected:
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return result.Succeeded();
 | 
					    return result.Succeeded();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  class CommandOptions : public Options {
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    CommandOptions() : Options() { OptionParsingStarting(nullptr); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
 | 
				
			||||||
 | 
					                          ExecutionContext *execution_context) override {
 | 
				
			||||||
 | 
					      assert(option_idx == 0 && "We only have one option.");
 | 
				
			||||||
 | 
					      m_verbose = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return Status();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void OptionParsingStarting(ExecutionContext *execution_context) override {
 | 
				
			||||||
 | 
					      m_verbose = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
 | 
				
			||||||
 | 
					      static constexpr OptionDefinition g_options[] = {
 | 
				
			||||||
 | 
					          {LLDB_OPT_SET_ALL,
 | 
				
			||||||
 | 
					           false,
 | 
				
			||||||
 | 
					           "verbose",
 | 
				
			||||||
 | 
					           'v',
 | 
				
			||||||
 | 
					           OptionParser::eNoArgument,
 | 
				
			||||||
 | 
					           nullptr,
 | 
				
			||||||
 | 
					           {},
 | 
				
			||||||
 | 
					           0,
 | 
				
			||||||
 | 
					           eArgTypeNone,
 | 
				
			||||||
 | 
					           "Enable verbose dump."},
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      return llvm::makeArrayRef(g_options);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool m_verbose;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  CommandOptions m_options;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma mark CommandObjectTargetModulesDump
 | 
					#pragma mark CommandObjectTargetModulesDump
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue