blob: 8659ec6b781387ff9a965dd8de091fb5a7f59951 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <string>
#include <vector>
#include <zircon/types.h>
#include "lib/fxl/macros.h"
#include "lib/fxl/strings/string_view.h"
namespace debugserver {
class Server;
class Thread;
// Utility class for holding the thread action list argument to vCont packets.
// https://sourceware.org/gdb/current/onlinedocs/gdb/Packets.html
class ThreadActionList final {
public:
// The kind of action to perform.
enum class Action {
// No action specified for this thread.
kNone,
// Continue the thread.
kContinue,
// Step the thread one instruction.
kStep,
// Other actions are not supported yet.
};
// Utility class to hold one entry in ThreadActionList.
class Entry final {
public:
Entry(Action action, zx_koid_t pid, zx_koid_t tid);
~Entry() = default;
Action action() const { return action_; }
zx_koid_t pid() const { return pid_; }
zx_koid_t tid() const { return tid_; }
// Call this to upgrade a "pick one" entry (tid == 0) to the chosen value.
void set_picked_tid(zx_koid_t tid);
bool Contains(zx_koid_t pid, zx_koid_t tid) const;
private:
friend class ThreadActionList;
Action action_;
// N.B. While the remote protocol defines zero for pid/tid to mean "pick a
// random one" zero values do not end up in |pid_|. The "pick one" must be
// done before an Entry is created. The "pick one" for |tid_| is resolved
// later though, after the Entry is created.
zx_koid_t pid_;
zx_koid_t tid_;
};
// For pid,tid values, means "all processes" or "all threads".
// TODO(dje): This is a legitimate value, we "should" use a different value,
// but this is fine for now. The kernel reserves the first 1K, possibly we
// could use one of those.
static constexpr zx_koid_t kAll = ~0ull;
static bool DecodeAction(char c, Action* out_action);
static const char* ActionToString(Action action);
ThreadActionList(const fxl::StringView& str, zx_koid_t cur_proc);
~ThreadActionList() = default;
bool valid() const { return valid_; }
// Call this after resolving all zero tid values, which means to "pick one".
// This must be called before calling GetAction.
// This exists to force caller to resolve zero tids ("pick one") to keep
// the resolution code separate. That step may need to evolve. Plus we'd
// have to stub out the resolution code in the unittest. Later.
void MarkPickOnesResolved() { pick_ones_resolved_ = true; }
// Return the action for |thread|.
Action GetAction(zx_koid_t pid, zx_koid_t tid) const;
Action default_action() const { return default_action_; }
const std::vector<Entry>& actions() const { return actions_; }
private:
ThreadActionList() = default;
// True if the contents are valid.
bool valid_ = false;
// True if "pick one" tid values have been resolved.
bool pick_ones_resolved_ = false;
Action default_action_ = Action::kNone;
std::vector<Entry> actions_;
FXL_DISALLOW_COPY_AND_ASSIGN(ThreadActionList);
};
} // namespace debugserver