aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process/elf-core/ThreadElfCore.h
blob: 38c52658a23a2154d26a6f1d08c5de0291b70439 (plain) (blame)
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
//===-- ThreadElfCore.h -----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ThreadElfCore_h_
#define liblldb_ThreadElfCore_h_

// C Includes
// C++ Includes
#include <string>

// Other libraries and framework includes
// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"

struct compat_timeval {
  alignas(8) uint64_t tv_sec;
  alignas(8) uint64_t tv_usec;
};

// 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

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::Error Parse(lldb_private::DataExtractor &data,
                            lldb_private::ArchSpec &arch);

  // 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(lldb_private::ArchSpec &arch);
};

static_assert(sizeof(ELFLinuxPrStatus) == 112,
              "sizeof ELFLinuxPrStatus is not correct!");

struct ELFLinuxSigInfo {
  int32_t si_signo;
  int32_t si_code;
  int32_t si_errno;

  ELFLinuxSigInfo();

  lldb_private::Error Parse(lldb_private::DataExtractor &data,
                            const lldb_private::ArchSpec &arch);

  // 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) == 12,
              "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::Error Parse(lldb_private::DataExtractor &data,
                            lldb_private::ArchSpec &arch);

  // 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(lldb_private::ArchSpec &arch);
};

static_assert(sizeof(ELFLinuxPrPsInfo) == 136,
              "sizeof ELFLinuxPrPsInfo is not correct!");

struct ThreadData {
  lldb_private::DataExtractor gpregset;
  lldb_private::DataExtractor fpregset;
  lldb_private::DataExtractor vregset;
  lldb::tid_t tid;
  int signo = 0;
  int prstatus_sig = 0;
  std::string name;
};

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;

  void ClearStackFrames() override;

  static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }

  const char *GetName() override {
    if (m_thread_name.empty())
      return NULL;
    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();
  }

protected:
  //------------------------------------------------------------------
  // Member variables.
  //------------------------------------------------------------------
  std::string m_thread_name;
  lldb::RegisterContextSP m_thread_reg_ctx_sp;

  int m_signo;

  lldb_private::DataExtractor m_gpregset_data;
  lldb_private::DataExtractor m_fpregset_data;
  lldb_private::DataExtractor m_vregset_data;

  bool CalculateStopInfo() override;
};

#endif // liblldb_ThreadElfCore_h_