15a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe/* 25a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * Copyright (C) 2014 The Android Open Source Project 35a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * 45a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 55a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * you may not use this file except in compliance with the License. 65a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * You may obtain a copy of the License at 75a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * 85a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 95a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * 105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * Unless required by applicable law or agreed to in writing, software 115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * See the License for the specific language governing permissions and 145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe * limitations under the License. 155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe */ 165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#ifndef ART_COMPILER_UTILS_ASSEMBLER_TEST_H_ 185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#define ART_COMPILER_UTILS_ASSEMBLER_TEST_H_ 195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include "assembler.h" 215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 22b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe#include "common_runtime_test.h" // For ScratchFile 235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <cstdio> 255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <cstdlib> 265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <fstream> 275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <iostream> 285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <iterator> 295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#include <sys/stat.h> 305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampenamespace art { 325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 33b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe// Use a glocal static variable to keep the same name for all test data. Else we'll just spam the 34b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe// temp directory. 35b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampestatic std::string tmpnam_; 36b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe 375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampetemplate<typename Ass, typename Reg, typename Imm> 385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampeclass AssemblerTest : public testing::Test { 395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe public: 405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Ass* GetAssembler() { 415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return assembler_.get(); 425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe typedef std::string (*TestFn)(Ass* assembler); 455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe void DriverFn(TestFn f, std::string test_name) { 475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Driver(f(assembler_.get()), test_name); 485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // This driver assumes the assembler has already been called. 515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe void DriverStr(std::string assembly_string, std::string test_name) { 525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Driver(assembly_string, test_name); 535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string RepeatR(void (Ass::*f)(Reg), std::string fmt) { 565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe const std::vector<Reg*> registers = GetRegisters(); 575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string str; 585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (auto reg : registers) { 595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe (assembler_.get()->*f)(*reg); 605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string base = fmt; 615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t reg_index = base.find("{reg}"); 635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (reg_index != std::string::npos) { 645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << *reg; 665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string reg_string = sreg.str(); 675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(reg_index, 5, reg_string); 685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (str.size() > 0) { 715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += base; 745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Add a newline at the end. 765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return str; 785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string RepeatRR(void (Ass::*f)(Reg, Reg), std::string fmt) { 815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe const std::vector<Reg*> registers = GetRegisters(); 825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string str; 835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (auto reg1 : registers) { 845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (auto reg2 : registers) { 855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe (assembler_.get()->*f)(*reg1, *reg2); 865a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string base = fmt; 875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t reg1_index = base.find("{reg1}"); 895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (reg1_index != std::string::npos) { 905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << *reg1; 925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string reg_string = sreg.str(); 935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(reg1_index, 6, reg_string); 945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t reg2_index = base.find("{reg2}"); 975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (reg2_index != std::string::npos) { 985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << *reg2; 1005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string reg_string = sreg.str(); 1015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(reg2_index, 6, reg_string); 1025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (str.size() > 0) { 1055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += base; 1085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Add a newline at the end. 1115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return str; 1135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, std::string fmt) { 1165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe const std::vector<Reg*> registers = GetRegisters(); 1175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string str; 1185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<int64_t> imms = CreateImmediateValues(imm_bytes); 1195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (auto reg : registers) { 1205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (int64_t imm : imms) { 1215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Imm* new_imm = CreateImmediate(imm); 1225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe (assembler_.get()->*f)(*reg, *new_imm); 1235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe delete new_imm; 1245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string base = fmt; 1255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t reg_index = base.find("{reg}"); 1275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (reg_index != std::string::npos) { 1285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 1295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << *reg; 1305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string reg_string = sreg.str(); 1315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(reg_index, 5, reg_string); 1325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t imm_index = base.find("{imm}"); 1355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_index != std::string::npos) { 1365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 1375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << imm; 1385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string imm_string = sreg.str(); 1395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(imm_index, 5, imm_string); 1405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (str.size() > 0) { 1435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += base; 1465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Add a newline at the end. 1495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return str; 1515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string RepeatI(void (Ass::*f)(const Imm&), size_t imm_bytes, std::string fmt) { 1545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string str; 1555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<int64_t> imms = CreateImmediateValues(imm_bytes); 1565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe for (int64_t imm : imms) { 1575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Imm* new_imm = CreateImmediate(imm); 1585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe (assembler_.get()->*f)(*new_imm); 1595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe delete new_imm; 1605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string base = fmt; 1615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t imm_index = base.find("{imm}"); 1635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_index != std::string::npos) { 1645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ostringstream sreg; 1655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe sreg << imm; 1665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string imm_string = sreg.str(); 1675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe base.replace(imm_index, 5, imm_string); 1685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (str.size() > 0) { 1715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += base; 1745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Add a newline at the end. 1765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe str += "\n"; 1775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return str; 1785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // This is intended to be run as a test. 1815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool CheckTools() { 1825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!FileExists(GetAssemblerCommand())) { 1835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 1845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "Chosen assembler command: " << GetAssemblerCommand(); 1865a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!FileExists(GetObjdumpCommand())) { 1885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 1895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "Chosen objdump command: " << GetObjdumpCommand(); 1915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 1925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Disassembly is optional. 1935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string disassembler = GetDisassembleCommand(); 1945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (disassembler.length() != 0) { 1955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!FileExists(disassembler)) { 1965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 1975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 1985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "Chosen disassemble command: " << GetDisassembleCommand(); 1995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 2005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "No disassembler given."; 2015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return true; 2045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe protected: 2075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe void SetUp() OVERRIDE { 2085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe assembler_.reset(new Ass()); 2095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 210b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe // Fake a runtime test for ScratchFile 211f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe CommonRuntimeTest::SetUpAndroidData(android_data_); 212b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe 2135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe SetUpHelpers(); 2145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 216f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe void TearDown() OVERRIDE { 217f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe // We leave temporaries in case this failed so we can debug issues. 218f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe CommonRuntimeTest::TearDownAndroidData(android_data_, false); 219f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe tmpnam_ = ""; 220f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe } 221f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe 2225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Override this to set up any architecture-specific things, e.g., register vectors. 2235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual void SetUpHelpers() {} 2245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::vector<Reg*> GetRegisters() = 0; 2265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Get the typically used name for this architecture, e.g., aarch64, x86_64, ... 2285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetArchitectureString() = 0; 2295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Get the name of the assembler, e.g., "as" by default. 2315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetAssemblerCmdName() { 2325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return "as"; 2335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Switches to the assembler command. Default none. 2365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetAssemblerParameters() { 2375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return ""; 2385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Return the host assembler command for this test. 2415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetAssemblerCommand() { 2425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Already resolved it once? 2435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (resolved_assembler_cmd_.length() != 0) { 2445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return resolved_assembler_cmd_; 2455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string line = FindTool(GetAssemblerCmdName()); 2485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (line.length() == 0) { 2495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 2505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe resolved_assembler_cmd_ = line + GetAssemblerParameters(); 2535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 2555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Get the name of the objdump, e.g., "objdump" by default. 2585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetObjdumpCmdName() { 2595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return "objdump"; 2605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Switches to the objdump command. Default is " -h". 2635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetObjdumpParameters() { 2645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return " -h"; 2655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Return the host objdump command for this test. 2685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetObjdumpCommand() { 2695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Already resolved it once? 2705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (resolved_objdump_cmd_.length() != 0) { 2715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return resolved_objdump_cmd_; 2725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string line = FindTool(GetObjdumpCmdName()); 2755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (line.length() == 0) { 2765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 2775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe resolved_objdump_cmd_ = line + GetObjdumpParameters(); 2805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 2825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Get the name of the objdump, e.g., "objdump" by default. 2855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetDisassembleCmdName() { 2865a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return "objdump"; 2875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Switches to the objdump command. As it's a binary, one needs to push the architecture and 2905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // such to objdump, so it's architecture-specific and there is no default. 2915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetDisassembleParameters() = 0; 2925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 2935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Return the host disassembler command for this test. 2945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::string GetDisassembleCommand() { 2955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Already resolved it once? 2965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (resolved_disassemble_cmd_.length() != 0) { 2975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return resolved_disassemble_cmd_; 2985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 2995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string line = FindTool(GetDisassembleCmdName()); 3015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (line.length() == 0) { 3025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 3035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe resolved_disassemble_cmd_ = line + GetDisassembleParameters(); 3065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 3085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Create a couple of immediate values up to the number of bytes given. 3115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes) { 3125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<int64_t> res; 3135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0); 3145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(-1); 3155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0x12); 3165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_bytes >= 2) { 3175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0x1234); 3185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(-0x1234); 3195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_bytes >= 4) { 3205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0x12345678); 3215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(-0x12345678); 3225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_bytes >= 6) { 3235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0x123456789ABC); 3245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(-0x123456789ABC); 3255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (imm_bytes >= 8) { 3265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(0x123456789ABCDEF0); 3275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res.push_back(-0x123456789ABCDEF0); 3285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return res; 3335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Create an immediate from the specific value. 3365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe virtual Imm* CreateImmediate(int64_t imm_value) = 0; 3375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe private: 3395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Driver() assembles and compares the results. If the results are not equal and we have a 3405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // disassembler, disassemble both and check whether they have the same mnemonics (in which case 3415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // we just warn). 3425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe void Driver(std::string assembly_text, std::string test_name) { 3435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_NE(assembly_text.length(), 0U) << "Empty assembly"; 3445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe NativeAssemblerResult res; 3465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Compile(assembly_text, &res, test_name); 3475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_TRUE(res.ok) << res.error_msg; 3495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!res.ok) { 3505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // No way of continuing. 3515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return; 3525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t cs = assembler_->CodeSize(); 355700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs)); 3565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe MemoryRegion code(&(*data)[0], data->size()); 3575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe assembler_->FinalizeInstructions(code); 3585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (*data == *res.code) { 3605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe Clean(&res); 3615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 3625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (DisassembleBinaries(*data, *res.code, test_name)) { 3635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (data->size() > res.code->size()) { 364f0d30ed8fcffc839ceb91359a547c0efb7641d53Andreas Gampe // Fail this test with a fancy colored warning being printed. 365f0d30ed8fcffc839ceb91359a547c0efb7641d53Andreas Gampe EXPECT_TRUE(false) << "Assembly code is not identical, but disassembly of machine code " 366f0d30ed8fcffc839ceb91359a547c0efb7641d53Andreas Gampe "is equal: this implies sub-optimal encoding! Our code size=" << data->size() << 3675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe ", gcc size=" << res.code->size(); 3685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 369f0d30ed8fcffc839ceb91359a547c0efb7641d53Andreas Gampe // Otherwise just print an info message and clean up. 3705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "GCC chose a different encoding than ours, but the overall length is the " 3715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe "same."; 372f0d30ed8fcffc839ceb91359a547c0efb7641d53Andreas Gampe Clean(&res); 3735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 3755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // This will output the assembly. 3765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_EQ(*data, *res.code) << "Outputs (and disassembly) not identical."; 3775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Structure to store intermediates and results. 3825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe struct NativeAssemblerResult { 3835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool ok; 3845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string error_msg; 3855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string base_name; 386700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<std::vector<uint8_t>> code; 3875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe uintptr_t length; 3885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe }; 3895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Compile the assembly file from_file to a binary file to_file. Returns true on success. 3915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool Assemble(const char* from_file, const char* to_file, std::string* error_msg) { 3925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool have_assembler = FileExists(GetAssemblerCommand()); 3935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_TRUE(have_assembler) << "Cannot find assembler:" << GetAssemblerCommand(); 3945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!have_assembler) { 3955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 3965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 3975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 3985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<std::string> args; 3995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(GetAssemblerCommand()); 4015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-o"); 4025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(to_file); 4035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(from_file); 4045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return Exec(args, error_msg); 4065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Runs objdump -h on the binary file and extracts the first line with .text. 4095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Returns "" on failure. 4105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string Objdump(std::string file) { 4115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool have_objdump = FileExists(GetObjdumpCommand()); 4125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_TRUE(have_objdump) << "Cannot find objdump: " << GetObjdumpCommand(); 4135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!have_objdump) { 4145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return ""; 4155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string error_msg; 4185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<std::string> args; 4195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(GetObjdumpCommand()); 4215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(file); 4225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(">"); 4235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(file+".dump"); 4245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string cmd = Join(args, ' '); 4255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.clear(); 4275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("/bin/sh"); 4285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-c"); 4295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(cmd); 4305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!Exec(args, &error_msg)) { 4325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_TRUE(false) << error_msg; 4335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream dump(file+".dump"); 4365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string line; 4385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool found = false; 4395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe while (std::getline(dump, line)) { 4405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (line.find(".text") != line.npos) { 4415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe found = true; 4425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe break; 4435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe dump.close(); 4475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (found) { 4495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 4505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 4515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return ""; 4525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Disassemble both binaries and compare the text. 4565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool DisassembleBinaries(std::vector<uint8_t>& data, std::vector<uint8_t>& as, 4575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string test_name) { 4585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string disassembler = GetDisassembleCommand(); 4595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (disassembler.length() == 0) { 4605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(WARNING) << "No dissassembler command."; 4615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 4625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string data_name = WriteToFile(data, test_name + ".ass"); 4655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string error_msg; 4665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!DisassembleBinary(data_name, &error_msg)) { 4675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "Error disassembling: " << error_msg; 4685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(data_name.c_str()); 4695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 4705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string as_name = WriteToFile(as, test_name + ".gcc"); 4735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!DisassembleBinary(as_name, &error_msg)) { 4745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe LOG(INFO) << "Error disassembling: " << error_msg; 4755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(data_name.c_str()); 4765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((data_name + ".dis").c_str()); 4775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(as_name.c_str()); 4785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 4795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool result = CompareFiles(data_name + ".dis", as_name + ".dis"); 4825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (result) { 4845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(data_name.c_str()); 4855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(as_name.c_str()); 4865a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((data_name + ".dis").c_str()); 4875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((as_name + ".dis").c_str()); 4885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return result; 4915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 4925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool DisassembleBinary(std::string file, std::string* error_msg) { 4945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<std::string> args; 4955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 4965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(GetDisassembleCommand()); 4975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(file); 4985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("| sed -n \'/<.data>/,$p\' | sed -e \'s/.*://\'"); 4995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(">"); 5005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(file+".dis"); 5015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string cmd = Join(args, ' '); 5025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.clear(); 5045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("/bin/sh"); 5055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-c"); 5065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(cmd); 5075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return Exec(args, error_msg); 5095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string WriteToFile(std::vector<uint8_t>& buffer, std::string test_name) { 5125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string file_name = GetTmpnam() + std::string("---") + test_name; 5135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe const char* data = reinterpret_cast<char*>(buffer.data()); 5145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ofstream s_out(file_name + ".o"); 5155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe s_out.write(data, buffer.size()); 5165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe s_out.close(); 5175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return file_name + ".o"; 5185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool CompareFiles(std::string f1, std::string f2) { 5215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream f1_in(f1); 5225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream f2_in(f2); 5235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool result = std::equal(std::istreambuf_iterator<char>(f1_in), 5255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istreambuf_iterator<char>(), 5265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istreambuf_iterator<char>(f2_in)); 5275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe f1_in.close(); 5295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe f2_in.close(); 5305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return result; 5325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Compile the given assembly code and extract the binary, if possible. Put result into res. 5355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe bool Compile(std::string assembly_code, NativeAssemblerResult* res, std::string test_name) { 5365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->ok = false; 5375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->code.reset(nullptr); 5385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->base_name = GetTmpnam() + std::string("---") + test_name; 5405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // TODO: Lots of error checking. 5425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ofstream s_out(res->base_name + ".S"); 5445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe s_out << assembly_code; 5455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe s_out.close(); 5465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!Assemble((res->base_name + ".S").c_str(), (res->base_name + ".o").c_str(), 5485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe &res->error_msg)) { 5495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->error_msg = "Could not compile."; 5505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 5515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string odump = Objdump(res->base_name + ".o"); 5545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (odump.length() == 0) { 5555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->error_msg = "Objdump failed."; 5565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 5575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istringstream iss(odump); 5605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istream_iterator<std::string> start(iss); 5615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istream_iterator<std::string> end; 5625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<std::string> tokens(start, end); 5635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (tokens.size() < OBJDUMP_SECTION_LINE_MIN_TOKENS) { 5655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->error_msg = "Objdump output not recognized: too few tokens."; 5665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 5675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (tokens[1] != ".text") { 5705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->error_msg = "Objdump output not recognized: .text not second token."; 5715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 5725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string lengthToken = "0x" + tokens[2]; 5755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istringstream(lengthToken) >> std::hex >> res->length; 5765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string offsetToken = "0x" + tokens[5]; 5785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe uintptr_t offset; 5795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::istringstream(offsetToken) >> std::hex >> offset; 5805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream obj(res->base_name + ".o"); 5825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe obj.seekg(offset); 5835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->code.reset(new std::vector<uint8_t>(res->length)); 5845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe obj.read(reinterpret_cast<char*>(&(*res->code)[0]), res->length); 5855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe obj.close(); 5865a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5875a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe res->ok = true; 5885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return true; 5895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Remove temporary files. 5925a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe void Clean(const NativeAssemblerResult* res) { 5935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((res->base_name + ".S").c_str()); 5945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((res->base_name + ".o").c_str()); 5955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove((res->base_name + ".o.dump").c_str()); 5965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 5975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 5985a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Check whether file exists. Is used for commands, so strips off any parameters: anything after 5995a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // the first space. We skip to the last slash for this, so it should work with directories with 6005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // spaces. 6015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe static bool FileExists(std::string file) { 6025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (file.length() == 0) { 6035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return false; 6045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6065a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Need to strip any options. 6075a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t last_slash = file.find_last_of('/'); 6085a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (last_slash == std::string::npos) { 6095a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // No slash, start looking at the start. 6105a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe last_slash = 0; 6115a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6125a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe size_t space_index = file.find(' ', last_slash); 6135a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6145a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (space_index == std::string::npos) { 6155a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream infile(file.c_str()); 6165a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return infile.good(); 6175a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } else { 6185a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string copy = file.substr(0, space_index - 1); 6195a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6205a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe struct stat buf; 6215a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return stat(copy.c_str(), &buf) == 0; 6225a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6235a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6245a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6255a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe static std::string GetGCCRootPath() { 6265a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return "prebuilts/gcc/linux-x86"; 6275a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6285a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6295a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe static std::string GetRootPath() { 6305a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // 1) Check ANDROID_BUILD_TOP 6315a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe char* build_top = getenv("ANDROID_BUILD_TOP"); 6325a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (build_top != nullptr) { 6335a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return std::string(build_top) + "/"; 6345a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6355a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6365a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // 2) Do cwd 6375a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe char temp[1024]; 6385a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return getcwd(temp, 1024) ? std::string(temp) + "/" : std::string(""); 6395a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6405a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6415a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string FindTool(std::string tool_name) { 6425a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Find the current tool. Wild-card pattern is "arch-string*tool-name". 6435a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string gcc_path = GetRootPath() + GetGCCRootPath(); 6445a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::vector<std::string> args; 6455a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("find"); 6465a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(gcc_path); 6475a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-name"); 6485a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(GetArchitectureString() + "*" + tool_name); 6495a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("|"); 6505a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("sort"); 6515a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("|"); 6525a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("tail"); 6535a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-n"); 6545a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("1"); 6555a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string tmp_file = GetTmpnam(); 6565a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(">"); 6575a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(tmp_file); 6585a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string sh_args = Join(args, ' '); 6595a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6605a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.clear(); 6615a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("/bin/sh"); 6625a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back("-c"); 6635a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe args.push_back(sh_args); 6645a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6655a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string error_msg; 6665a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!Exec(args, &error_msg)) { 6675a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe EXPECT_TRUE(false) << error_msg; 6685a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return ""; 6695a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6705a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6715a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::ifstream in(tmp_file.c_str()); 6725a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string line; 6735a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (!std::getline(in, line)) { 6745a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe in.close(); 6755a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(tmp_file.c_str()); 6765a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return ""; 6775a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6785a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe in.close(); 6795a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::remove(tmp_file.c_str()); 6805a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return line; 6815a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6825a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6835a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe // Use a consistent tmpnam, so store it. 6845a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string GetTmpnam() { 6855a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe if (tmpnam_.length() == 0) { 686b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe ScratchFile tmp; 687b40c6a768aa8df4774d2a8c3ac7045237cc748cdAndreas Gampe tmpnam_ = tmp.GetFilename() + "asm"; 6885a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6895a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe return tmpnam_; 6905a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe } 6915a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 692700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<Ass> assembler_; 6935a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 6945a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string resolved_assembler_cmd_; 6955a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string resolved_objdump_cmd_; 6965a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe std::string resolved_disassemble_cmd_; 6975a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 698f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe std::string android_data_; 699f896965072343a2d6ad64d46a61112b10b3645ddAndreas Gampe 7005a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe static constexpr size_t OBJDUMP_SECTION_LINE_MIN_TOKENS = 6; 7015a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe}; 7025a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 7035a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe} // namespace art 7045a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe 7055a4fa82ab42af6e728a60e3261963aa243c3e2cdAndreas Gampe#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_ 706