1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
//===-- ThreadElfCore.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "llvm/ADT/DenseMap.h"
#include <optional>
#include <string>
struct compat_timeval {
alignas(8) uint64_t tv_sec;
alignas(8) uint64_t tv_usec;
};
namespace lldb_private {
class ProcessInstanceInfo;
}
// PRSTATUS structure's size differs based on architecture.
// This is the layout in the x86-64 arch.
// In the i386 case we parse it manually and fill it again
// in the same structure
// The gp registers are also a part of this struct, but they are handled
// separately
#undef si_signo
#undef si_code
#undef si_errno
#undef si_addr
#undef si_addr_lsb
struct ELFLinuxPrStatus {
int32_t si_signo;
int32_t si_code;
int32_t si_errno;
int16_t pr_cursig;
alignas(8) uint64_t pr_sigpend;
alignas(8) uint64_t pr_sighold;
uint32_t pr_pid;
uint32_t pr_ppid;
uint32_t pr_pgrp;
uint32_t pr_sid;
compat_timeval pr_utime;
compat_timeval pr_stime;
compat_timeval pr_cutime;
compat_timeval pr_cstime;
ELFLinuxPrStatus();
lldb_private::Status Parse(const lldb_private::DataExtractor &data,
const lldb_private::ArchSpec &arch);
static std::optional<ELFLinuxPrStatus>
Populate(const lldb::ThreadSP &thread_sp);
// Return the bytesize of the structure
// 64 bit - just sizeof
// 32 bit - hardcoded because we are reusing the struct, but some of the
// members are smaller -
// so the layout is not the same
static size_t GetSize(const lldb_private::ArchSpec &arch);
};
static_assert(sizeof(ELFLinuxPrStatus) == 112,
"sizeof ELFLinuxPrStatus is not correct!");
struct ELFLinuxSigInfo {
int32_t si_signo; // Order matters for the first 3.
int32_t si_errno;
int32_t si_code;
// Copied from siginfo_t so we don't have to include signal.h on non 'Nix
// builds. Slight modifications to ensure no 32b vs 64b differences.
struct alignas(8) {
lldb::addr_t si_addr; /* faulting insn/memory ref. */
int16_t si_addr_lsb; /* Valid LSB of the reported address. */
union {
/* used when si_code=SEGV_BNDERR */
struct {
lldb::addr_t _lower;
lldb::addr_t _upper;
} _addr_bnd;
/* used when si_code=SEGV_PKUERR */
uint32_t _pkey;
} bounds;
} sigfault;
enum SigInfoNoteType : uint8_t { eUnspecified, eNT_SIGINFO };
SigInfoNoteType note_type;
ELFLinuxSigInfo();
lldb_private::Status Parse(const lldb_private::DataExtractor &data,
const lldb_private::ArchSpec &arch,
const lldb_private::UnixSignals &unix_signals);
std::string
GetDescription(const lldb_private::UnixSignals &unix_signals) const;
// Return the bytesize of the structure
// 64 bit - just sizeof
// 32 bit - hardcoded because we are reusing the struct, but some of the
// members are smaller -
// so the layout is not the same
static size_t GetSize(const lldb_private::ArchSpec &arch);
};
//static_assert(sizeof(ELFLinuxSigInfo) == 56,
// "sizeof ELFLinuxSigInfo is not correct!");
// PRPSINFO structure's size differs based on architecture.
// This is the layout in the x86-64 arch case.
// In the i386 case we parse it manually and fill it again
// in the same structure
struct ELFLinuxPrPsInfo {
char pr_state;
char pr_sname;
char pr_zomb;
char pr_nice;
alignas(8) uint64_t pr_flag;
uint32_t pr_uid;
uint32_t pr_gid;
int32_t pr_pid;
int32_t pr_ppid;
int32_t pr_pgrp;
int32_t pr_sid;
char pr_fname[16];
char pr_psargs[80];
ELFLinuxPrPsInfo();
lldb_private::Status Parse(const lldb_private::DataExtractor &data,
const lldb_private::ArchSpec &arch);
static std::optional<ELFLinuxPrPsInfo>
Populate(const lldb::ProcessSP &process_sp);
static std::optional<ELFLinuxPrPsInfo>
Populate(const lldb_private::ProcessInstanceInfo &info,
lldb::StateType state);
// Return the bytesize of the structure
// 64 bit - just sizeof
// 32 bit - hardcoded because we are reusing the struct, but some of the
// members are smaller -
// so the layout is not the same
static size_t GetSize(const lldb_private::ArchSpec &arch);
};
static_assert(sizeof(ELFLinuxPrPsInfo) == 136,
"sizeof ELFLinuxPrPsInfo is not correct!");
struct ThreadData {
lldb_private::DataExtractor gpregset;
std::vector<lldb_private::CoreNote> notes;
lldb::tid_t tid;
std::string name;
ELFLinuxSigInfo siginfo;
int prstatus_sig = 0;
};
class ThreadElfCore : public lldb_private::Thread {
public:
ThreadElfCore(lldb_private::Process &process, const ThreadData &td);
~ThreadElfCore() override;
void RefreshStateAfterStop() override;
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
const char *GetName() override {
if (m_thread_name.empty())
return nullptr;
return m_thread_name.c_str();
}
void SetName(const char *name) override {
if (name && name[0])
m_thread_name.assign(name);
else
m_thread_name.clear();
}
void CreateStopFromSigInfo(const ELFLinuxSigInfo &siginfo,
const lldb_private::UnixSignals &unix_signals);
protected:
// Member variables.
std::string m_thread_name;
lldb::RegisterContextSP m_thread_reg_ctx_sp;
lldb_private::DataExtractor m_gpregset_data;
std::vector<lldb_private::CoreNote> m_notes;
ELFLinuxSigInfo m_siginfo;
bool CalculateStopInfo() override;
};
#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
|