2014-04-29 18:21:07 +00:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
2014-04-25 23:08:24 +00:00
|
|
|
#include <iostream>
|
2014-05-23 22:25:29 +00:00
|
|
|
#include <pthread.h>
|
2014-05-14 14:51:27 +00:00
|
|
|
#include <unistd.h>
|
2014-05-23 22:25:29 +00:00
|
|
|
#include <vector>
|
2014-04-25 23:08:24 +00:00
|
|
|
|
2014-04-29 18:21:07 +00:00
|
|
|
static const char *const RETVAL_PREFIX = "retval:";
|
2014-05-14 14:51:27 +00:00
|
|
|
static const char *const SLEEP_PREFIX = "sleep:";
|
|
|
|
static const char *const STDERR_PREFIX = "stderr:";
|
2014-04-29 18:21:07 +00:00
|
|
|
|
2014-05-23 22:25:29 +00:00
|
|
|
static const char *const THREAD_PREFIX = "thread:";
|
|
|
|
static const char *const THREAD_COMMAND_NEW = "new";
|
|
|
|
|
|
|
|
static void*
|
|
|
|
thread_func (void *arg)
|
|
|
|
{
|
|
|
|
// For now, just sleep for a few seconds.
|
|
|
|
// std::cout << "thread " << pthread_self() << ": created" << std::endl;
|
|
|
|
|
|
|
|
int sleep_seconds_remaining = 5;
|
|
|
|
while (sleep_seconds_remaining > 0)
|
|
|
|
{
|
|
|
|
sleep_seconds_remaining = sleep (sleep_seconds_remaining);
|
|
|
|
}
|
|
|
|
|
|
|
|
// std::cout << "thread " << pthread_self() << ": exiting" << std::endl;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-04-29 18:21:07 +00:00
|
|
|
int main (int argc, char **argv)
|
2014-04-25 23:08:24 +00:00
|
|
|
{
|
2014-05-23 22:25:29 +00:00
|
|
|
std::vector<pthread_t> threads;
|
2014-04-29 18:21:07 +00:00
|
|
|
int return_value = 0;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
|
{
|
|
|
|
if (std::strstr (argv[i], STDERR_PREFIX))
|
|
|
|
{
|
|
|
|
// Treat remainder as text to go to stderr.
|
|
|
|
std::cerr << (argv[i] + strlen (STDERR_PREFIX)) << std::endl;
|
|
|
|
}
|
|
|
|
else if (std::strstr (argv[i], RETVAL_PREFIX))
|
|
|
|
{
|
|
|
|
// Treat as the return value for the program.
|
|
|
|
return_value = std::atoi (argv[i] + strlen (RETVAL_PREFIX));
|
|
|
|
}
|
2014-05-14 14:51:27 +00:00
|
|
|
else if (std::strstr (argv[i], SLEEP_PREFIX))
|
|
|
|
{
|
|
|
|
// Treat as the amount of time to have this process sleep (in seconds).
|
2014-05-14 19:34:06 +00:00
|
|
|
int sleep_seconds_remaining = std::atoi (argv[i] + strlen (SLEEP_PREFIX));
|
|
|
|
|
|
|
|
// Loop around, sleeping until all sleep time is used up. Note that
|
|
|
|
// signals will cause sleep to end early with the number of seconds remaining.
|
|
|
|
for (int i = 0; sleep_seconds_remaining > 0; ++i)
|
|
|
|
{
|
|
|
|
sleep_seconds_remaining = sleep (sleep_seconds_remaining);
|
Added gdb remote protocol tests across all qRegisterInfo responses.
Added support for gdb remote protocol capture/playback where there is a query/multiple-response
pattern. The new playback entry supports:
- a general query command (key: next_query or query)
- an optional first-query command if that differs from the subsequent queries (key: first_query)
- an end regex for matching anything that would signify that the query/multi-response
iteration has come to an end. An assumption is that the end regex is not a content
package we care about aside from ending the iteration. (key: end_regex)
- an optional 0-based index appended to the end of the query command
(key: append_iteration_suffix), default: False.
- a key used to collect responses from the query. Any response from the gdb remote
that doesn't match the end-of-iteration regex is captured in the playback context
dictionary using the key specified. That key will be an array, where each array
entry is one of the responses from the query/multi-response iteration. (key: save_key).
- a runaway response value, defaulting to 10k, where if this many responses is captured,
assume the ending condition regex is invalid, or the debug monitor is doing something
goofy that is going to blow out memory or time. (key: runaway_response_count, default: 10000)
See the lldbgdbserverutils.MultiResponseGdbRemoteEntry class for details.
A MultiResponseGdbRemoteEntry is added by adding an element to the GdbRemoteTestSequence
(via GdbRemoteTestSequence.add_log_lines), using a dictionary, where the "type" key
is set to "multi_response", and the rest of the keys in the dictionary entry are
set to the keys documented for MultiResponseGdbRemoteEntry.
Added helper functions to add the required entry to grab all qRegisterInfo responses.
Added another helper to parse the qRegisterInfo response packets into an array of
dictionaries, where each key:value in the dictionary comes from the register info
response packet.
Added a test to verify that a generic register exists for the program counter,
frame pointer, stack pointer and cpu flags across all register info responses.
Added a test to verify that at least one register set exists across all register
info responses.
llvm-svn: 209170
2014-05-19 22:35:24 +00:00
|
|
|
// std::cout << "sleep result (call " << i << "): " << sleep_seconds_remaining << std::endl;
|
2014-05-14 19:34:06 +00:00
|
|
|
}
|
2014-05-14 14:51:27 +00:00
|
|
|
}
|
2014-05-23 22:25:29 +00:00
|
|
|
else if (std::strstr (argv[i], THREAD_PREFIX))
|
|
|
|
{
|
|
|
|
// Check if we're creating a new thread.
|
|
|
|
if (std::strstr (argv[i] + strlen(THREAD_PREFIX), THREAD_COMMAND_NEW))
|
|
|
|
{
|
|
|
|
// Create a new thread.
|
|
|
|
pthread_t new_thread;
|
|
|
|
const int err = ::pthread_create (&new_thread, NULL, thread_func, NULL);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
std::cerr << "pthread_create() failed with error code " << err << std::endl;
|
|
|
|
exit (err);
|
|
|
|
}
|
|
|
|
threads.push_back (new_thread);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// At this point we don't do anything else with threads.
|
|
|
|
// Later use thread index and send command to thread.
|
|
|
|
}
|
|
|
|
}
|
2014-04-29 18:21:07 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Treat the argument as text for stdout.
|
|
|
|
std::cout << argv[i] << std::endl;
|
|
|
|
}
|
|
|
|
}
|
2014-05-23 22:25:29 +00:00
|
|
|
|
|
|
|
// If we launched any threads, join them
|
|
|
|
for (std::vector<pthread_t>::iterator it = threads.begin (); it != threads.end (); ++it)
|
|
|
|
{
|
|
|
|
void *thread_retval = NULL;
|
|
|
|
const int err = ::pthread_join (*it, &thread_retval);
|
|
|
|
if (err != 0)
|
|
|
|
{
|
|
|
|
std::cerr << "pthread_join() failed with error code " << err << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-29 18:21:07 +00:00
|
|
|
return return_value;
|
2014-04-25 23:08:24 +00:00
|
|
|
}
|