115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky/* 215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Copyright (C) 2015 The Android Open Source Project 315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Licensed under the Apache License, Version 2.0 (the "License"); 515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * you may not use this file except in compliance with the License. 615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * You may obtain a copy of the License at 715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * http://www.apache.org/licenses/LICENSE-2.0 915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * 1015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * Unless required by applicable law or agreed to in writing, software 1115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * distributed under the License is distributed on an "AS IS" BASIS, 1215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * See the License for the specific language governing permissions and 1415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky * limitations under the License. 1515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky */ 1615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 174fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#ifndef ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 184fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#define ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 1915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 2015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <cstring> 2115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <dirent.h> 2215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <memory> 2315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <set> 2415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <stdio.h> 2515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <string> 2615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include <sys/types.h> 2715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 2815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include "base/unix_file/fd_file.h" 2915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include "common_runtime_test.h" 3015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include "elf_builder.h" 3115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include "gtest/gtest.h" 32131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/file_output_stream.h" 3315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#include "os.h" 3415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 3515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckynamespace art { 3615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckynamespace dwarf { 3715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 3815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__) 3915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky#define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__) 4015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 4115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbeckyclass DwarfTest : public CommonRuntimeTest { 4215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky public: 4315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky static constexpr bool kPrintObjdumpOutput = false; // debugging. 4415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 4515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky struct ExpectedLine { 4615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::string substring; 4715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky bool next; 4815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky const char* at_file; 4915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky int at_line; 5015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky }; 5115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 5215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Check that the objdump output contains given output. 5315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // If next is true, it must be the next line. Otherwise lines are skipped. 5415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky void Check(const char* substr, bool next, const char* at_file, int at_line) { 5515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky expected_lines_.push_back(ExpectedLine {substr, next, at_file, at_line}); 5615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 5715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 5815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Pretty-print the generated DWARF data using objdump. 59533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky template<typename ElfTypes> 60bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky std::vector<std::string> Objdump(const char* args) { 6115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Write simple elf file with just the DWARF sections. 62bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky InstructionSet isa = (sizeof(typename ElfTypes::Addr) == 8) ? kX86_64 : kX86; 636d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky ScratchFile file; 646d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky FileOutputStream output_stream(file.GetFile()); 655d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky ElfBuilder<ElfTypes> builder(isa, nullptr, &output_stream); 666d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.Start(); 6715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (!debug_info_data_.empty()) { 686d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.WriteSection(".debug_info", &debug_info_data_); 6915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 7015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (!debug_abbrev_data_.empty()) { 716d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.WriteSection(".debug_abbrev", &debug_abbrev_data_); 7215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 7315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (!debug_str_data_.empty()) { 746d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.WriteSection(".debug_str", &debug_str_data_); 7515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 7615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (!debug_line_data_.empty()) { 776d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.WriteSection(".debug_line", &debug_line_data_); 7815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 79ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky if (!debug_frame_data_.empty()) { 806d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.WriteSection(".debug_frame", &debug_frame_data_); 8115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 826d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky builder.End(); 836d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky EXPECT_TRUE(builder.Good()); 8415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 8515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Read the elf file back using objdump. 8615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<std::string> lines; 873e52aa4d406fe802dabee2a2e7ba8764cc13aaaaDavid Srbecky std::string cmd = GetAndroidHostToolsDir(); 883e52aa4d406fe802dabee2a2e7ba8764cc13aaaaDavid Srbecky cmd = cmd + "objdump " + args + " " + file.GetFilename() + " 2>&1"; 8915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky FILE* output = popen(cmd.data(), "r"); 9015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky char buffer[1024]; 9115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky const char* line; 9215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky while ((line = fgets(buffer, sizeof(buffer), output)) != nullptr) { 9315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (kPrintObjdumpOutput) { 9415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky printf("%s", line); 9515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 9615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (line[0] != '\0' && line[0] != '\n') { 9715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky EXPECT_TRUE(strstr(line, "objdump: Error:") == nullptr) << line; 9815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky EXPECT_TRUE(strstr(line, "objdump: Warning:") == nullptr) << line; 9915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::string str(line); 10015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (str.back() == '\n') { 10115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky str.pop_back(); 10215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky lines.push_back(str); 10415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky pclose(output); 10715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky return lines; 10815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 10915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 11015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<std::string> Objdump(bool is64bit, const char* args) { 11115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (is64bit) { 112bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky return Objdump<ElfTypes64>(args); 11315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 114bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky return Objdump<ElfTypes32>(args); 11515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 11615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 11715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 11815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Compare objdump output to the recorded checks. 11915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky void CheckObjdumpOutput(bool is64bit, const char* args) { 12015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<std::string> actual_lines = Objdump(is64bit, args); 12115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky auto actual_line = actual_lines.begin(); 12215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky for (const ExpectedLine& expected_line : expected_lines_) { 12315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky const std::string& substring = expected_line.substring; 12415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (actual_line == actual_lines.end()) { 12515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << 12615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Expected '" << substring << "'.\n" << 12715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Seen end of output."; 12815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else if (expected_line.next) { 12915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (actual_line->find(substring) == std::string::npos) { 13015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << 13115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Expected '" << substring << "'.\n" << 13215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Seen '" << actual_line->data() << "'."; 13315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 13415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data()); 13515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 13615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky actual_line++; 13715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 13815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky bool found = false; 13915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky for (auto it = actual_line; it < actual_lines.end(); it++) { 14015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (it->find(substring) != std::string::npos) { 14115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky actual_line = it; 14215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky found = true; 14315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky break; 14415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 14515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 14615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky if (!found) { 14715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << 14815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Expected '" << substring << "'.\n" << 14915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky "Not found anywhere in the rest of the output."; 15015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } else { 15115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data()); 15215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky actual_line++; 15315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 15415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 15515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 15615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky } 15715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 15815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // Buffers which are going to assembled into ELF file and passed to objdump. 159ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky std::vector<uint8_t> debug_frame_data_; 16015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<uint8_t> debug_info_data_; 16115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<uint8_t> debug_abbrev_data_; 16215c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<uint8_t> debug_str_data_; 16315c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<uint8_t> debug_line_data_; 16415c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 16515c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky // The expected output of objdump. 16615c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky std::vector<ExpectedLine> expected_lines_; 16715c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky}; 16815c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 16915c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky} // namespace dwarf 17015c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky} // namespace art 17115c1975f5fa5ae646ae87b57394bfdae1090a236David Srbecky 1724fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#endif // ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_ 173