1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <dirent.h> 21*795d594fSAndroid Build Coastguard Worker #include <stdio.h> 22*795d594fSAndroid Build Coastguard Worker #include <sys/types.h> 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker #include <cstring> 25*795d594fSAndroid Build Coastguard Worker #include <memory> 26*795d594fSAndroid Build Coastguard Worker #include <set> 27*795d594fSAndroid Build Coastguard Worker #include <string> 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 30*795d594fSAndroid Build Coastguard Worker #include "base/os.h" 31*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h" 32*795d594fSAndroid Build Coastguard Worker #include "common_compiler_test.h" 33*795d594fSAndroid Build Coastguard Worker #include "elf/elf_builder.h" 34*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h" 35*795d594fSAndroid Build Coastguard Worker #include "stream/file_output_stream.h" 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 38*795d594fSAndroid Build Coastguard Worker namespace dwarf { 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker #define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__) 41*795d594fSAndroid Build Coastguard Worker #define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__) 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker class DwarfTest : public CommonCompilerTest { 44*795d594fSAndroid Build Coastguard Worker public: 45*795d594fSAndroid Build Coastguard Worker static constexpr bool kPrintObjdumpOutput = false; // debugging. 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker struct ExpectedLine { 48*795d594fSAndroid Build Coastguard Worker std::string substring; 49*795d594fSAndroid Build Coastguard Worker bool next; 50*795d594fSAndroid Build Coastguard Worker const char* at_file; 51*795d594fSAndroid Build Coastguard Worker int at_line; 52*795d594fSAndroid Build Coastguard Worker }; 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // Check that the objdump output contains given output. 55*795d594fSAndroid Build Coastguard Worker // If next is true, it must be the next line. Otherwise lines are skipped. Check(const char * substr,bool next,const char * at_file,int at_line)56*795d594fSAndroid Build Coastguard Worker void Check(const char* substr, bool next, const char* at_file, int at_line) { 57*795d594fSAndroid Build Coastguard Worker expected_lines_.push_back(ExpectedLine {substr, next, at_file, at_line}); 58*795d594fSAndroid Build Coastguard Worker } 59*795d594fSAndroid Build Coastguard Worker 60*795d594fSAndroid Build Coastguard Worker // Pretty-print the generated DWARF data using objdump. 61*795d594fSAndroid Build Coastguard Worker template<typename ElfTypes> Objdump(const char * args)62*795d594fSAndroid Build Coastguard Worker std::vector<std::string> Objdump(const char* args) { 63*795d594fSAndroid Build Coastguard Worker // Write simple elf file with just the DWARF sections. 64*795d594fSAndroid Build Coastguard Worker InstructionSet isa = 65*795d594fSAndroid Build Coastguard Worker (sizeof(typename ElfTypes::Addr) == 8) ? InstructionSet::kX86_64 : InstructionSet::kX86; 66*795d594fSAndroid Build Coastguard Worker ScratchFile file; 67*795d594fSAndroid Build Coastguard Worker FileOutputStream output_stream(file.GetFile()); 68*795d594fSAndroid Build Coastguard Worker ElfBuilder<ElfTypes> builder(isa, &output_stream); 69*795d594fSAndroid Build Coastguard Worker builder.Start(); 70*795d594fSAndroid Build Coastguard Worker if (!debug_info_data_.empty()) { 71*795d594fSAndroid Build Coastguard Worker builder.WriteSection(".debug_info", &debug_info_data_); 72*795d594fSAndroid Build Coastguard Worker } 73*795d594fSAndroid Build Coastguard Worker if (!debug_abbrev_data_.empty()) { 74*795d594fSAndroid Build Coastguard Worker builder.WriteSection(".debug_abbrev", &debug_abbrev_data_); 75*795d594fSAndroid Build Coastguard Worker } 76*795d594fSAndroid Build Coastguard Worker if (!debug_str_data_.empty()) { 77*795d594fSAndroid Build Coastguard Worker builder.WriteSection(".debug_str", &debug_str_data_); 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker if (!debug_line_data_.empty()) { 80*795d594fSAndroid Build Coastguard Worker builder.WriteSection(".debug_line", &debug_line_data_); 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker if (!debug_frame_data_.empty()) { 83*795d594fSAndroid Build Coastguard Worker builder.WriteSection(".debug_frame", &debug_frame_data_); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker builder.End(); 86*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(builder.Good()); 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker // Read the elf file back using objdump. 89*795d594fSAndroid Build Coastguard Worker std::vector<std::string> lines; 90*795d594fSAndroid Build Coastguard Worker std::string cmd = GetAndroidTool("llvm-dwarfdump"); 91*795d594fSAndroid Build Coastguard Worker cmd = cmd + " " + args + " " + file.GetFilename() + " 2>&1"; 92*795d594fSAndroid Build Coastguard Worker FILE* output = popen(cmd.data(), "r"); 93*795d594fSAndroid Build Coastguard Worker char buffer[1024]; 94*795d594fSAndroid Build Coastguard Worker const char* line; 95*795d594fSAndroid Build Coastguard Worker while ((line = fgets(buffer, sizeof(buffer), output)) != nullptr) { 96*795d594fSAndroid Build Coastguard Worker if (kPrintObjdumpOutput) { 97*795d594fSAndroid Build Coastguard Worker printf("%s", line); 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker if (line[0] != '\0' && line[0] != '\n') { 100*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strstr(line, "error:") == nullptr) << line; 101*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(strstr(line, "warning:") == nullptr) << line; 102*795d594fSAndroid Build Coastguard Worker std::string str(line); 103*795d594fSAndroid Build Coastguard Worker if (str.back() == '\n') { 104*795d594fSAndroid Build Coastguard Worker str.pop_back(); 105*795d594fSAndroid Build Coastguard Worker } 106*795d594fSAndroid Build Coastguard Worker std::replace(str.begin(), str.end(), '\t', ' '); 107*795d594fSAndroid Build Coastguard Worker lines.push_back(str); 108*795d594fSAndroid Build Coastguard Worker } 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker pclose(output); 111*795d594fSAndroid Build Coastguard Worker return lines; 112*795d594fSAndroid Build Coastguard Worker } 113*795d594fSAndroid Build Coastguard Worker Objdump(bool is64bit,const char * args)114*795d594fSAndroid Build Coastguard Worker std::vector<std::string> Objdump(bool is64bit, const char* args) { 115*795d594fSAndroid Build Coastguard Worker if (is64bit) { 116*795d594fSAndroid Build Coastguard Worker return Objdump<ElfTypes64>(args); 117*795d594fSAndroid Build Coastguard Worker } else { 118*795d594fSAndroid Build Coastguard Worker return Objdump<ElfTypes32>(args); 119*795d594fSAndroid Build Coastguard Worker } 120*795d594fSAndroid Build Coastguard Worker } 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker // Compare objdump output to the recorded checks. CheckObjdumpOutput(bool is64bit,const char * args)123*795d594fSAndroid Build Coastguard Worker void CheckObjdumpOutput(bool is64bit, const char* args) { 124*795d594fSAndroid Build Coastguard Worker std::vector<std::string> actual_lines = Objdump(is64bit, args); 125*795d594fSAndroid Build Coastguard Worker auto actual_line = actual_lines.begin(); 126*795d594fSAndroid Build Coastguard Worker bool failed = false; 127*795d594fSAndroid Build Coastguard Worker for (const ExpectedLine& expected : expected_lines_) { 128*795d594fSAndroid Build Coastguard Worker const std::string& substring = expected.substring; 129*795d594fSAndroid Build Coastguard Worker auto it = std::find_if(actual_line, actual_lines.end(), 130*795d594fSAndroid Build Coastguard Worker [&](const std::string& line) { return line.find(substring) != std::string::npos; }); 131*795d594fSAndroid Build Coastguard Worker if (it == actual_lines.end()) { 132*795d594fSAndroid Build Coastguard Worker failed = true; 133*795d594fSAndroid Build Coastguard Worker ADD_FAILURE_AT(expected.at_file, expected.at_line) << "'" << substring << "' not found."; 134*795d594fSAndroid Build Coastguard Worker } else { 135*795d594fSAndroid Build Coastguard Worker if (expected.next && it != actual_line) { 136*795d594fSAndroid Build Coastguard Worker failed = true; 137*795d594fSAndroid Build Coastguard Worker ADD_FAILURE_AT(expected.at_file, expected.at_line) 138*795d594fSAndroid Build Coastguard Worker << "'" << substring << "' found, but not on the immediate next line as expected."; 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker actual_line = ++it; 141*795d594fSAndroid Build Coastguard Worker } 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker if (failed) { 144*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "objdump output:"; 145*795d594fSAndroid Build Coastguard Worker for (const std::string& it : actual_lines) { 146*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << it; 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker } 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker // Buffers which are going to assembled into ELF file and passed to objdump. 152*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> debug_frame_data_; 153*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> debug_info_data_; 154*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> debug_abbrev_data_; 155*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> debug_str_data_; 156*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> debug_line_data_; 157*795d594fSAndroid Build Coastguard Worker 158*795d594fSAndroid Build Coastguard Worker // The expected output of objdump. 159*795d594fSAndroid Build Coastguard Worker std::vector<ExpectedLine> expected_lines_; 160*795d594fSAndroid Build Coastguard Worker }; 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker } // namespace dwarf 163*795d594fSAndroid Build Coastguard Worker } // namespace art 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 166