Skip to content

Commit b71f542

Browse files
committed
Reduce support for thread_db to the barest minimum
The only practical use at this point is to give pthread thread ids for the threads, so just do that, and make everything else rely on LWPs everywhere. We can also now get our full CoreRegisters when unwinding the stack. Change the register get interfaces to throw exceptions when the fail - it's too easy to silently ignore at the moment.
1 parent 1cb6ea7 commit b71f542

File tree

7 files changed

+284
-298
lines changed

7 files changed

+284
-298
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.10)
2-
set(PSTACK_SOVERSION 2.15)
3-
set(PSTACK_VERSION 2.15)
2+
set(PSTACK_SOVERSION 2.16)
3+
set(PSTACK_VERSION 2.16)
44
project(pstack LANGUAGES C CXX VERSION "${PSTACK_VERSION}" )
55

66
include (GNUInstallDirs)

libpstack/proc.h

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
#include <elf.h>
44
#include <signal.h>
55
#include <memory.h>
6-
extern "C" {
7-
// Some thread_db headers are not safe to include unwrapped in extern "C"
8-
#include <thread_db.h>
9-
}
106

117
#include <map>
128
#include <set>
@@ -16,8 +12,10 @@ extern "C" {
1612
#include <string_view>
1713
#include <sys/stat.h> // for ino_t
1814
#include <ucontext.h> // for gregset_t
15+
extern "C" { // sigh.
16+
#include <thread_db.h>
17+
}
1918

20-
#include "libpstack/ps_callback.h"
2119
#include "libpstack/dwarf.h"
2220
#include "libpstack/arch.h"
2321

@@ -172,13 +170,16 @@ struct PrintableFrame {
172170

173171
};
174172

175-
struct ThreadStack {
176-
td_thrinfo_t info {};
173+
struct Lwp {
174+
lwpid_t id;
177175
std::optional<std::string> name;
176+
std::optional<td_thrinfo_t> threadInfo;
178177
std::vector<StackFrame> stack;
179178
void unwind(Process &, const CoreRegisters &regs);
180179
};
181180

181+
using Stacks = std::map<lwpid_t, Lwp>;
182+
182183
struct DevNode {
183184
int major = -1;
184185
int minor = -1;
@@ -270,8 +271,20 @@ class Process : public ps_prochandle {
270271

271272
virtual size_t getRegs(lwpid_t pid, int code, size_t size, void *data) = 0;
272273

273-
template <typename T, int code> size_t getRegset(lwpid_t pid, T &reg) {
274-
return getRegs(pid, code, sizeof (T), reinterpret_cast<void *>( &reg ) );
274+
template <typename T, int code> void getRegset(lwpid_t pid, T &reg) {
275+
size_t rc = getRegs(pid, code, sizeof (T), reinterpret_cast<void *>( &reg ) );
276+
if (rc == 0) {
277+
// Failed
278+
throw (Exception()
279+
<< "failed to get register set " << code << " for " << pid
280+
<< ": " << strerror(errno));
281+
}
282+
if (rc < sizeof (T)) {
283+
// worked, but size doesn't match.
284+
throw (Exception()
285+
<< "invalid register set size, got " << rc
286+
<< ", expected " << sizeof(T));
287+
}
275288
}
276289
CoreRegisters getCoreRegs(lwpid_t lwp);
277290

@@ -287,7 +300,7 @@ class Process : public ps_prochandle {
287300
virtual void resumeProcess() = 0;
288301
virtual void resume(pid_t lwpid) = 0;
289302
virtual Elf::Object::sptr executableImage() { return nullptr; }
290-
std::ostream &dumpStackText(std::ostream &, const ThreadStack &);
303+
std::ostream &dumpStackText(std::ostream &, const Lwp &);
291304
std::ostream &dumpFrameText(std::ostream &, const StackFrame &, int);
292305
template <typename T> void listThreads(const T &invokeable);
293306
virtual void listLWPs(const std::function<void(lwpid_t)> &) {};
@@ -301,7 +314,7 @@ class Process : public ps_prochandle {
301314
std::tuple<Elf::Object::sptr, Elf::Addr, Elf::Sym>
302315
resolveSymbolDetail(const char *name, bool includeDebug,
303316
std::function<bool(std::string_view)> match = [](std::string_view) { return true; });
304-
virtual std::list<ThreadStack> getStacks();
317+
virtual Stacks getStacks();
305318
void load();
306319
[[nodiscard]] virtual pid_t getPID() const = 0;
307320
[[nodiscard]] virtual AddressSpace addressSpace() const = 0;
@@ -471,7 +484,7 @@ std::ostream &operator << (std::ostream &os, WaitStatus ws);
471484
}
472485

473486
std::ostream &operator << (std::ostream &os, const JSON<pstack::Procman::StackFrame, pstack::Procman::Process *> &jt);
474-
std::ostream &operator << (std::ostream &os, const JSON<pstack::Procman::ThreadStack, pstack::Procman::Process *> &jt);
487+
std::ostream &operator << (std::ostream &os, const JSON<pstack::Procman::Lwp, pstack::Procman::Process *> &jt);
475488

476489
}
477490

libpstack/ps_callback.h

Lines changed: 0 additions & 17 deletions
This file was deleted.

live.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "libpstack/proc.h"
2-
#include "libpstack/ps_callback.h"
32
#include "libpstack/stringify.h"
43

54
#include <sys/ptrace.h>
@@ -31,7 +30,6 @@ LiveProcess::LiveProcess(Context &context, Elf::Object::sptr &ex, pid_t pid_, bo
3130
: Process( context, ex, std::make_shared<CacheReader>(std::make_shared<LiveReader>(context, pid_, "mem")))
3231
, pid(pid_)
3332
{
34-
(void)ps_getpid(this);
3533
if (alreadyStopped)
3634
stoppedLWPs[pid].stopCount = 1;
3735
}

proc_service.cc

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "libpstack/proc.h"
2-
#include "libpstack/ps_callback.h"
32

3+
#include <thread_db.h>
4+
#include <proc_service.h>
45
#include <cstdarg>
56

67
using pstack::Procman::Process;
@@ -9,9 +10,9 @@ using namespace pstack;
910
extern "C" {
1011

1112
ps_err_e
12-
ps_pcontinue(const struct ps_prochandle *ph)
13+
ps_pcontinue(struct ps_prochandle *ph)
1314
{
14-
auto p = const_cast<Process *>(static_cast<const Process *>(ph));
15+
auto p = static_cast<Process *>(ph);
1516
try {
1617
p->resumeProcess();
1718
return PS_OK;
@@ -22,9 +23,9 @@ ps_pcontinue(const struct ps_prochandle *ph)
2223
}
2324

2425
ps_err_e
25-
ps_lcontinue(const struct ps_prochandle *ph, lwpid_t pid)
26+
ps_lcontinue(struct ps_prochandle *ph, lwpid_t pid)
2627
{
27-
auto p = const_cast<Process *>(static_cast<const Process *>(ph));
28+
auto p = static_cast<Process *>(ph);
2829
try {
2930
p->resume(pid);
3031
return PS_OK;
@@ -87,9 +88,9 @@ ps_pread(struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t len)
8788
}
8889

8990
ps_err_e
90-
ps_pstop(const struct ps_prochandle *ph)
91+
ps_pstop(struct ps_prochandle *ph)
9192
{
92-
auto *p = const_cast<Process *>(static_cast<const Process *>(ph));
93+
auto *p = static_cast<Process *>(ph);
9394
try {
9495
p->stopProcess();
9596
return PS_OK;
@@ -174,8 +175,15 @@ ps_err_e ps_lgetfpregs(struct ps_prochandle * /* unused */, lwpid_t /* unused */
174175

175176
ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t pid, prgregset_t gregset)
176177
{
177-
auto p = static_cast<Process *>(ph);
178-
return p->getRegset<user_regs_struct, NT_PRSTATUS>(pid, *reinterpret_cast<user_regs_struct *>(gregset)) ? PS_OK : PS_ERR;
178+
auto p = static_cast<Process *>(ph);
179+
auto gregs = reinterpret_cast<user_regs_struct *>(gregset);
180+
try {
181+
p->getRegset<user_regs_struct, NT_PRSTATUS>(pid, *gregs);
182+
return PS_OK;
183+
}
184+
catch (const Exception &ex) {
185+
return PS_ERR;
186+
}
179187
}
180188

181189
ps_err_e ps_lsetfpregs(struct ps_prochandle * /* unused */, lwpid_t /* unused */,
@@ -192,9 +200,9 @@ ps_err_e ps_lsetregs(struct ps_prochandle * /* unused */, lwpid_t /* unused */,
192200
return (PS_ERR);
193201
}
194202

195-
ps_err_e ps_lstop(const struct ps_prochandle *ph, lwpid_t lwpid)
203+
ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid)
196204
{
197-
Process *p = const_cast<Process *>(static_cast<const Process *>(ph));
205+
auto p = static_cast<Process *>(ph);
198206
try {
199207
p->stop(lwpid);
200208
return PS_OK;

0 commit comments

Comments
 (0)