Added the ability to download a symboled executable and symbol file given a UUID.

llvm-svn: 164753
This commit is contained in:
Greg Clayton 2012-09-27 03:13:55 +00:00
parent c36b184fa2
commit c8f814d1df
9 changed files with 226 additions and 19 deletions

View File

@ -61,6 +61,10 @@ public:
m_packet.clear();
}
// Beware, this might not be NULL terminated as you can expect from
// StringString as there may be random bits in the llvm::SmallVector. If
// you are using this class to create a C string, be sure the call PutChar ('\0')
// after you have created your string, or use StreamString.
const char *
GetData () const
{

View File

@ -420,7 +420,8 @@ public:
int *status_ptr, // Pass NULL if you don't want the process exit status
int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
std::string *command_output, // Pass NULL if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
uint32_t timeout_sec,
const char *shell = "/bin/bash");
static lldb::DataBufferSP
GetAuxvData (lldb_private::Process *process);

View File

@ -24,9 +24,21 @@ namespace lldb_private {
class Symbols
{
public:
//----------------------------------------------------------------------
// Locate the executable file given a module specification.
//
// Locating the file should happen only on the local computer or using
// the current computers global settings.
//----------------------------------------------------------------------
static FileSpec
LocateExecutableObjectFile (const ModuleSpec &module_spec);
//----------------------------------------------------------------------
// Locate the symbol file given a module specification.
//
// Locating the file should happen only on the local computer or using
// the current computers global settings.
//----------------------------------------------------------------------
static FileSpec
LocateExecutableSymbolFile (const ModuleSpec &module_spec);
@ -34,6 +46,17 @@ public:
FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
const lldb_private::UUID *uuid,
const ArchSpec *arch);
//----------------------------------------------------------------------
// Locate the object and symbol file given a module specification.
//
// Locating the file can try to download the file from a corporate build
// respository, or using any other meeans necessary to locate both the
// unstripped object file and the debug symbols.
//----------------------------------------------------------------------
static bool
DownloadObjectAndSymbolFile (ModuleSpec &module_spec);
};
} // namespace lldb_private

View File

@ -24,6 +24,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
@ -4056,7 +4057,32 @@ protected:
symfile_spec.SetFile(symfile_path, true);
ArchSpec arch;
if (symfile_spec.Exists())
bool symfile_exists = symfile_spec.Exists();
// The code below was testing the new "Symbols::DownloadObjectAndSymbolFile"
// functionality. Now that it works on MacOSX, it will be enabled soon with
// option values (like "--uuid <UUID>" or "--file <module>", or "--frame"
// for the current stack frame's module). So it is commented out for now.
// if (!symfile_exists)
// {
// if (sym_spec.GetUUID().SetfromCString(symfile_path))
// {
// // A UUID was specified, look it up via UUID
// if (Symbols::DownloadObjectAndSymbolFile (sym_spec))
// {
//// printf ("UUID: %s\n", symfile_path);
//// printf ("objfile_spec: %s/%s\n",
//// sym_spec.GetFileSpec().GetDirectory().GetCString(),
//// sym_spec.GetFileSpec().GetFilename().GetCString());
//// printf ("symfile_spec: %s/%s\n",
//// sym_spec.GetSymbolFileSpec().GetDirectory().GetCString(),
//// sym_spec.GetSymbolFileSpec().GetFilename().GetCString());
// symfile_spec = sym_spec.GetSymbolFileSpec();
// symfile_exists = symfile_spec.Exists();
// }
// }
// }
if (symfile_exists)
{
ModuleSP symfile_module_sp (new Module (symfile_spec, target->GetArchitecture()));
const UUID &symfile_uuid = symfile_module_sp->GetUUID();
@ -4111,6 +4137,21 @@ protected:
}
else
{
// sym_spec.GetSymbolFileSpec().Clear();
// if (sym_spec.GetUUID().SetfromCString(symfile_path))
// {
// if (Symbols::DownloadObjectAndSymbolFile (sym_spec))
// {
// printf ("UUID: %s\n", symfile_path);
// printf ("objfile_spec: %s/%s\n",
// sym_spec.GetFileSpec().GetDirectory().GetCString(),
// sym_spec.GetFileSpec().GetFilename().GetCString());
// printf ("symfile_spec: %s/%s\n",
// sym_spec.GetSymbolFileSpec().GetDirectory().GetCString(),
// sym_spec.GetSymbolFileSpec().GetFilename().GetCString());
// }
// }
char resolved_symfile_path[PATH_MAX];
result.SetStatus (eReturnStatusFailed);
if (symfile_spec.GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))

View File

