blob: 191b351c8669b0e5f6de38ad2c96ca838d69ac71 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SIMPLE_PERF_JIT_DEBUG_READER_H_
#define SIMPLE_PERF_JIT_DEBUG_READER_H_
#include <unistd.h>
#include <functional>
#include <memory>
#include <stack>
#include <unordered_set>
#include <vector>
#include <android-base/logging.h>
#include <android-base/test_utils.h>
namespace simpleperf {
struct JITSymFile {
uint64_t addr; // The start addr of the JITed code
uint64_t len; // The length of the JITed code
std::string file_path; // The path of a temporary ELF file storing debug info of the JITed code
};
struct DexSymFile {
uint64_t dex_file_offset; // The offset of the dex file in the file containing it
std::string file_path; // The path of file containing the dex file
};
class JITDebugReader {
public:
JITDebugReader(pid_t pid, bool keep_symfiles);
pid_t Pid() const {
return pid_;
}
void ReadUpdate(std::vector<JITSymFile>* new_jit_symfiles,
std::vector<DexSymFile>* new_dex_symfiles);
private:
// An arch-independent representation of JIT/dex debug descriptor.
struct Descriptor {
uint32_t action_seqlock = 0; // incremented before and after any modification
uint64_t action_timestamp = 0; // CLOCK_MONOTONIC time of last action
uint64_t first_entry_addr = 0;
};
// An arch-independent representation of JIT/dex code entry.
struct CodeEntry {
uint64_t addr;
uint64_t symfile_addr;
uint64_t symfile_size;
uint64_t timestamp; // CLOCK_MONOTONIC time of last action
};
bool TryInit();
bool ReadRemoteMem(uint64_t remote_addr, uint64_t size, void* data);
bool ReadDescriptors(Descriptor* jit_descriptor, Descriptor* dex_descriptor);
bool LoadDescriptor(const char* data, Descriptor* descriptor);
template <typename DescriptorT>
bool LoadDescriptorImpl(const char* data, Descriptor* descriptor);
bool ReadNewCodeEntries(const Descriptor& descriptor, uint64_t last_action_timestamp,
std::vector<CodeEntry>* new_code_entries);
template <typename DescriptorT, typename CodeEntryT>
bool ReadNewCodeEntriesImpl(const Descriptor& descriptor, uint64_t last_action_timestamp,
std::vector<CodeEntry>* new_code_entries);
void ReadJITSymFiles(const std::vector<CodeEntry>& jit_entries,
std::vector<JITSymFile>* jit_symfiles);
void ReadDexSymFiles(const std::vector<CodeEntry>& dex_entries,
std::vector<DexSymFile>* dex_symfiles);
pid_t pid_;
bool keep_symfiles_;
bool initialized_;
bool is_64bit_;
// The jit descriptor and dex descriptor can be read in one process_vm_readv() call.
uint64_t descriptors_addr_;
uint64_t descriptors_size_;
std::vector<char> descriptors_buf_;
// offset relative to descriptors_addr
uint64_t jit_descriptor_offset_;
// offset relative to descriptors_addr
uint64_t dex_descriptor_offset_;
// The state we know about the remote jit debug descriptor.
Descriptor last_jit_descriptor_;
// The state we know about the remote dex debug descriptor.
Descriptor last_dex_descriptor_;
};
} //namespace simpleperf
#endif // SIMPLE_PERF_JIT_DEBUG_READER_H_