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