mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-01-02 04:34:47 +01:00
When initializing the LineReader, the size passed should be the sizeof the dwarf4 line program. Change-Id: I67e6fa404d4fa8851e4958013a35a061fe169156 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2585345 Reviewed-by: Sterling Augustine <saugustine@google.com>
187 lines
6.8 KiB
C++
187 lines
6.8 KiB
C++
// 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(dwarf4_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
|