xref: /aosp_15_r20/external/google-breakpad/src/common/dwarf/dwarf2reader_lineinfo_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2020 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 // Original author: Sterling Augustine <[email protected]>
30 
31 // dwarf2reader_lineinfo_unittest.cc: Unit tests for google_breakpad::LineInfo
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>  // Must come first
35 #endif
36 
37 #include <stdint.h>
38 #include <stdlib.h>
39 
40 #include <string>
41 #include <vector>
42 
43 #include "breakpad_googletest_includes.h"
44 #include "common/dwarf/bytereader.h"
45 #include "common/dwarf/dwarf2reader.h"
46 #include "google_breakpad/common/breakpad_types.h"
47 
48 using std::vector;
49 using testing::InSequence;
50 using testing::Return;
51 using testing::Sequence;
52 using testing::Test;
53 using testing::_;
54 
55 using namespace google_breakpad;
56 
57 namespace {
58 
59 const uint8_t dwarf5_line_program[] = {
60   0x40, 0x0, 0x0, 0x0,  // unit_length (end - begin)
61   // begin
62   0x05, 0x0,  // version
63   0x8,  // address_size
64   0x0,  // segment_selector_size
65   0x26, 0x0, 0x0, 0x0, // header_length (end_header_end - begin_header)
66   // begin_header:
67   0x1,  // minimum_instruction_length
68   0x1,  // maximum_operations_per_instruction
69   0x1,  // default_is_stmt
70   0xfb, // line_base
71   0xe,  // line_range
72   0xd,  // opcode_base and lengths
73   0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
74   0x1,  // directory entry format count
75   DW_LNCT_path, DW_FORM_strp,
76   0x1,  // directories count
77   0x1, 0x0, 0x0, 0x0, // offset into .debug_line_str
78   0x2,  // file_name_entry_format_count
79   DW_LNCT_directory_index, DW_FORM_data1,
80   DW_LNCT_path, DW_FORM_line_strp,
81   0x1,  // filename count
82   0x0,  // directory index
83   0x1, 0x0, 0x0, 0x0, // offset into .debug_str
84   // end_header
85   DW_LNS_set_file, 0x0,
86   //  set address to 0x0
87   0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
88   // Advance Address by 0 and line by 3
89   0x15,
90   // Advance PC by 1
91   0x2, 0x1,
92   0x0,
93   DW_LNE_end_sequence,
94   DW_LNE_end_sequence,
95   // end
96 };
97 
98 const uint8_t dwarf4_line_program[] = {
99   0x37, 0x0, 0x0, 0x0,  // unit_length (end - begin)
100   // begin
101   0x04, 0x0,  // version
102   0x1d, 0x0, 0x0, 0x0, // header_length (end_header - begin_header)
103   // begin_header:
104   0x1,  // minimum_instruction_length
105   0x1,  // maximum_operations_per_instruction
106   0x1,  // default_is_stmt
107   0xfb, // line_base
108   0xe,  // line_range
109   0xd,  // opcode_base and lengths
110   0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1,
111   '/', 'a', '\0',  // directory entry 1 (zeroth entry implied)
112   '\0', // end of directory table
113   'b', '/', 'c', '\0',  // file entry 1 (zeroth entry implied)
114   0, // file 1 directory
115   0, // file 1 modification time
116   0, // file 1 length
117   '\0', // end of file table
118   // end_header
119   DW_LNS_set_file, 0x0,
120   //  set address to 0x0
121   0x0, 0x9, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
122   // Advance Address by 0 and line by 3
123   0x15,
124   // Advance PC by 1
125   0x2, 0x1,
126   0x0,
127   DW_LNE_end_sequence,
128   DW_LNE_end_sequence,
129   // end
130 };
131 
132 class MockLineInfoHandler: public LineInfoHandler {
133  public:
134   MOCK_METHOD(void, DefineDir, (const string&, uint32_t dir_num), (override));
135   MOCK_METHOD(void, DefineFile, (const string& name, int32_t file_num,
136                                  uint32_t dir_num, uint64_t mod_time,
137                                  uint64_t length), (override));
138   MOCK_METHOD(void, AddLine, (uint64_t address, uint64_t length,
139                               uint32_t file_num, uint32_t line_num,
140                               uint32_t column_num), (override));
141 };
142 
143 const uint8_t string_section[] = {'x', '/', 'a', '\0'};
144 const uint8_t line_string_section[] = {'x', 'b', '/', 'c', '\0' };
145 
146 struct LineProgram: public Test {
147   MockLineInfoHandler handler_;
148 };
149 
TEST_F(LineProgram,ReadLinesDwarf5)150 TEST_F(LineProgram, ReadLinesDwarf5) {
151   ByteReader byte_reader(ENDIANNESS_LITTLE);
152   // LineTables don't specify the offset size like Compilation Units do.
153   byte_reader.SetOffsetSize(4);
154   LineInfo line_reader(dwarf5_line_program,
155                        sizeof(dwarf5_line_program),
156                        &byte_reader,
157                        string_section,
158                        sizeof(string_section),
159                        line_string_section,
160                        sizeof(line_string_section),
161                        &handler_);
162   EXPECT_CALL(handler_, DefineDir("/a", 0)).Times(1);
163   EXPECT_CALL(handler_, DefineFile("b/c", 0, 0, 0, 0)).Times(1);
164   EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
165   EXPECT_EQ(line_reader.Start(), sizeof(dwarf5_line_program));
166 }
167 
TEST_F(LineProgram,ReadLinesDwarf4)168 TEST_F(LineProgram, ReadLinesDwarf4) {
169   ByteReader byte_reader(ENDIANNESS_LITTLE);
170   // LineTables don't specify the offset size like Compilation Units do.
171   byte_reader.SetOffsetSize(4);
172   // dwarf4 line info headers don't encode the address size.
173   byte_reader.SetAddressSize(8);
174   LineInfo line_reader(dwarf4_line_program,
175                        sizeof(dwarf4_line_program),
176                        &byte_reader,
177                        // dwarf4 line tables can't access the string sections
178                        // so pass values likely to make assertions fail if
179                        // the code uses them improperly.
180                        nullptr, 0, nullptr, 0,
181                        &handler_);
182   EXPECT_CALL(handler_, DefineDir("", 0)).Times(1);
183   EXPECT_CALL(handler_, DefineDir("/a", 1)).Times(1);
184   EXPECT_CALL(handler_, DefineFile("", 0, 0, 0, 0)).Times(1);
185   EXPECT_CALL(handler_, DefineFile("b/c", 1, 0, 0, 0)).Times(1);
186   EXPECT_CALL(handler_, AddLine(0, 1, 0, 4, 0)).Times(1);
187   EXPECT_EQ(line_reader.Start(), sizeof(dwarf4_line_program));
188 }
189 
190 }  // anonymous namespace
191