| // Copyright 2017 The Crashpad Authors |
| // |
| // 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 CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_ |
| #define CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_ |
| |
| #include <sys/time.h> |
| #include <sys/types.h> |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "snapshot/elf/elf_image_reader.h" |
| #include "snapshot/module_snapshot.h" |
| #include "util/linux/address_types.h" |
| #include "util/linux/memory_map.h" |
| #include "util/linux/ptrace_connection.h" |
| #include "util/linux/thread_info.h" |
| #include "util/misc/initialization_state_dcheck.h" |
| #include "util/posix/process_info.h" |
| #include "util/process/process_memory.h" |
| |
| namespace crashpad { |
| |
| //! \brief Accesses information about another process, identified by a process |
| //! ID. |
| class ProcessReaderLinux { |
| public: |
| //! \brief Contains information about a thread that belongs to a process. |
| struct Thread { |
| Thread(); |
| ~Thread(); |
| |
| //! \brief Initializes the thread's stack using \a stack_pointer instead of |
| //! the stack pointer in \a thread_info. |
| //! |
| //! This method initializes \a stack_region_address and \a stack_region_size |
| //! overwriting any values they previously contained. This is useful, for |
| //! example, if the thread is currently in a signal handler context, which |
| //! may execute on a different stack than was used before the signal was |
| //! received. |
| //! |
| //! \param[in] reader A process reader for the target process. |
| //! \param[in] stack_pointer The stack pointer for the stack to initialize. |
| void InitializeStackFromSP(ProcessReaderLinux* reader, |
| LinuxVMAddress stack_pointer); |
| |
| ThreadInfo thread_info; |
| LinuxVMAddress stack_region_address; |
| LinuxVMSize stack_region_size; |
| std::string name; |
| pid_t tid; |
| int sched_policy; |
| int static_priority; |
| int nice_value; |
| |
| //! \brief `true` if `sched_policy`, `static_priority`, and `nice_value` are |
| //! all valid. |
| bool have_priorities; |
| |
| private: |
| friend class ProcessReaderLinux; |
| |
| bool InitializePtrace(PtraceConnection* connection); |
| void InitializeStack(ProcessReaderLinux* reader); |
| }; |
| |
| //! \brief Contains information about a module loaded into a process. |
| struct Module { |
| Module(); |
| ~Module(); |
| |
| //! \brief The pathname used to load the module from disk. |
| std::string name; |
| |
| //! \brief An image reader for the module. |
| //! |
| //! The lifetime of this ElfImageReader is scoped to the lifetime of the |
| //! ProcessReaderLinux that created it. |
| //! |
| //! This field may be `nullptr` if a reader could not be created for the |
| //! module. |
| ElfImageReader* elf_reader; |
| |
| //! \brief The module's type. |
| ModuleSnapshot::ModuleType type; |
| }; |
| |
| ProcessReaderLinux(); |
| |
| ProcessReaderLinux(const ProcessReaderLinux&) = delete; |
| ProcessReaderLinux& operator=(const ProcessReaderLinux&) = delete; |
| |
| ~ProcessReaderLinux(); |
| |
| //! \brief Initializes this object. |
| //! |
| //! This method must be successfully called before calling any other method in |
| //! this class and may only be called once. |
| //! |
| //! \param[in] connection A PtraceConnection to the target process. |
| //! \return `true` on success. `false` on failure with a message logged. |
| bool Initialize(PtraceConnection* connection); |
| |
| //! \brief Return `true` if the target task is a 64-bit process. |
| bool Is64Bit() const { return is_64_bit_; } |
| |
| //! \brief Return the target process' process ID. |
| pid_t ProcessID() const { return process_info_.ProcessID(); } |
| |
| //! \brief Return the target process' parent process ID. |
| pid_t ParentProcessID() const { return process_info_.ParentProcessID(); } |
| |
| //! \brief Return a memory reader for the target process. |
| const ProcessMemoryLinux* Memory() const { return connection_->Memory(); } |
| |
| //! \brief Return a memory map of the target process. |
| MemoryMap* GetMemoryMap() { return &memory_map_; } |
| |
| //! \brief Determines the target process’ start time. |
| //! |
| //! \param[out] start_time The time that the process started. |
| //! \return `true` on success with \a start_time set. Otherwise `false` with a |
| //! message logged. |
| bool StartTime(timeval* start_time) const; |
| |
| //! \brief Determines the target process’ execution time. |
| //! |
| //! \param[out] user_time The amount of time the process has executed code in |
| //! user mode. |
| //! \param[out] system_time The amount of time the process has executed code |
| //! in system mode. |
| //! |
| //! \return `true` on success, `false` on failure, with a warning logged. On |
| //! failure, \a user_time and \a system_time will be set to represent no |
| //! time spent executing code in user or system mode. |
| bool CPUTimes(timeval* user_time, timeval* system_time) const; |
| |
| //! \brief Return a vector of threads that are in the task process. If the |
| //! main thread is able to be identified and traced, it will be placed at |
| //! index `0`. |
| const std::vector<Thread>& Threads(); |
| |
| //! \return The modules loaded in the process. The first element (at index |
| //! `0`) corresponds to the main executable. |
| const std::vector<Module>& Modules(); |
| |
| //! \return On Android, the abort message that was passed to |
| //! android_set_abort_message(). This is only available on Q or later. |
| const std::string& AbortMessage(); |
| |
| private: |
| void InitializeThreads(); |
| void InitializeModules(); |
| void InitializeAbortMessage(); |
| template <bool Is64Bit> |
| void ReadAbortMessage(const MemoryMap::Mapping* mapping); |
| |
| PtraceConnection* connection_; // weak |
| ProcessInfo process_info_; |
| MemoryMap memory_map_; |
| std::vector<Thread> threads_; |
| std::vector<Module> modules_; |
| std::string abort_message_; |
| std::vector<std::unique_ptr<ElfImageReader>> elf_readers_; |
| bool is_64_bit_; |
| bool initialized_threads_; |
| bool initialized_modules_; |
| InitializationStateDcheck initialized_; |
| }; |
| |
| } // namespace crashpad |
| |
| #endif // CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_ |