@ -66,9 +66,12 @@ char *
UUID::GetAsCString (char *dst, size_t dst_len) const
{
const uint8_t *u = (const uint8_t *)GetBytes();
snprintf(dst, dst_len, "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
return dst;
if (dst_len > snprintf (dst,
dst_len,
"%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]))
return dst;
return NULL;
}
void

View File

@ -1312,19 +1312,32 @@ Host::RunShellCommand (const char *command,
int *status_ptr,
int *signo_ptr,
std::string *command_output_ptr,
uint32_t timeout_sec)
uint32_t timeout_sec,
const char *shell)
{
Error error;
ProcessLaunchInfo launch_info;
launch_info.SetShell("/bin/bash");
launch_info.GetArguments().AppendArgument(command);
const bool localhost = true;
const bool will_debug = false;
const bool first_arg_is_full_shell_command = true;
launch_info.ConvertArgumentsForLaunchingInShell (error,
localhost,
will_debug,
first_arg_is_full_shell_command);
if (shell && shell[0])
{
// Run the command in a shell
launch_info.SetShell(shell);
launch_info.GetArguments().AppendArgument(command);
const bool localhost = true;
const bool will_debug = false;
const bool first_arg_is_full_shell_command = true;
launch_info.ConvertArgumentsForLaunchingInShell (error,
localhost,
will_debug,
first_arg_is_full_shell_command);
}
else
{
// No shell, just run it
Args args (command);
const bool first_arg_is_executable = true;
const bool first_arg_is_executable_and_argument = true;
launch_info.SetArguments(args, first_arg_is_executable, first_arg_is_executable_and_argument);
}
if (working_dir)
launch_info.SetWorkingDirectory(working_dir);
@ -1338,7 +1351,7 @@ Host::RunShellCommand (const char *command,
output_file_path = ::tmpnam(output_file_path_buffer);
launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
launch_info.AppendOpenFileAction(STDOUT_FILENO, output_file_path, false, true);
launch_info.AppendDuplicateFileAction(STDERR_FILENO, STDOUT_FILENO);
launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
}
else
{

View File

@ -36,5 +36,13 @@ Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
return FileSpec();
}
bool
Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec)
{
// Fill in the module_spec.GetFileSpec() for the object file and/or the
// module_spec.GetSymbolFileSpec() for the debug symbols file.
return false;
}
#endif

View File

@ -1552,7 +1552,6 @@ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, :
argv = (char * const*)tmp_argv;
}
const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir)
{
@ -1605,13 +1604,21 @@ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, :
eErrorTypePOSIX);
if (error.Fail() || log)
error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
{
error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
pid,
exe_path,
&file_actions,
&attr,
argv,
envp);
if (log)
{
for (int ii=0; argv[ii]; ++ii)
log->Printf("argv[%i] = '%s'", ii, argv[ii]);
}
}
}
else
{
@ -1624,12 +1631,19 @@ LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, :
eErrorTypePOSIX);
if (error.Fail() || log)
error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
{
error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
pid,
exe_path,
&attr,
argv,
envp);
if (log)
{
for (int ii=0; argv[ii]; ++ii)
log->Printf("argv[%i] = '%s'", ii, argv[ii]);
}
}
}
if (working_dir)

View File

@ -30,6 +30,7 @@
#include "lldb/Host/Host.h"
#include "lldb/Utility/CleanUp.h"
#include "Host/macosx/cfcpp/CFCBundle.h"
#include "Host/macosx/cfcpp/CFCData.h"
#include "Host/macosx/cfcpp/CFCReleaser.h"
#include "Host/macosx/cfcpp/CFCString.h"
#include "mach/machine.h"
@ -582,3 +583,102 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
}
return symbol_fspec;
}
bool
Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec)
{
bool success = false;
const UUID *uuid_ptr = module_spec.GetUUIDPtr();
if (uuid_ptr)
{
static bool g_located_dsym_for_uuid_exe = false;
static bool g_dsym_for_uuid_exe_exists = false;
static char g_dsym_for_uuid_exe_path[PATH_MAX];
if (!g_located_dsym_for_uuid_exe)
{
g_located_dsym_for_uuid_exe = true;
const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
FileSpec dsym_for_uuid_exe_spec;
if (dsym_for_uuid_exe_path_cstr)
{
dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
}
if (!g_dsym_for_uuid_exe_exists)
{
dsym_for_uuid_exe_spec.SetFile("~rc/bin/dsymForUUID", true);
g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
if (!g_dsym_for_uuid_exe_exists)
{
dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
}
}
if (g_dsym_for_uuid_exe_exists)
dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path));
}
if (g_dsym_for_uuid_exe_exists)
{
StreamString command;
char uuid_cstr_buffer[64];
const char *uuid_cstr = uuid_ptr->GetAsCString(uuid_cstr_buffer, sizeof(uuid_cstr_buffer));
command.Printf("%s --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_cstr);
int exit_status = -1;
int signo = -1;
std::string command_output;
Error error = Host::RunShellCommand (command.GetData(),
NULL, // current working directory
&exit_status, // Exit status
&signo, // Signal int *
&command_output, // Command output
30, // Large timeout to allow for long dsym download times
NULL); // Don't run in a shell (we don't need shell expansion)
if (error.Success() && exit_status == 0 && !command_output.empty())
{
CFCData data (CFDataCreateWithBytesNoCopy (NULL,
(const UInt8 *)command_output.data(),
command_output.size(),
kCFAllocatorNull));
CFCReleaser<CFPropertyListRef> plist(::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL));
if (CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ())
{
std::string str;
CFCString uuid_cfstr(uuid_cstr);
CFTypeRef uuid_dict = CFDictionaryGetValue ((CFDictionaryRef) plist.get(), uuid_cfstr.get());
if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ())
{
CFStringRef cf_str;
cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable"));
if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
{
if (CFCString::FileSystemRepresentation(cf_str, str))
{
success = true;
module_spec.GetFileSpec().SetFile (str.c_str(), true);
}
}
cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath"));
if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
{
if (CFCString::FileSystemRepresentation(cf_str, str))
{
success = true;
module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true);
}
}
}
}
}
}
}
return success;
}