Make ProcessReaderModule and ProcessReaderThread nested classes.

This change is being made in response to the suggestion at
https://codereview.chromium.org/539263003/diff/20001/util/mac/mach_o_image_symbol_table_reader.h#newcode45

TEST=util_test ProcessReader.*
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/543193002
This commit is contained in:
Mark Mentovai 2014-09-05 16:35:16 -04:00
parent 9dd0ac943a
commit 3d4eeae864
3 changed files with 76 additions and 74 deletions

View File

@ -69,7 +69,7 @@ kern_return_t MachVMRegionRecurseDeepest(mach_port_t task,
namespace crashpad {
ProcessReaderThread::ProcessReaderThread()
ProcessReader::Thread::Thread()
: thread_context(),
float_context(),
debug_context(),
@ -82,10 +82,10 @@ ProcessReaderThread::ProcessReaderThread()
priority(0) {
}
ProcessReaderModule::ProcessReaderModule() : name(), address(0), timestamp(0) {
ProcessReader::Module::Module() : name(), address(0), timestamp(0) {
}
ProcessReaderModule::~ProcessReaderModule() {
ProcessReader::Module::~Module() {
}
ProcessReader::ProcessReader()
@ -101,7 +101,7 @@ ProcessReader::ProcessReader()
}
ProcessReader::~ProcessReader() {
for (const ProcessReaderThread& thread : threads_) {
for (const Thread& thread : threads_) {
kern_return_t kr = mach_port_deallocate(mach_task_self(), thread.port);
MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
}
@ -186,7 +186,7 @@ bool ProcessReader::CPUTimes(timeval* user_time, timeval* system_time) const {
return true;
}
const std::vector<ProcessReaderThread>& ProcessReader::Threads() {
const std::vector<ProcessReader::Thread>& ProcessReader::Threads() {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
if (!initialized_threads_) {
@ -196,7 +196,7 @@ const std::vector<ProcessReaderThread>& ProcessReader::Threads() {
return threads_;
}
const std::vector<ProcessReaderModule>& ProcessReader::Modules() {
const std::vector<ProcessReader::Module>& ProcessReader::Modules() {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
if (!initialized_modules_) {
@ -231,7 +231,7 @@ void ProcessReader::InitializeThreads() {
mach_vm_round_page(thread_count * sizeof(*threads)));
for (size_t index = 0; index < thread_count; ++index) {
ProcessReaderThread thread;
Thread thread;
thread.port = threads[index];
#if defined(ARCH_CPU_X86_FAMILY)
@ -410,7 +410,7 @@ void ProcessReader::InitializeModules() {
bool found_dyld = false;
for (const process_types::dyld_image_info& image_info : image_info_vector) {
ProcessReaderModule module;
Module module;
module.address = image_info.imageLoadAddress;
module.timestamp = image_info.imageFileModDate;
if (!task_memory_->ReadCString(image_info.imageFilePath, &module.name)) {
@ -443,7 +443,7 @@ void ProcessReader::InitializeModules() {
// in its LC_LOAD_DYLINKER command.
if (!found_dyld && all_image_infos.version >= 2 &&
all_image_infos.dyldImageLoadAddress) {
ProcessReaderModule module;
Module module;
module.address = all_image_infos.dyldImageLoadAddress;
module.timestamp = 0;

View File

@ -32,62 +32,63 @@
namespace crashpad {
//! \brief Contains information about a thread that belongs to a task (process).
struct ProcessReaderThread {
#if defined(ARCH_CPU_X86_FAMILY)
union ThreadContext {
x86_thread_state64_t t64;
x86_thread_state32_t t32;
};
union FloatContext {
x86_float_state64_t f64;
x86_float_state32_t f32;
};
union DebugContext {
x86_debug_state64_t d64;
x86_debug_state32_t d32;
};
#endif
ProcessReaderThread();
~ProcessReaderThread() {}
ThreadContext thread_context;
FloatContext float_context;
DebugContext debug_context;
uint64_t id;
mach_vm_address_t stack_region_address;
mach_vm_size_t stack_region_size;
mach_vm_address_t thread_specific_data_address;
mach_port_t port;
int suspend_count;
int priority;
};
//! \brief Contains information about a module loaded into a process.
struct ProcessReaderModule {
ProcessReaderModule();
~ProcessReaderModule();
//! \brief The pathname used to load the module from disk.
std::string name;
//! \brief The address where the base of the module is loaded in the remote
//! process.
mach_vm_address_t address;
//! \brief The modules timestamp.
//!
//! This field will be `0` if its value cannot be determined. It can only be
//! determined for images that are loaded by dyld, so it will be `0` for the
//! main executable and for dyld itself.
time_t timestamp;
};
//! \brief Accesses information about another process, identified by a Mach
//! task.
class ProcessReader {
public:
//! \brief Contains information about a thread that belongs to a task
//! (process).
struct Thread {
#if defined(ARCH_CPU_X86_FAMILY)
union ThreadContext {
x86_thread_state64_t t64;
x86_thread_state32_t t32;
};
union FloatContext {
x86_float_state64_t f64;
x86_float_state32_t f32;
};
union DebugContext {
x86_debug_state64_t d64;
x86_debug_state32_t d32;
};
#endif
Thread();
~Thread() {}
ThreadContext thread_context;
FloatContext float_context;
DebugContext debug_context;
uint64_t id;
mach_vm_address_t stack_region_address;
mach_vm_size_t stack_region_size;
mach_vm_address_t thread_specific_data_address;
mach_port_t port;
int suspend_count;
int priority;
};
//! \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 The address where the base of the module is loaded in the remote
//! process.
mach_vm_address_t address;
//! \brief The modules timestamp.
//!
//! This field will be `0` if its value cannot be determined. It can only be
//! determined for images that are loaded by dyld, so it will be `0` for the
//! main executable and for dyld itself.
time_t timestamp;
};
ProcessReader();
~ProcessReader();
@ -129,12 +130,12 @@ class ProcessReader {
//! \return The threads that are in the task (process). The first element (at
//! index `0`) corresponds to the main thread.
const std::vector<ProcessReaderThread>& Threads();
const std::vector<Thread>& Threads();
//! \return The modules loaded in the process. The first element (at index
//! `0`) corresponds to the main executable, and the final element
//! corresponds to the dynamic loader, dyld.
const std::vector<ProcessReaderModule>& Modules();
const std::vector<Module>& Modules();
private:
//! Performs lazy initialization of the \a threads_ vector on behalf of
@ -201,8 +202,8 @@ class ProcessReader {
unsigned int user_tag);
kinfo_proc kern_proc_info_;
std::vector<ProcessReaderThread> threads_; // owns send rights
std::vector<ProcessReaderModule> modules_;
std::vector<Thread> threads_; // owns send rights
std::vector<Module> modules_;
scoped_ptr<TaskMemory> task_memory_;
mach_port_t task_; // weak
InitializationStateDcheck initialized_;

View File

@ -144,7 +144,7 @@ TEST(ProcessReader, SelfOneThread) {
ProcessReader process_reader;
ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
const std::vector<ProcessReaderThread>& threads = process_reader.Threads();
const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
// If other tests ran in this process previously, threads may have been
// created and may still be running. This check must look for at least one
@ -315,7 +315,7 @@ typedef std::map<uint64_t, TestThreadPool::ThreadExpectation> ThreadMap;
// the tests control (such as system libraries) may start threads, or may have
// started threads prior to a tests execution.
void ExpectSeveralThreads(ThreadMap* thread_map,
const std::vector<ProcessReaderThread>& threads,
const std::vector<ProcessReader::Thread>& threads,
const bool tolerate_extra_threads) {
if (tolerate_extra_threads) {
ASSERT_GE(threads.size(), thread_map->size());
@ -324,7 +324,7 @@ void ExpectSeveralThreads(ThreadMap* thread_map,
}
for (size_t thread_index = 0; thread_index < threads.size(); ++thread_index) {
const ProcessReaderThread& thread = threads[thread_index];
const ProcessReader::Thread& thread = threads[thread_index];
mach_vm_address_t thread_stack_region_end =
thread.stack_region_address + thread.stack_region_size;
@ -357,7 +357,7 @@ void ExpectSeveralThreads(ThreadMap* thread_map,
continue;
}
const ProcessReaderThread& other_thread = threads[other_thread_index];
const ProcessReader::Thread& other_thread = threads[other_thread_index];
EXPECT_NE(thread.id, other_thread.id);
EXPECT_NE(thread.port, other_thread.port);
@ -409,7 +409,7 @@ TEST(ProcessReader, SelfSeveralThreads) {
thread_map[thread_id] = expectation;
}
const std::vector<ProcessReaderThread>& threads = process_reader.Threads();
const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
// Other tests that have run previously may have resulted in the creation of
// threads that still exist, so pass true for |tolerate_extra_threads|.
@ -420,7 +420,7 @@ TEST(ProcessReader, SelfSeveralThreads) {
// shows up once.
base::mac::ScopedMachSendRight thread_self(mach_thread_self());
bool found_thread_self = false;
for (const ProcessReaderThread& thread : threads) {
for (const ProcessReader::Thread& thread : threads) {
if (thread.port == thread_self) {
EXPECT_FALSE(found_thread_self);
found_thread_self = true;
@ -477,7 +477,7 @@ class ProcessReaderThreadedChild final : public MachMultiprocess {
thread_map[thread_id] = expectation;
}
const std::vector<ProcessReaderThread>& threads = process_reader.Threads();
const std::vector<ProcessReader::Thread>& threads = process_reader.Threads();
// The child shouldnt have any threads other than its main thread and the
// ones it created in its pool, so pass false for |tolerate_extra_threads|.
@ -578,7 +578,7 @@ TEST(ProcessReader, SelfModules) {
ASSERT_TRUE(process_reader.Initialize(mach_task_self()));
uint32_t dyld_image_count = _dyld_image_count();
const std::vector<ProcessReaderModule>& modules = process_reader.Modules();
const std::vector<ProcessReader::Module>& modules = process_reader.Modules();
// There needs to be at least an entry for the main executable, for a dylib,
// and for dyld.
@ -639,7 +639,8 @@ class ProcessReaderModulesChild final : public MachMultiprocess {
ProcessReader process_reader;
ASSERT_TRUE(process_reader.Initialize(ChildTask()));
const std::vector<ProcessReaderModule>& modules = process_reader.Modules();
const std::vector<ProcessReader::Module>& modules =
process_reader.Modules();
// There needs to be at least an entry for the main executable, for a dylib,
// and for dyld.