aboutsummaryrefslogtreecommitdiff
path: root/src/common/dwarf/dwarf2reader_lineinfo_unittest.cc
blob: 99fc1a0756ec15ffb3210777db682f9656481d46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Copyright (c) 2020, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Original author: Sterling Augustine <saugustine@google.com>

// dwarf2reader_lineinfo_unittest.cc: Unit tests for dwarf2reader::LineInfo

#include <stdint.h>
#include <stdlib.h>

#include <string>
#include <vector>

#include "breakpad_googletest_includes.h"
#include "common/dwarf/bytereader.h"
#include "common/dwarf/dwarf2reader.h"
#include "google_breakpad/common/breakpad_types.h"

using std::vector;
using testing::InSequence;
using testing::Return;
using testing::Sequence;
using testing::Test;
using testing::_;

using namespace dwarf2reader;

namespace {

const uint8_t dwarf5_line_program[] = {
  0x40, 0x0, 0x0, 0x0,  // unit_length (end - begin)
  // begin
  0x05, 0x0,  // version
  0x8,  // address_size
  0x0,  // segment_selector_size
  0x26, 0x0, 0x0, 0x0, // header_length (end_header_end - begin_header)
  // begin_header:
  0x1,  // minimum_instruction_length
  0x1,  // maximum_operations_per_instruction
  0x1,  // default_is_stmt
  0xfb, // line_base
  0xe,  // line_range
  0xd,  // opcode_base and lengths
  0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
  0x1,  // directory entry format count
  DW_LNCT_path, DW_FORM_strp,
  0x1,  // directories count
  0x1, 0x0, 0x0, 0x0, // offset into .debug_line_str
  0x2,  // file_name_entry_format_count
  DW_LNCT_directory_index, DW_FORM_data1,
  DW_LNCT_path, DW_FORM_line_strp,
  0x1,  // filename count
  0x0,  // directory index
  0x1, 0x0, 0x0, 0x0, // offset into .debug_str
  // end_header
  DW_LNS_set_file, 0x0,
  //  set address to 0x0
  0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  // Advance Address by 0 and line by 3
  0x15,
  // Advance PC by 1
  0x2, 0x1,
  0x0,
  DW_LNE_end_sequence,
  DW_LNE_end_sequence,
  // end
};

const uint8_t dwarf4_line_program[] = {
  0x37, 0x0, 0x0, 0x0,  // unit_length (end - begin)
  // begin
  0x04, 0x0,  // version
  0x1d, 0x0, 0x0, 0x0, // header_length (end_header - begin_header)
  // begin_header:
  0x1,  // minimum_instruction_length
  0x1,  // maximum_operations_per_instruction
  0x1,  // default_is_stmt
  0xfb, // line_base
  0xe,  // line_range
  0xd,  // opcode_base and lengths
  0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
  '/', 'a', '\0',  // directory entry 1 (zeroth entry implied)
  '\0', // end of directory table
  'b', '/', 'c', '\0',  // file entry 1 (zeroth entry implied)
  0, // file 1 directory
  0, // file 1 modification time
  0, // file 1 length
  '\0', // end of file table
  // end_header
  DW_LNS_set_file, 0x0,
  //  set address to 0x0
  0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
  // Advance Address by 0 and line by 3
  0x15,
  // Advance PC by 1
  0x2, 0x1,
  0x0,
  DW_LNE_end_sequence,
  DW_LNE_end_sequence,
  // end
};

class MockLineInfoHandler: public LineInfoHandler {
 public:
  MOCK_METHOD(void, DefineDir, (const string&, uint32_t dir_num), (override));
  MOCK_METHOD(void, DefineFile, (const string& name, int32_t file_num,
                                 uint32_t dir_num, uint64_t mod_time,
                                 uint64_t length), (override));
  MOCK_METHOD(void, AddLine, (uint64_t address, uint64_t length,
                              uint32_t file_num, uint32_t line_num,
                              uint32_t column_num), (override));
};

const uint8_t string_section[] = {'x', '/', 'a', '\0'};
const uint8_t line_string_section[] = {'x', 'b', '/', 'c', '\0' };

struct LineProgram: public Test {
  MockLineInfoHandler handler_;
};

TEST_F(LineProgram, ReadLinesDwarf5) {
  ByteReader byte_reader(ENDIANNESS_LITTLE);
  // LineTables don't specify the offset size like Compilation Units do.
  byte_reader.SetOffsetSize(4);
  LineInfo line_reader(dwarf5_line_program,
                       sizeof(dwarf5_line_program),
                       &byte_reader,
                       string_section,
                       sizeof(string_section),
                       line_string_section,
                       sizeof(line_string_section),
                       &handler_);
  EXPECT_CALL(handler_, DefineDir("/a", 0)).Times(1);
  EXPECT_CALL(handler_, DefineFile("b/c", 0, 0, 0, 0)).Times(1);
  EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
  EXPECT_EQ(line_reader.Start(), sizeof(dwarf5_line_program));
}

TEST_F(LineProgram, ReadLinesDwarf4) {
  ByteReader byte_reader(ENDIANNESS_LITTLE);
  // LineTables don't specify the offset size like Compilation Units do.
  byte_reader.SetOffsetSize(4);
  // dwarf4 line info headers don't encode the address size.
  byte_reader.SetAddressSize(8);
  LineInfo line_reader(dwarf4_line_program,
                       sizeof(dwarf5_line_program),
                       &byte_reader,
                       // dwarf4 line tables can't access the string sections
                       // so pass values likely to make assertions fail if
                       // the code uses them improperly.
                       nullptr, 0, nullptr, 0,
                       &handler_);
  EXPECT_CALL(handler_, DefineDir("", 0)).Times(1);
  EXPECT_CALL(handler_, DefineDir("/a", 1)).Times(1);
  EXPECT_CALL(handler_, DefineFile("", 0, 0, 0, 0)).Times(1);
  EXPECT_CALL(handler_, DefineFile("b/c", 1, 0, 0, 0)).Times(1);
  EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
  EXPECT_EQ(line_reader.Start(), sizeof(dwarf4_line_program));
}

}  // anonymous namespace