Full core file support has been added for mach-o core files.

Tracking modules down when you have a UUID and a path has been improved.

DynamicLoaderDarwinKernel no longer parses mach-o load commands and it
now uses the memory based modules now that we can load modules from memory.

Added a target setting named "target.exec-search-paths" which can be used
to supply a list of directories to use when trying to look for executables.
This allows one or more directories to be used when searching for modules
that may not exist in the SDK/PDK. The target automatically adds the directory
for the main executable to this list so this should help us in tracking down
shared libraries and other binaries. 

llvm-svn: 150426
This commit is contained in:
Greg Clayton 2012-02-13 23:10:39 +00:00
parent 698452bc7e
commit c859e2d524
34 changed files with 1107 additions and 783 deletions

View File

@ -416,6 +416,7 @@ public:
const ConstString *object_name,
off_t object_offset,
lldb::ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr,
bool always_create = false);

View File

@ -262,6 +262,12 @@ public:
FinalizeSettingsController (lldb::UserSettingsControllerSP &controller_sp);
lldb::InstanceSettingsSP
GetDefaultInstanceSettings ()
{
return m_default_settings;
}
protected:
// -------------------------------------------------------------------------

View File

@ -298,6 +298,28 @@ public:
GetModuleFileSpecForHostAddress (const void *host_addr);
//------------------------------------------------------------------
/// If you have an executable that is in a bundle and want to get
/// back to the bundle directory from the path itself, this
/// function will change a path to a file within a bundle to the
/// bundle directory itself.
///
/// @param[in] file
/// A file spec that might point to a file in a bundle.
///
/// @param[out] bundle_directory
/// An object will be filled in with the bundle directory for
/// the bundle when \b true is returned. Otherwise \a file is
/// left untouched and \b false is returned.
///
/// @return
/// \b true if \a file was resolved in \a bundle_directory,
/// \b false otherwise.
//------------------------------------------------------------------
static bool
GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory);
//------------------------------------------------------------------
/// When executable files may live within a directory, where the
/// directory represents an executable bundle (like the MacOSX

View File

@ -505,6 +505,12 @@ public:
size_t
MemoryMapSectionData (const Section *section,
DataExtractor& section_data) const;
bool
IsInMemory () const
{
return m_memory_addr != LLDB_INVALID_ADDRESS;
}
protected:
//------------------------------------------------------------------
// Member variables.
@ -519,11 +525,6 @@ protected:
lldb::ProcessWP m_process_wp;
const lldb::addr_t m_memory_addr;
bool
IsInMemory () const
{
return m_memory_addr != LLDB_INVALID_ADDRESS;
}
//------------------------------------------------------------------
/// Sets the architecture for a module. At present the architecture
/// can only be set if it is invalid. It is not allowed to switch from

View File

@ -108,7 +108,8 @@ namespace lldb_private {
virtual Error
ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &arch,
lldb::ModuleSP &module_sp);
lldb::ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr);
//------------------------------------------------------------------
/// Resolves the FileSpec to a (possibly) remote path. Remote
@ -237,6 +238,7 @@ namespace lldb_private {
const ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);

View File

@ -1601,6 +1601,18 @@ public:
error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetShortPluginName());
return error;
}
//------------------------------------------------------------------
/// Get the dynamic loader plug-in for this process.
///
/// The default action is to let the DynamicLoader plug-ins check
/// the main executable and the DynamicLoader will select itself
/// automatically. Subclasses can override this if inspecting the
/// executable is not desired, or if Process subclasses can only
/// use a specific DynamicLoader plug-in.
//------------------------------------------------------------------
virtual DynamicLoader *
GetDynamicLoader ();
//------------------------------------------------------------------
/// Attach to an existing process using the process attach info.
@ -2400,7 +2412,7 @@ public:
/// vm_addr, \a buf, and \a size updated appropriately. Zero is
/// returned to indicate an error.
//------------------------------------------------------------------
size_t
virtual size_t
ReadMemory (lldb::addr_t vm_addr,
void *buf,
size_t size,
@ -2631,7 +2643,9 @@ public:
lldb::ModuleSP
ReadModuleFromMemory (const FileSpec& file_spec,
lldb::addr_t header_addr);
lldb::addr_t header_addr,
bool add_image_to_target,
bool load_sections_in_target);
//------------------------------------------------------------------
/// Attempt to get the attributes for a region of memory in the process.
@ -2976,12 +2990,6 @@ public:
const lldb::ABISP &
GetABI ();
DynamicLoader *
GetDynamicLoader ()
{
return m_dyld_ap.get();
}
OperatingSystem *
GetOperatingSystem ()
{

View File

@ -87,6 +87,19 @@ public:
return m_source_map;
}
FileSpecList &
GetExecutableSearchPaths ()
{
return m_exe_search_paths;
}
const FileSpecList &
GetExecutableSearchPaths () const
{
return m_exe_search_paths;
}
uint32_t
GetMaximumNumberOfChildrenToDisplay()
{
@ -225,6 +238,7 @@ protected:
int m_prefer_dynamic_value;
OptionValueBoolean m_skip_prologue;
PathMappingList m_source_map;
FileSpecList m_exe_search_paths;
uint32_t m_max_children_display;
uint32_t m_max_strlen_length;
OptionValueBoolean m_breakpoints_use_platform_avoid;
@ -273,6 +287,9 @@ public:
static lldb::UserSettingsControllerSP &
GetSettingsController ();
static FileSpecList
GetDefaultExecutableSearchPaths ();
static ArchSpec
GetDefaultArchitecture ();

View File

@ -46,7 +46,14 @@ SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr) :
{
ProcessSP process_sp (process.GetSP());
if (process_sp)
m_opaque_sp = process_sp->ReadModuleFromMemory (FileSpec(), header_addr);
{
const bool add_image_to_target = true;
const bool load_image_sections_in_target = true;
m_opaque_sp = process_sp->ReadModuleFromMemory (FileSpec(),
header_addr,
add_image_to_target,
load_image_sections_in_target);
}
}
const SBModule &

View File

@ -211,31 +211,43 @@ public:
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
if (core_file)
{
ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file));
char core_path[PATH_MAX];
core_file.GetPath(core_path, sizeof(core_path));
if (process_sp)
if (core_file.Exists())
{
// Seems wierd that we Launch a core file, but that is
// what we do!
error = process_sp->LoadCore();
FileSpec core_file_dir;
core_file_dir.GetDirectory() = core_file.GetDirectory();
target_sp->GetExecutableSearchPaths ().Append (core_file_dir);
if (error.Fail())
ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file));
if (process_sp)
{
result.AppendError(error.AsCString("can't find plug-in for core file"));
result.SetStatus (eReturnStatusFailed);
return false;
// Seems wierd that we Launch a core file, but that is
// what we do!
error = process_sp->LoadCore();
if (error.Fail())
{
result.AppendError(error.AsCString("can't find plug-in for core file"));
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName());
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
}
else
{
result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName());
result.SetStatus (eReturnStatusSuccessFinishNoResult);
result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path);
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path);
result.AppendErrorWithFormat ("Core file '%s' does not exist\n", core_path);
result.SetStatus (eReturnStatusFailed);
}
}

View File

@ -729,6 +729,7 @@ ModuleList::GetSharedModule
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr,
bool always_create

View File

@ -754,6 +754,14 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
}
#if !defined (__APPLE__) // see Host.mm
bool
Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle)
{
bundle.Clear();
return false;
}
bool
Host::ResolveExecutableInBundle (FileSpec &file)
{

View File

@ -137,6 +137,28 @@ Host::ThreadCreated (const char *thread_name)
}
}
bool
Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory)
{
#if defined (__APPLE__)
if (file.GetFileType () == FileSpec::eFileTypeDirectory)
{
char path[PATH_MAX];
if (file.GetPath(path, sizeof(path)))
{
CFCBundle bundle (path);
if (bundle.GetPath (path, sizeof(path)))
{
bundle_directory.SetFile (path, false);
return true;
}
}
}
#endif
bundle_directory.Clear();
return false;
}
bool
Host::ResolveExecutableInBundle (FileSpec &file)
@ -1215,7 +1237,8 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
lldb::ModuleSP exe_module_sp;
error = host_platform_sp->ResolveExecutable (exe_spec,
arch_spec,
exe_module_sp);
exe_module_sp,
NULL);
if (error.Fail())
return error;

View File

@ -367,7 +367,8 @@ LocateMacOSXFilesUsingDebugSymbols
if (out_exec_fspec)
{
CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));;
CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));
bool success = false;
if (dict.get())
{
char uuid_cstr_buf[64];
@ -381,10 +382,13 @@ LocateMacOSXFilesUsingDebugSymbols
{
++items_found;
out_exec_fspec->SetFile(path, path[0] == '~');
if (out_exec_fspec->Exists())
success = true;
}
}
}
else
if (!success)
{
// No dictionary, check near the dSYM bundle for an executable that matches...
if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))

View File

@ -55,6 +55,22 @@ CFCBundle::SetPath (const char *path)
return get() != NULL;
}
bool
CFCBundle::GetPath (char *dst, size_t dst_len)
{
CFBundleRef bundle = get();
if (bundle)
{
CFCReleaser<CFURLRef> bundle_url (CFBundleCopyBundleURL (bundle));
if (bundle_url.get())
{
Boolean resolveAgainstBase = 0;
return ::CFURLGetFileSystemRepresentation (bundle_url.get(), resolveAgainstBase, (UInt8 *)dst, dst_len) != 0;
}
}
return false;
}
CFStringRef
CFCBundle::GetIdentifier () const
{

View File

@ -33,6 +33,9 @@ public:
CFTypeRef
GetValueForInfoDictionaryKey(CFStringRef key) const;
bool
GetPath (char *dst, size_t dst_len);
bool
SetPath (const char *path);

View File

@ -154,6 +154,129 @@ DynamicLoaderDarwinKernel::Clear (bool clear_process)
}
bool
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (Process *process)
{
if (IsLoaded())
return true;
bool uuid_is_valid = uuid.IsValid();
Target &target = process->GetTarget();
ModuleSP memory_module_sp;
// Use the memory module as the module if we have one...
if (address != LLDB_INVALID_ADDRESS)
{
FileSpec file_spec;
if (module_sp)
file_spec = module_sp->GetFileSpec();
else
file_spec.SetFile (name, false);
memory_module_sp = process->ReadModuleFromMemory (file_spec, address, false, false);
if (memory_module_sp && !uuid_is_valid)
{
uuid = memory_module_sp->GetUUID();
uuid_is_valid = uuid.IsValid();
}
}
if (!module_sp)
{
bool uuid_is_valid = uuid.IsValid();
if (uuid_is_valid)
{
ModuleList &target_images = target.GetImages();
module_sp = target_images.FindModule(uuid);
if (!module_sp)
module_sp = target.GetSharedModule (FileSpec(), target.GetArchitecture(), &uuid);
}
}
if (memory_module_sp)
{
// Someone already supplied a file, make sure it is the right one.
if (module_sp)
{
if (module_sp->GetUUID() == memory_module_sp->GetUUID())
{
ObjectFile *ondisk_object_file = module_sp->GetObjectFile();
ObjectFile *memory_object_file = memory_module_sp->GetObjectFile();
if (memory_object_file && ondisk_object_file)
{
SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
SectionList *memory_section_list = memory_object_file->GetSectionList ();
if (memory_section_list && ondisk_section_list)
{
const uint32_t num_sections = ondisk_section_list->GetSize();
// There may be CTF sections in the memory image so we can't
// always just compare the number of sections (which are actually
// segments in mach-o parlance)
uint32_t sect_idx = 0;
const Section *memory_section;
const Section *ondisk_section;
// Always use the number of sections from the on disk file
// in case there are extra sections added to the memory image.
for (sect_idx=0; sect_idx<num_sections; ++sect_idx)
{
memory_section = memory_section_list->GetSectionAtIndex(sect_idx).get();
ondisk_section = ondisk_section_list->GetSectionAtIndex(sect_idx).get();
if (memory_section->GetName() != ondisk_section->GetName())
{
// Section count was the same, but the sections themselves do not match
module_sp.reset();
break;
}
}
if (module_sp)
{
for (sect_idx=0; sect_idx<num_sections; ++sect_idx)
{
memory_section = memory_section_list->GetSectionAtIndex(sect_idx).get();
ondisk_section = ondisk_section_list->GetSectionAtIndex(sect_idx).get();
target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section, memory_section->GetFileAddress());
}
if (num_sections > 0)
load_process_stop_id = process->GetStopID();
}
}
else
module_sp.reset(); // One or both section lists
}
else
module_sp.reset(); // One or both object files missing
}
else
module_sp.reset(); // UUID mismatch
}
// Use the memory module as the module if we didn't like the file
// module we either found or were supplied with
if (!module_sp)
{
module_sp = memory_module_sp;
// Load the memory image in the target as all adresses are already correct
bool changed = false;
target.GetImages().Append (memory_module_sp);
if (module_sp->SetLoadAddress (target, 0, changed))
load_process_stop_id = process->GetStopID();
}
}
bool is_loaded = IsLoaded();
if (so_address.IsValid())
{
if (is_loaded)
so_address.SetLoadAddress (address, &target);
else
target.GetImages().ResolveFileAddress (address, so_address);
}
return is_loaded;
}
//----------------------------------------------------------------------
// Load the kernel module and initialize the "m_kernel" member. Return
// true _only_ if the kernel is loaded the first time through (subsequent
@ -167,233 +290,42 @@ DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded()
{
m_kernel.Clear(false);
m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
if (m_kernel.module_sp)
strncpy(m_kernel.name, "mach_kernel", sizeof(m_kernel.name));
if (m_kernel.address == LLDB_INVALID_ADDRESS)
{
static ConstString mach_header_name ("_mh_execute_header");
static ConstString kext_summary_symbol ("gLoadedKextSummaries");
const Symbol *symbol = NULL;
symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
if (symbol)
m_kext_summary_header_ptr_addr = symbol->GetValue();
symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute);
if (symbol)
m_kernel.address = m_process->GetImageInfoAddress ();
if (m_kernel.address == LLDB_INVALID_ADDRESS && m_kernel.module_sp)
{
// The "_mh_execute_header" symbol is absolute and not a section based
// symbol that will have a valid address, so we need to resolve it...
m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address);
DataExtractor data; // Load command data
if (ReadMachHeader (m_kernel, &data))
{
if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable)
{
if (ParseLoadCommands (data, m_kernel))
UpdateImageLoadAddress (m_kernel);
// Update all image infos
ReadAllKextSummaries ();
}
}
else
{
m_kernel.Clear(false);
}
// We didn't get a hint from the process, so we will
// try the kernel at the address that it exists at in
// the file if we have one
ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile();
if (kernel_object_file)
m_kernel.address = kernel_object_file->GetHeaderAddress().GetFileAddress();
}
}
}
}
if (m_kernel.address != LLDB_INVALID_ADDRESS)
m_kernel.LoadImageUsingMemoryModule (m_process);
bool
DynamicLoaderDarwinKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr)
{
if (did_create_ptr)
*did_create_ptr = false;
const bool image_info_uuid_is_valid = image_info.uuid.IsValid();
if (image_info.module_sp)
{
if (image_info_uuid_is_valid)
if (m_kernel.IsLoaded())
{
if (image_info.module_sp->GetUUID() == image_info.uuid)
return true;
else
image_info.module_sp.reset();
static ConstString kext_summary_symbol ("gLoadedKextSummaries");
const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
if (symbol)
{
m_kext_summary_header_ptr_addr = symbol->GetValue();
// Update all image infos
ReadAllKextSummaries ();
}
}
else
return true;
}
ModuleList &target_images = m_process->GetTarget().GetImages();
if (image_info_uuid_is_valid)
image_info.module_sp = target_images.FindModule(image_info.uuid);
if (image_info.module_sp)
return true;
ArchSpec arch (image_info.GetArchitecture ());
if (can_create)
{
if (image_info_uuid_is_valid)
{
image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(),
arch,
&image_info.uuid);
if (did_create_ptr)
*did_create_ptr = image_info.module_sp;
m_kernel.Clear(false);
}
}
return image_info.module_sp;
}
bool
DynamicLoaderDarwinKernel::UpdateCommPageLoadAddress(Module *module)
{
bool changed = false;
if (module)
{
ObjectFile *image_object_file = module->GetObjectFile();
if (image_object_file)
{
SectionList *section_list = image_object_file->GetSectionList ();
if (section_list)
{
uint32_t num_sections = section_list->GetSize();
for (uint32_t i=0; i<num_sections; ++i)
{
Section* section = section_list->GetSectionAtIndex (i).get();
if (section)
{
const addr_t new_section_load_addr = section->GetFileAddress ();
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section);
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ()))
changed = true;
}
}
}
}
}
}
return changed;
}
//----------------------------------------------------------------------
// Update the load addresses for all segments in MODULE using the
// updated INFO that is passed in.
//----------------------------------------------------------------------
bool
DynamicLoaderDarwinKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info)
{
Module *module = info.module_sp.get();
bool changed = false;
if (module)
{
ObjectFile *image_object_file = module->GetObjectFile();
if (image_object_file)
{
SectionList *section_list = image_object_file->GetSectionList ();
if (section_list)
{
// We now know the slide amount, so go through all sections
// and update the load addresses with the correct values.
uint32_t num_segments = info.segments.size();
for (uint32_t i=0; i<num_segments; ++i)
{
const addr_t new_section_load_addr = info.segments[i].vmaddr;
if (section_list->FindSectionByName(info.segments[i].name))
{
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
if (section_sp)
{
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
changed = true;
}
}
else
{
Host::SystemLog (Host::eSystemLogWarning, "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
(uint64_t)new_section_load_addr,
image_object_file->GetFileSpec().GetDirectory().AsCString(),
image_object_file->GetFileSpec().GetFilename().AsCString());
}
}
else
{
// The segment name is empty which means this is a .o file.
// Object files in LLDB end up getting reorganized so that
// the segment name that is in the section is promoted into
// an actual segment, so we just need to go through all sections
// and slide them by a single amount.
uint32_t num_sections = section_list->GetSize();
for (uint32_t i=0; i<num_sections; ++i)
{
Section* section = section_list->GetSectionAtIndex (i).get();
if (section)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress() + new_section_load_addr))
changed = true;
}
}
}
}
}
}
}
return changed;
}
//----------------------------------------------------------------------
// Update the load addresses for all segments in MODULE using the
// updated INFO that is passed in.
//----------------------------------------------------------------------
bool
DynamicLoaderDarwinKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info)
{
Module *module = info.module_sp.get();
bool changed = false;
if (module)
{
ObjectFile *image_object_file = module->GetObjectFile();
if (image_object_file)
{
SectionList *section_list = image_object_file->GetSectionList ();
if (section_list)
{
uint32_t num_segments = info.segments.size();
for (uint32_t i=0; i<num_segments; ++i)
{
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
if (section_sp)
{
const addr_t old_section_load_addr = info.segments[i].vmaddr;
if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr))
changed = true;
}
else
{
Host::SystemLog (Host::eSystemLogWarning,
"warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
image_object_file->GetFileSpec().GetDirectory().AsCString(),
image_object_file->GetFileSpec().GetFilename().AsCString());
}
}
}
}
}
return changed;
}
//----------------------------------------------------------------------
// Static callback function that gets called when our DYLD notification
// breakpoint gets hit. We update all of our image infos and then
@ -513,18 +445,20 @@ DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr,
}
}
DataExtractor data; // Load command data
if (ReadMachHeader (kext_summaries[i], &data))
{
ParseLoadCommands (data, kext_summaries[i]);
}
kext_summaries[i].LoadImageUsingMemoryModule (m_process);
if (s)
{
if (kext_summaries[i].module_sp)
s->Printf("\n found kext: %s/%s\n",
kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(),
kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
{
if (kext_summaries[i].module_sp->GetFileSpec().GetDirectory())
s->Printf("\n found kext: %s/%s\n",
kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(),
kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
else
s->Printf("\n found kext: %s\n",
kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
}
else
s->Printf (" failed to locate/load.\n");
}
@ -547,20 +481,11 @@ DynamicLoaderDarwinKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::c
for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
{
m_kext_summaries.push_back(image_infos[idx]);
OSKextLoadedKextSummary &image_info = image_infos[idx];
m_kext_summaries.push_back(image_info);
if (FindTargetModule (image_infos[idx], true, NULL))
{
// UpdateImageLoadAddress will return true if any segments
// change load address. We need to check this so we don't
// mention that all loaded shared libraries are newly loaded
// each time we hit out dyld breakpoint since dyld will list all
// shared libraries each time.
if (UpdateImageLoadAddress (image_infos[idx]))
{
loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
}
}
if (image_info.module_sp && m_process->GetStopID() == image_info.load_process_stop_id)
loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
}
if (loaded_module_list.GetSize() > 0)
@ -644,6 +569,14 @@ DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr,
{
image_infos[i].reference_list = 0;
}
printf ("[%3u] %*.*s: address=0x%16.16llx, size=0x%16.16llx, version=0x%16.16llx, load_tag=0x%8.8x, flags=0x%8.8x\n",
i,
KERNEL_MODULE_MAX_NAME, KERNEL_MODULE_MAX_NAME, (char *)name_data,
image_infos[i].address,
image_infos[i].size,
image_infos[i].version,
image_infos[i].load_tag,
image_infos[i].flags);
}
if (i < image_infos.size())
image_infos.resize(i);
@ -678,215 +611,6 @@ DynamicLoaderDarwinKernel::ReadAllKextSummaries ()
return false;
}
//----------------------------------------------------------------------
// Read a mach_header at ADDR into HEADER, and also fill in the load
// command data into LOAD_COMMAND_DATA if it is non-NULL.
//
// Returns true if we succeed, false if we fail for any reason.
//----------------------------------------------------------------------
bool
DynamicLoaderDarwinKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data)
{
DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
Error error;
const bool prefer_file_cache = false;
size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address,
prefer_file_cache,
header_bytes.GetBytes(),
header_bytes.GetByteSize(),
error);
if (bytes_read == sizeof(llvm::MachO::mach_header))
{
uint32_t offset = 0;
::memset (&kext_summary.header, 0, sizeof(kext_summary.header));
// Get the magic byte unswapped so we can figure out what we are dealing with
DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), endian::InlHostByteOrder(), 4);
kext_summary.header.magic = data.GetU32(&offset);
Address load_cmd_addr = kext_summary.so_address;
data.SetByteOrder(DynamicLoaderDarwinKernel::GetByteOrderFromMagic(kext_summary.header.magic));
switch (kext_summary.header.magic)
{
case llvm::MachO::HeaderMagic32:
case llvm::MachO::HeaderMagic32Swapped:
data.SetAddressByteSize(4);
load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header));
break;
case llvm::MachO::HeaderMagic64:
case llvm::MachO::HeaderMagic64Swapped:
data.SetAddressByteSize(8);
load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64));
break;
default:
return false;
}
// Read the rest of dyld's mach header
if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1))
{
if (load_command_data == NULL)
return true; // We were able to read the mach_header and weren't asked to read the load command bytes
DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0));
size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr,
prefer_file_cache,
load_cmd_data_sp->GetBytes(),
load_cmd_data_sp->GetByteSize(),
error);
if (load_cmd_bytes_read == kext_summary.header.sizeofcmds)
{
// Set the load command data and also set the correct endian
// swap settings and the correct address size
load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds);
load_command_data->SetByteOrder(data.GetByteOrder());
load_command_data->SetAddressByteSize(data.GetAddressByteSize());
return true; // We successfully read the mach_header and the load command data
}
return false; // We weren't able to read the load command data
}
}
return false; // We failed the read the mach_header
}
//----------------------------------------------------------------------
// Parse the load commands for an image
//----------------------------------------------------------------------
uint32_t
DynamicLoaderDarwinKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info)
{
uint32_t offset = 0;
uint32_t cmd_idx;
Segment segment;
image_info.Clear (true);
for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++)
{
// Clear out any load command specific data from image_info since
// we are about to read it.
if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
{
llvm::MachO::load_command load_cmd;
uint32_t load_cmd_offset = offset;
load_cmd.cmd = data.GetU32 (&offset);
load_cmd.cmdsize = data.GetU32 (&offset);
switch (load_cmd.cmd)
{
case llvm::MachO::LoadCommandSegment32:
{
segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
// We are putting 4 uint32_t values 4 uint64_t values so
// we have to use multiple 32 bit gets below.
segment.vmaddr = data.GetU32 (&offset);
segment.vmsize = data.GetU32 (&offset);
segment.fileoff = data.GetU32 (&offset);
segment.filesize = data.GetU32 (&offset);
// Extract maxprot, initprot, nsects and flags all at once
data.GetU32(&offset, &segment.maxprot, 4);
image_info.segments.push_back (segment);
}
break;
case llvm::MachO::LoadCommandSegment64:
{
segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16);
// Extract vmaddr, vmsize, fileoff, and filesize all at once
data.GetU64(&offset, &segment.vmaddr, 4);
// Extract maxprot, initprot, nsects and flags all at once
data.GetU32(&offset, &segment.maxprot, 4);
image_info.segments.push_back (segment);
}
break;
case llvm::MachO::LoadCommandUUID:
image_info.uuid.SetBytes(data.GetData (&offset, 16));
break;
default:
break;
}
// Set offset to be the beginning of the next load command.
offset = load_cmd_offset + load_cmd.cmdsize;
}
}
#if 0
// No slide in the kernel...
// All sections listed in the dyld image info structure will all
// either be fixed up already, or they will all be off by a single
// slide amount that is determined by finding the first segment
// that is at file offset zero which also has bytes (a file size
// that is greater than zero) in the object file.
// Determine the slide amount (if any)
const size_t num_sections = image_info.segments.size();
for (size_t i = 0; i < num_sections; ++i)
{
// Iterate through the object file sections to find the
// first section that starts of file offset zero and that
// has bytes in the file...
if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0)
{
image_info.slide = image_info.address - image_info.segments[i].vmaddr;
// We have found the slide amount, so we can exit
// this for loop.
break;
}
}
#endif
if (image_info.uuid.IsValid())
{
bool did_create = false;
if (FindTargetModule(image_info, true, &did_create))
{
if (did_create)
image_info.module_create_stop_id = m_process->GetStopID();
}
}
return cmd_idx;
}
//----------------------------------------------------------------------
// Dump a Segment to the file handle provided.
//----------------------------------------------------------------------
void
DynamicLoaderDarwinKernel::Segment::PutToLog (Log *log, addr_t slide) const
{
if (log)
{
if (slide == 0)
log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
name.AsCString(""),
vmaddr + slide,
vmaddr + slide + vmsize);
else
log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
name.AsCString(""),
vmaddr + slide,
vmaddr + slide + vmsize,
slide);
}
}
const DynamicLoaderDarwinKernel::Segment *
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const
{
const size_t num_segments = segments.size();
for (size_t i=0; i<num_segments; ++i)
{
if (segments[i].name == name)
return &segments[i];
}
return NULL;
}
//----------------------------------------------------------------------
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
@ -927,8 +651,6 @@ DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
address, address+size, version, load_tag, flags, reference_list,
name);
}
for (uint32_t i=0; i<segments.size(); ++i)
segments[i].PutToLog(log, 0);
}
}
@ -971,7 +693,7 @@ DynamicLoaderDarwinKernel::PrivateInitialize(Process *process)
void
DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
{
if (m_break_id == LLDB_INVALID_BREAK_ID)
if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.module_sp)
{
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));

View File

@ -113,22 +113,9 @@ protected:
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
uint32_t
AddrByteSize()
GetAddrByteSize()
{
switch (m_kernel.header.magic)
{
case llvm::MachO::HeaderMagic32:
case llvm::MachO::HeaderMagic32Swapped:
return 4;
case llvm::MachO::HeaderMagic64:
case llvm::MachO::HeaderMagic64Swapped:
return 8;
default:
break;
}
return 0;
return m_kernel.GetAddressByteSize();
}
static lldb::ByteOrder
@ -152,46 +139,6 @@ protected:
}
return lldb::eByteOrderInvalid;
}
class Segment
{
public:
Segment() :
name(),
vmaddr(LLDB_INVALID_ADDRESS),
vmsize(0),
fileoff(0),
filesize(0),
maxprot(0),
initprot(0),
nsects(0),
flags(0)
{
}
lldb_private::ConstString name;
lldb::addr_t vmaddr;
lldb::addr_t vmsize;
lldb::addr_t fileoff;
lldb::addr_t filesize;
uint32_t maxprot;
uint32_t initprot;
uint32_t nsects;
uint32_t flags;
bool
operator==(const Segment& rhs) const
{
return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
}
void
PutToLog (lldb_private::Log *log,
lldb::addr_t slide) const;
};
enum
{
KERNEL_MODULE_MAX_NAME = 64u,
@ -206,7 +153,7 @@ protected:
{
char name[KERNEL_MODULE_MAX_NAME];
lldb::ModuleSP module_sp;
uint32_t module_create_stop_id;
uint32_t load_process_stop_id;
lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files
uint64_t address;
@ -215,12 +162,10 @@ protected:
uint32_t load_tag;
uint32_t flags;
uint64_t reference_list;
llvm::MachO::mach_header header; // The mach header for this image
std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
OSKextLoadedKextSummary() :
module_sp (),
module_create_stop_id (UINT32_MAX),
load_process_stop_id (UINT32_MAX),
uuid (),
so_address (),
address (LLDB_INVALID_ADDRESS),
@ -228,12 +173,16 @@ protected:
version (0),
load_tag (0),
flags (0),
reference_list (0),
header(),
segments()
reference_list (0)
{
name[0] = '\0';
}
bool
IsLoaded ()
{
return load_process_stop_id != UINT32_MAX;
}
void
Clear (bool load_cmd_data_only)
@ -248,30 +197,28 @@ protected:
flags = 0;
reference_list = 0;
name[0] = '\0';
::memset (&header, 0, sizeof(header));
}
module_sp.reset();
module_create_stop_id = UINT32_MAX;
uuid.Clear();
segments.clear();
load_process_stop_id = UINT32_MAX;
}
bool
operator == (const OSKextLoadedKextSummary& rhs) const
{
return address == rhs.address
&& size == rhs.size
//&& module_sp.get() == rhs.module_sp.get()
&& uuid == rhs.uuid
&& version == rhs.version
&& load_tag == rhs.load_tag
&& flags == rhs.flags
&& reference_list == rhs.reference_list
&& strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0
&& memcmp(&header, &rhs.header, sizeof(header)) == 0
&& segments == rhs.segments;
}
LoadImageUsingMemoryModule (lldb_private::Process *process);
// bool
// operator == (const OSKextLoadedKextSummary& rhs) const
// {
// return address == rhs.address
// && size == rhs.size
// //&& module_sp.get() == rhs.module_sp.get()
// && uuid == rhs.uuid
// && version == rhs.version
// && load_tag == rhs.load_tag
// && flags == rhs.flags
// && reference_list == rhs.reference_list
// && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0;
// }
//
bool
UUIDValid() const
{
@ -281,47 +228,27 @@ protected:
uint32_t
GetAddressByteSize ()
{
if (header.cputype)
{
if (header.cputype & llvm::MachO::CPUArchABI64)
return 8;
else
return 4;
}
if (module_sp)
return module_sp->GetArchitecture().GetAddressByteSize();
return 0;
}
lldb::ByteOrder
GetByteOrder()
{
switch (header.magic)
{
case llvm::MachO::HeaderMagic32: // MH_MAGIC
case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
return lldb::endian::InlHostByteOrder();
case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
return lldb::eByteOrderBig;
else
return lldb::eByteOrderLittle;
default:
assert (!"invalid header.magic value");
break;
}
if (module_sp)
return module_sp->GetArchitecture().GetByteOrder();
return lldb::endian::InlHostByteOrder();
}
lldb_private::ArchSpec
GetArchitecture () const
{
return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
if (module_sp)
return module_sp->GetArchitecture();
return lldb_private::ArchSpec ();
}
const Segment *
FindSegment (const lldb_private::ConstString &name) const;
void
PutToLog (lldb_private::Log *log) const;
@ -374,28 +301,12 @@ protected:
}
};
bool
ReadMachHeader (OSKextLoadedKextSummary& kext_summary,
lldb_private::DataExtractor *load_command_data);
void
RegisterNotificationCallbacks();
void
UnregisterNotificationCallbacks();
uint32_t
ParseLoadCommands (const lldb_private::DataExtractor& data,
OSKextLoadedKextSummary& dylib_info);
bool
UpdateImageLoadAddress(OSKextLoadedKextSummary& info);
bool
FindTargetModule (OSKextLoadedKextSummary &image_info,
bool can_create,
bool *did_create_ptr);
void
SetNotificationBreakpointIfNeeded ();
@ -417,17 +328,11 @@ protected:
uint32_t infos_count,
bool update_executable);
bool
UpdateCommPageLoadAddress (lldb_private::Module *module);
uint32_t
ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
uint32_t image_infos_count,
OSKextLoadedKextSummary::collection &image_infos);
bool
UnloadImageLoadAddress (OSKextLoadedKextSummary& info);
OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
lldb_private::Address m_kext_summary_header_ptr_addr;
lldb_private::Address m_kext_summary_header_addr;

View File

@ -210,7 +210,7 @@ DynamicLoaderMacOSXDYLD::LocateDYLD()
// Check the image info addr as it might point to the
// mach header for dyld, or it might point to the
// dyld_all_image_infos struct
addr_t shlib_addr = m_process->GetImageInfoAddress ();
const addr_t shlib_addr = m_process->GetImageInfoAddress ();
ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
uint8_t buf[4];
@ -310,8 +310,14 @@ DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &
arch,
image_info_uuid_is_valid ? &image_info.uuid : NULL);
if (!module_sp || module_sp->GetObjectFile() == NULL)
{
const bool add_image_to_target = true;
const bool load_image_sections_in_target = false;
module_sp = m_process->ReadModuleFromMemory (image_info.file_spec,
image_info.address);
image_info.address,
add_image_to_target,
load_image_sections_in_target);
}
if (did_create_ptr)
*did_create_ptr = module_sp;
@ -434,14 +440,22 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo&
{
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
if (section_sp)
{
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
// Don't ever load any __LINKEDIT sections since the ones in the shared
// cached will be coalesced into a single section and we will get warnings
// about multiple sections mapping to the same address.
if (section_sp->GetName() != g_section_name_LINKEDIT)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
changed = true;
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
changed = true;
}
}
}
else
@ -780,10 +794,14 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &i
&commpage_dbstr,
objfile->GetOffset() + commpage_section->GetFileOffset());
if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
{
const bool add_image_to_target = true;
const bool load_image_sections_in_target = false;
commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
image_infos[idx].address);
image_infos[idx].address,
add_image_to_target,
load_image_sections_in_target);
}
}
if (commpage_image_module_sp)
UpdateCommPageLoadAddress (commpage_image_module_sp.get());
@ -1249,8 +1267,14 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co
exe_arch_spec,
&image_infos[exe_idx].uuid);
if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
{
const bool add_image_to_target = true;
const bool load_image_sections_in_target = false;
exe_module_sp = m_process->ReadModuleFromMemory (image_infos[exe_idx].file_spec,
image_infos[exe_idx].address);
image_infos[exe_idx].address,
add_image_to_target,
load_image_sections_in_target);
}
}
if (exe_module_sp)

View File

@ -27,6 +27,8 @@
#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
@ -52,44 +54,162 @@ public:
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
int flavor;
uint32_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
while ((flavor = data.GetU32 (&offset)) > 0)
bool done = false;
while (!done)
{
uint32_t i;
uint32_t count = data.GetU32 (&offset);
switch (flavor)
int flavor = data.GetU32 (&offset);
if (flavor == 0)
done = true;
else
{
case 7:
case 8:
case 9:
// Goofy extra flavor inside state...
flavor = data.GetU32 (&offset);
count = data.GetU32 (&offset);
default:
break;
uint32_t i;
uint32_t count = data.GetU32 (&offset);
switch (flavor)
{
case GPRRegSet:
for (i=0; i<count; ++i)
(&gpr.rax)[i] = data.GetU64(&offset);
SetError (GPRRegSet, Read, 0);
done = true;
break;
case FPURegSet:
// TODO: fill in FPU regs....
//SetError (FPURegSet, Read, -1);
done = true;
break;
case EXCRegSet:
exc.trapno = data.GetU32(&offset);
exc.err = data.GetU32(&offset);
exc.faultvaddr = data.GetU64(&offset);
SetError (EXCRegSet, Read, 0);
done = true;
break;
case 7:
case 8:
case 9:
// fancy flavors that encapsulate of the the above
// falvors...
break;
default:
done = true;
break;
}
}
}
}
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return 0;
}
virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return 0;
}
virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return 0;
}
virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return 0;
}
virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return 0;
}
virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return 0;
}
};
switch (flavor)
class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386
{
public:
RegisterContextDarwin_i386_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
RegisterContextDarwin_i386 (thread, 0)
{
SetRegisterDataFrom_LC_THREAD (data);
}
virtual void
InvalidateAllRegisters ()
{
// Do nothing... registers are always valid...
}
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
uint32_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
bool done = false;
while (!done)
{
int flavor = data.GetU32 (&offset);
if (flavor == 0)
done = true;
else
{
case GPRRegSet:
for (i=0; i<count; ++i)
(&gpr.rax)[i] = data.GetU64(&offset);
SetError (GPRRegSet, Read, 0);
break;
case FPURegSet:
// TODO: fill in FPU regs....
//SetError (FPURegSet, Read, -1);
break;
case EXCRegSet:
exc.trapno = data.GetU32(&offset);
exc.err = data.GetU32(&offset);
exc.faultvaddr = data.GetU64(&offset);
SetError (EXCRegSet, Read, 0);
break;
uint32_t i;
uint32_t count = data.GetU32 (&offset);
switch (flavor)
{
case GPRRegSet:
for (i=0; i<count; ++i)
(&gpr.eax)[i] = data.GetU32(&offset);
SetError (GPRRegSet, Read, 0);
done = true;
break;
case FPURegSet:
// TODO: fill in FPU regs....
//SetError (FPURegSet, Read, -1);
done = true;
break;
case EXCRegSet:
exc.trapno = data.GetU32(&offset);
exc.err = data.GetU32(&offset);
exc.faultvaddr = data.GetU32(&offset);
SetError (EXCRegSet, Read, 0);
done = true;
break;
case 7:
case 8:
case 9:
// fancy flavors that encapsulate of the the above
// falvors...
break;
default:
done = true;
break;
}
}
}
}
@ -131,6 +251,87 @@ protected:
}
};
class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm
{
public:
RegisterContextDarwin_arm_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
RegisterContextDarwin_arm (thread, 0)
{
SetRegisterDataFrom_LC_THREAD (data);
}
virtual void
InvalidateAllRegisters ()
{
// Do nothing... registers are always valid...
}
void
SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
{
uint32_t offset = 0;
SetError (GPRRegSet, Read, -1);
SetError (FPURegSet, Read, -1);
SetError (EXCRegSet, Read, -1);
int flavor = data.GetU32 (&offset);
uint32_t count = data.GetU32 (&offset);
switch (flavor)
{
case GPRRegSet:
for (uint32_t i=0; i<count; ++i)
gpr.r[i] = data.GetU32(&offset);
SetError (GPRRegSet, Read, 0);
break;
case FPURegSet:
// TODO: fill in FPU regs....
//SetError (FPURegSet, Read, -1);
break;
case EXCRegSet:
exc.exception = data.GetU32(&offset);
exc.fsr = data.GetU32(&offset);
exc.far = data.GetU32(&offset);
SetError (EXCRegSet, Read, 0);
break;
}
}
protected:
virtual int
DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
{
return 0;
}
virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return 0;
}
virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return 0;
}
virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return 0;
}
virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return 0;
}
virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return 0;
}
};
#define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008
void
@ -1017,9 +1218,11 @@ ObjectFileMachO::ParseSymtab (bool minimize)
const addr_t symoff_addr = linkedit_load_addr + symtab_load_command.symoff - linkedit_file_offset;
const addr_t stroff_addr = linkedit_load_addr + symtab_load_command.stroff - linkedit_file_offset;
DataBufferSP nlist_data_sp (ReadMemory (process_sp, symoff_addr, nlist_data_byte_size));
if (nlist_data_sp)
nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize());
DataBufferSP strtab_data_sp (ReadMemory (process_sp, stroff_addr, strtab_data_byte_size));
nlist_data.SetData (nlist_data_sp, 0, nlist_data_sp->GetByteSize());
strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
if (strtab_data_sp)
strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
}
}
else
@ -2104,12 +2307,24 @@ ObjectFileMachO::GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &th
lldb::RegisterContextSP reg_ctx_sp;
const FileRangeArray::Entry *thread_context_file_range = m_thread_context_offsets.GetEntryAtIndex (idx);
if (thread_context_file_range)
DataExtractor data (m_data,
thread_context_file_range->GetRangeBase(),
thread_context_file_range->GetByteSize());
switch (m_header.cputype)
{
DataExtractor data (m_data,
thread_context_file_range->GetRangeBase(),
thread_context_file_range->GetByteSize());
reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
case llvm::MachO::CPUTypeARM:
reg_ctx_sp.reset (new RegisterContextDarwin_arm_Mach (thread, data));
break;
case llvm::MachO::CPUTypeI386:
reg_ctx_sp.reset (new RegisterContextDarwin_i386_Mach (thread, data));
break;
case llvm::MachO::CPUTypeX86_64:
reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
break;
}
return reg_ctx_sp;
}

View File

@ -46,7 +46,8 @@ PlatformDarwin::~PlatformDarwin()
Error
PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
Error error;
// Nothing special to do here, just use the actual file and architecture
@ -84,7 +85,8 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
{
error = m_remote_platform_sp->ResolveExecutable (exe_file,
exe_arch,
exe_module_sp);
exe_module_sp,
module_search_paths_ptr);
}
else
{
@ -111,6 +113,7 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
module_search_paths_ptr,
NULL,
NULL);
@ -139,6 +142,7 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
module_search_paths_ptr,
NULL,
NULL);
// Did we find an executable using one of the
@ -171,6 +175,100 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
}
Error
PlatformDarwin::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
Error error;
module_sp.reset();
if (IsRemote())
{
// If we have a remote platform always, let it try and locate
// the shared module first.
if (m_remote_platform_sp)
{
error = m_remote_platform_sp->GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
module_search_paths_ptr,
old_module_sp_ptr,
did_create_ptr);
}
}
if (!module_sp)
{
// Fall back to the local platform and find the file locally
error = Platform::GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
module_search_paths_ptr,
old_module_sp_ptr,
did_create_ptr);
if (!module_sp && module_search_paths_ptr && platform_file)
{
// We can try to pull off part of the file path up to the bundle
// directory level and try any module search paths...
FileSpec bundle_directory;
if (Host::GetBundleDirectory (platform_file, bundle_directory))
{
char platform_path[PATH_MAX];
char bundle_dir[PATH_MAX];
platform_file.GetPath (platform_path, sizeof(platform_path));
const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
char new_path[PATH_MAX];
size_t num_module_search_paths = module_search_paths_ptr->GetSize();
for (size_t i=0; i<num_module_search_paths; ++i)
{
const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
if (search_path_len < sizeof(new_path))
{
snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
FileSpec new_file_spec (new_path, false);
if (new_file_spec.Exists())
{
Error new_error (Platform::GetSharedModule (new_file_spec,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
NULL,
old_module_sp_ptr,
did_create_ptr));
if (module_sp)
{
module_sp->SetPlatformFileSpec(new_file_spec);
return new_error;
}
}
}
}
}
}
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
size_t
PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{

View File

@ -30,7 +30,19 @@ public:
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr);
virtual lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
virtual size_t
GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,

View File

@ -128,53 +128,6 @@ PlatformMacOSX::GetFile (const FileSpec &platform_file,
return Error();
}
Error
PlatformMacOSX::GetSharedModule (const FileSpec &platform_file,
const ArchSpec &arch,
const UUID *uuid_ptr,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
Error error;
module_sp.reset();
if (IsRemote())
{
// If we have a remote platform always, let it try and locate
// the shared module first.
if (m_remote_platform_sp)
{
error = m_remote_platform_sp->GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
}
if (!module_sp)
{
// Fall back to the local platform and find the file locally
error = Platform::GetSharedModule (platform_file,
arch,
uuid_ptr,
object_name_ptr,
object_offset,
module_sp,
old_module_sp_ptr,
did_create_ptr);
}
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
bool
PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{

View File

@ -81,16 +81,6 @@ public:
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx,
lldb_private::ArchSpec &arch);

View File

@ -121,7 +121,8 @@ PlatformRemoteiOS::GetStatus (Stream &strm)
Error
PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
Error error;
// Nothing special to do here, just use the actual file and architecture
@ -148,6 +149,7 @@ PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
NULL,
NULL,
NULL);
@ -168,6 +170,7 @@ PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
NULL,
NULL,
NULL);
// Did we find an executable using one of the
@ -429,6 +432,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
@ -441,8 +445,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file,
error = GetFile (platform_file, uuid_ptr, local_file);
if (error.Success())
{
error = ResolveExecutable (local_file, arch, module_sp);
error = ResolveExecutable (local_file, arch, module_sp, module_search_paths_ptr);
}
else
{
@ -453,6 +456,7 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file,
object_name_ptr,
object_offset,
module_sp,
module_search_paths_ptr,
old_module_sp_ptr,
did_create_ptr,
always_create);

View File

@ -76,7 +76,8 @@ public:
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr);
virtual const char *
GetDescription ()
@ -92,13 +93,14 @@ public:
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
virtual lldb_private::Error
GetSharedModule (const lldb_private::FileSpec &platform_file,
const lldb_private::ArchSpec &arch,
const lldb_private::UUID *uuid_ptr,
const lldb_private::ConstString *object_name_ptr,
off_t object_offset,
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr);

View File

@ -92,7 +92,8 @@ PlatformRemoteGDBServer::GetDescription ()
Error
PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
Error error;
error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");

View File

@ -72,7 +72,8 @@ public:
virtual lldb_private::Error
ResolveExecutable (const lldb_private::FileSpec &exe_file,
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &module_sp);
lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr);
virtual const char *
GetDescription ();

View File

@ -13,6 +13,7 @@
// C++ Includes
#include "llvm/Support/MachO.h"
#include "llvm/Support/MathExtras.h"
// Other libraries and framework includes
#include "lldb/Core/Debugger.h"
@ -27,6 +28,9 @@
#include "ThreadMachCore.h"
#include "StopInfoMachException.h"
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
using namespace lldb;
using namespace lldb_private;
@ -67,7 +71,15 @@ ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name)
// For now we are just making sure the file exists for a given module
if (!m_core_module_sp && m_core_file.Exists())
{
Error error (ModuleList::GetSharedModule(m_core_file, target.GetArchitecture(), NULL, NULL, 0, m_core_module_sp, NULL, NULL));
Error error (ModuleList::GetSharedModule (m_core_file,
target.GetArchitecture(),
NULL,
NULL,
0,
m_core_module_sp,
NULL,
NULL,
NULL));
if (m_core_module_sp)
{
@ -92,7 +104,8 @@ ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileS
m_core_aranges (),
m_core_module_sp (),
m_core_file (core_file),
m_shlib_addr (LLDB_INVALID_ADDRESS)
m_dyld_addr (LLDB_INVALID_ADDRESS),
m_dyld_plugin_name ()
{
}
@ -130,6 +143,61 @@ ProcessMachCore::GetPluginVersion()
return 1;
}
bool
ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr)
{
llvm::MachO::mach_header header;
Error error;
if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header))
return false;
if (header.magic == llvm::MachO::HeaderMagic32Swapped ||
header.magic == llvm::MachO::HeaderMagic64Swapped)
{
header.magic = llvm::ByteSwap_32(header.magic);
header.cputype = llvm::ByteSwap_32(header.cputype);
header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
header.filetype = llvm::ByteSwap_32(header.filetype);
header.ncmds = llvm::ByteSwap_32(header.ncmds);
header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
header.flags = llvm::ByteSwap_32(header.flags);
}
// TODO: swap header if needed...
//printf("0x%16.16llx: magic = 0x%8.8x, file_type= %u\n", vaddr, header.magic, header.filetype);
if (header.magic == llvm::MachO::HeaderMagic32 ||
header.magic == llvm::MachO::HeaderMagic64)
{
// Check MH_EXECUTABLE to see if we can find the mach image
// that contains the shared library list. The dynamic loader
// (dyld) is what contains the list for user applications,
// and the mach kernel contains a global that has the list
// of kexts to load
switch (header.filetype)
{
case llvm::MachO::HeaderFileTypeDynamicLinkEditor:
//printf("0x%16.16llx: file_type = MH_DYLINKER\n", vaddr);
// Address of dyld "struct mach_header" in the core file
m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
m_dyld_addr = addr;
return true;
case llvm::MachO::HeaderFileTypeExecutable:
//printf("0x%16.16llx: file_type = MH_EXECUTE\n", vaddr);
// Check MH_EXECUTABLE file types to see if the dynamic link object flag
// is NOT set. If it isn't, then we have a mach_kernel.
if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
{
m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
// Address of the mach kernel "struct mach_header" in the core file.
m_dyld_addr = addr;
return true;
}
break;
}
}
return false;
}
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
@ -137,7 +205,12 @@ Error
ProcessMachCore::DoLoadCore ()
{
Error error;
DataExtractor data;
if (!m_core_module_sp)
{
error.SetErrorString ("invalid core module");
return error;
}
ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
if (core_objfile == NULL)
{
@ -157,6 +230,13 @@ ProcessMachCore::DoLoadCore ()
error.SetErrorString ("core file has no sections");
return error;
}
llvm::MachO::mach_header header;
DataExtractor data (&header,
sizeof(header),
m_core_module_sp->GetArchitecture().GetByteOrder(),
m_core_module_sp->GetArchitecture().GetAddressByteSize());
bool ranges_are_sorted = true;
addr_t vm_addr = 0;
for (uint32_t i=0; i<num_sections; ++i)
@ -165,44 +245,6 @@ ProcessMachCore::DoLoadCore ()
if (section)
{
lldb::addr_t section_vm_addr = section->GetFileAddress();
if (m_shlib_addr == LLDB_INVALID_ADDRESS)
{
if (core_objfile->ReadSectionData (section, data))
{
uint32_t offset = 0;
llvm::MachO::mach_header header;
if (data.GetU32(&offset, &header, sizeof(header)/sizeof(uint32_t)))
{
if (header.magic == llvm::MachO::HeaderMagic32 ||
header.magic == llvm::MachO::HeaderMagic64)
{
// Check MH_EXECUTABLE to see if we can find the mach image
// that contains the shared library list. The dynamic loader
// (dyld) is what contains the list for user applications,
// and the mach kernel contains a global that has the list
// of kexts to load
switch (header.filetype)
{
case llvm::MachO::HeaderFileTypeDynamicLinkEditor:
// Address of dyld "struct mach_header" in the core file
m_shlib_addr = section_vm_addr;
break;
case llvm::MachO::HeaderFileTypeExecutable:
// Check MH_EXECUTABLE file types to see if the dynamic link object flag
// is NOT set. If it isn't, then we have a mach_kernel.
if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
{
// Address of the mach kernel "struct mach_header" in the core file.
m_shlib_addr = section_vm_addr;
}
break;
}
}
}
}
}
FileRange file_range (section->GetFileOffset(), section->GetFileSize());
VMRangeToFileOffset::Entry range_entry (section_vm_addr,
section->GetByteSize(),
@ -212,29 +254,91 @@ ProcessMachCore::DoLoadCore ()
ranges_are_sorted = false;
vm_addr = section->GetFileAddress();
VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
// printf ("LC_SEGMENT[%u] arange=[0x%16.16llx - 0x%16.16llx), frange=[0x%8.8x - 0x%8.8x)\n",
// i,
// range_entry.GetRangeBase(),
// range_entry.GetRangeEnd(),
// range_entry.data.GetRangeBase(),
// range_entry.data.GetRangeEnd());
if (last_entry &&
last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
{
last_entry->SetRangeEnd (range_entry.GetRangeEnd());
last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
//puts("combine");
}
else
{
m_core_aranges.Append(range_entry);
}
// After we have added this section to our m_core_aranges map,
// we can check the start of the section to see if it might
// contain dyld for user space apps, or the mach kernel file
// for kernel cores.
if (m_dyld_addr == LLDB_INVALID_ADDRESS)
GetDynamicLoaderAddress (section_vm_addr);
}
}
if (!ranges_are_sorted)
{
m_core_aranges.Sort();
}
if (!m_target.GetArchitecture().IsValid())
m_target.SetArchitecture(m_core_module_sp->GetArchitecture());
// Even if the architecture is set in the target, we need to override
// it to match the core file which is always single arch.
ArchSpec arch (m_core_module_sp->GetArchitecture());
if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
{
arch.SetTriple ("i386", m_target.GetPlatform().get());
}
if (arch.IsValid())
m_target.SetArchitecture(arch);
if (m_dyld_addr == LLDB_INVALID_ADDRESS)
{
// Check the magic kernel address for the mach image header address in case
// it is there.
if (arch.GetAddressByteSize() == 8)
{
Error header_addr_error;
addr_t header_addr = ReadPointerFromMemory (0xffffff8000002010ull, header_addr_error);
if (header_addr != LLDB_INVALID_ADDRESS)
GetDynamicLoaderAddress (header_addr);
}
// if (m_dyld_addr == LLDB_INVALID_ADDRESS)
// {
// // We haven't found our dyld or mach_kernel yet,
// // so we need to exhaustively look
// const size_t num_core_aranges = m_core_aranges.GetSize();
// bool done = false;
// for (size_t i=0; !done && i<num_core_aranges; ++i)
// {
// const addr_t start_vaddr = m_core_aranges.GetEntryRef(i).GetRangeBase();
// const addr_t end_vaddr = m_core_aranges.GetEntryRef(i).GetRangeEnd();
// // printf("core_arange[%u] [0x%16.16llx - 0x%16.16llx)\n", (uint32_t)i, start_vaddr, end_vaddr);
//
// for (addr_t vaddr = start_vaddr; !done && start_vaddr < end_vaddr; vaddr += 0x1000)
// {
// done = GetDynamicLoaderAddress (vaddr);
// }
// }
// }
}
return error;
}
lldb_private::DynamicLoader *
ProcessMachCore::GetDynamicLoader ()
{
if (m_dyld_ap.get() == NULL)
m_dyld_ap.reset (DynamicLoader::FindPlugin(this, m_dyld_plugin_name.empty() ? NULL : m_dyld_plugin_name.c_str()));
return m_dyld_ap.get();
}
uint32_t
ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
@ -292,6 +396,14 @@ ProcessMachCore::IsAlive ()
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
size_t
ProcessMachCore::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
// Don't allow the caching that lldb_private::Process::ReadMemory does
// since in core files we have it all cached our our core file anyway.
return DoReadMemory (addr, buf, size, error);
}
size_t
ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
@ -340,7 +452,7 @@ ProcessMachCore::Initialize()
addr_t
ProcessMachCore::GetImageInfoAddress()
{
return m_shlib_addr;
return m_dyld_addr;
}

View File

@ -68,6 +68,9 @@ public:
virtual lldb_private::Error
DoLoadCore ();
virtual lldb_private::DynamicLoader *
GetDynamicLoader ();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@ -98,6 +101,9 @@ public:
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
virtual size_t
ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
virtual size_t
DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
@ -120,6 +126,9 @@ protected:
return m_core_module_sp->GetObjectFile();
}
private:
bool
GetDynamicLoaderAddress (lldb::addr_t addr);
//------------------------------------------------------------------
// For ProcessMachCore only
//------------------------------------------------------------------
@ -129,7 +138,8 @@ private:
VMRangeToFileOffset m_core_aranges;
lldb::ModuleSP m_core_module_sp;
lldb_private::FileSpec m_core_file;
lldb::addr_t m_shlib_addr;
lldb::addr_t m_dyld_addr;
std::string m_dyld_plugin_name;
DISALLOW_COPY_AND_ASSIGN (ProcessMachCore);
};

View File

@ -94,6 +94,7 @@ Platform::GetSharedModule (const FileSpec &platform_file,
const ConstString *object_name_ptr,
off_t object_offset,
ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr,
bool *did_create_ptr)
{
@ -111,6 +112,7 @@ Platform::GetSharedModule (const FileSpec &platform_file,
object_name_ptr,
object_offset,
module_sp,
module_search_paths_ptr,
old_module_sp_ptr,
did_create_ptr,
always_create);
@ -403,7 +405,8 @@ Platform::SetOSVersion (uint32_t major,
Error
Platform::ResolveExecutable (const FileSpec &exe_file,
const ArchSpec &exe_arch,
lldb::ModuleSP &exe_module_sp)
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr)
{
Error error;
if (exe_file.Exists())
@ -416,6 +419,7 @@ Platform::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
module_search_paths_ptr,
NULL,
NULL);
}
@ -433,6 +437,7 @@ Platform::ResolveExecutable (const FileSpec &exe_file,
NULL,
0,
exe_module_sp,
module_search_paths_ptr,
NULL,
NULL);
// Did we find an executable using one of the

View File

@ -2193,14 +2193,23 @@ Process::DeallocateMemory (addr_t ptr)
}
ModuleSP
Process::ReadModuleFromMemory (const FileSpec& file_spec, lldb::addr_t header_addr)
Process::ReadModuleFromMemory (const FileSpec& file_spec,
lldb::addr_t header_addr,
bool add_image_to_target,
bool load_sections_in_target)
{
ModuleSP module_sp (new Module (file_spec, shared_from_this(), header_addr));
if (module_sp)
{
m_target.GetImages().Append(module_sp);
bool changed = false;
module_sp->SetLoadAddress (m_target, 0, changed);
if (add_image_to_target)
{
m_target.GetImages().Append(module_sp);
if (load_sections_in_target)
{
bool changed = false;
module_sp->SetLoadAddress (m_target, 0, changed);
}
}
}
return module_sp;
}
@ -2306,9 +2315,9 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
DidLaunch ();
m_dyld_ap.reset (DynamicLoader::FindPlugin (this, NULL));
if (m_dyld_ap.get())
m_dyld_ap->DidLaunch();
DynamicLoader *dyld = GetDynamicLoader ();
if (dyld)
dyld->DidLaunch();
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// This delays passing the stopped event to listeners till DidLaunch gets
@ -2349,7 +2358,11 @@ Process::LoadCore ()
else
StartPrivateStateThread ();
CompleteAttach ();
DynamicLoader *dyld = GetDynamicLoader ();
if (dyld)
dyld->DidAttach();
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// We successfully loaded a core file, now pretend we stopped so we can
// show all of the threads in the core file and explore the crashed
// state.
@ -2359,6 +2372,13 @@ Process::LoadCore ()
return error;
}
DynamicLoader *
Process::GetDynamicLoader ()
{
if (m_dyld_ap.get() == NULL)
m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
return m_dyld_ap.get();
}
Process::NextEventAction::EventActionResult
@ -2622,9 +2642,9 @@ Process::CompleteAttach ()
// We have completed the attach, now it is time to find the dynamic loader
// plug-in
m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
if (m_dyld_ap.get())
m_dyld_ap->DidAttach();
DynamicLoader *dyld = GetDynamicLoader ();
if (dyld)
dyld->DidAttach();
m_os_ap.reset (OperatingSystem::FindPlugin (this, NULL));
// Figure out which one is the executable, and set that in our target:

View File

@ -74,6 +74,9 @@ SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr
load_addr);
}
if (section->GetByteSize() == 0)
return false; // No change
Mutex::Locker locker(m_mutex);
sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section);
if (sta_pos != m_sect_to_addr.end())
@ -89,7 +92,19 @@ SectionLoadList::SetSectionLoadAddress (const Section *section, addr_t load_addr
addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
if (ats_pos != m_addr_to_sect.end())
{
assert (section != ats_pos->second);
if (section != ats_pos->second)
{
Module *module = section->GetModule();
if (module)
{
module->ReportWarning ("address 0x%16.16llx maps to more than one section: %s.%s and %s.%s",
load_addr,
module->GetFileSpec().GetFilename().GetCString(),
section->GetName().GetCString(),
ats_pos->second->GetModule()->GetFileSpec().GetFilename().GetCString(),
ats_pos->second->GetName().GetCString());
}
}
ats_pos->second = section;
}
else

View File

@ -869,6 +869,7 @@ Target::SetArchitecture (const ArchSpec &arch_spec)
NULL,
0,
executable_sp,
&GetExecutableSearchPaths(),
NULL,
NULL);
@ -1227,7 +1228,15 @@ Target::GetSharedModule
if (m_image_search_paths.RemapPath (file_spec.GetDirectory(), transformed_spec.GetDirectory()))
{
transformed_spec.GetFilename() = file_spec.GetFilename();
error = ModuleList::GetSharedModule (transformed_spec, arch, uuid_ptr, object_name, object_offset, module_sp, &old_module_sp, &did_create_module);
error = ModuleList::GetSharedModule (transformed_spec,
arch,
uuid_ptr,
object_name,
object_offset,
module_sp,
&GetExecutableSearchPaths(),
&old_module_sp,
&did_create_module);
}
}
@ -1242,6 +1251,7 @@ Target::GetSharedModule
object_name,
object_offset,
module_sp,
&GetExecutableSearchPaths(),
&old_module_sp,
&did_create_module);
}
@ -1395,6 +1405,20 @@ Target::GetSettingsController ()
return g_settings_controller_sp;
}
FileSpecList
Target::GetDefaultExecutableSearchPaths ()
{
lldb::UserSettingsControllerSP settings_controller_sp (GetSettingsController());
if (settings_controller_sp)
{
lldb::InstanceSettingsSP instance_settings_sp (settings_controller_sp->GetDefaultInstanceSettings ());
if (instance_settings_sp)
return static_cast<TargetInstanceSettings *>(instance_settings_sp.get())->GetExecutableSearchPaths ();
}
return FileSpecList();
}
ArchSpec
Target::GetDefaultArchitecture ()
{
@ -2016,6 +2040,7 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name)
#define TSC_PREFER_DYNAMIC "prefer-dynamic-value"
#define TSC_SKIP_PROLOGUE "skip-prologue"
#define TSC_SOURCE_MAP "source-map"
#define TSC_EXE_SEARCH_PATHS "exec-search-paths"
#define TSC_MAX_CHILDREN "max-children-count"
#define TSC_MAX_STRLENSUMMARY "max-string-summary-length"
#define TSC_PLATFORM_AVOID "breakpoints-use-platform-avoid-list"
@ -2057,6 +2082,13 @@ GetSettingNameForSourcePathMap ()
return g_const_string;
}
static const ConstString &
GetSettingNameForExecutableSearchPaths ()
{
static ConstString g_const_string (TSC_EXE_SEARCH_PATHS);
return g_const_string;
}
static const ConstString &
GetSettingNameForSkipPrologue ()
{
@ -2193,6 +2225,7 @@ TargetInstanceSettings::TargetInstanceSettings
m_prefer_dynamic_value (2),
m_skip_prologue (true, true),
m_source_map (NULL, NULL),
m_exe_search_paths (),
m_max_children_display(256),
m_max_strlen_length(1024),
m_breakpoints_use_platform_avoid (true, true),
@ -2231,6 +2264,7 @@ TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rh
m_prefer_dynamic_value (rhs.m_prefer_dynamic_value),
m_skip_prologue (rhs.m_skip_prologue),
m_source_map (rhs.m_source_map),
m_exe_search_paths (rhs.m_exe_search_paths),
m_max_children_display (rhs.m_max_children_display),
m_max_strlen_length (rhs.m_max_strlen_length),
m_breakpoints_use_platform_avoid (rhs.m_breakpoints_use_platform_avoid),
@ -2265,6 +2299,7 @@ TargetInstanceSettings::operator= (const TargetInstanceSettings &rhs)
m_prefer_dynamic_value = rhs.m_prefer_dynamic_value;
m_skip_prologue = rhs.m_skip_prologue;
m_source_map = rhs.m_source_map;
m_exe_search_paths = rhs.m_exe_search_paths;
m_max_children_display = rhs.m_max_children_display;
m_max_strlen_length = rhs.m_max_strlen_length;
m_breakpoints_use_platform_avoid = rhs.m_breakpoints_use_platform_avoid;
@ -2357,6 +2392,49 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n
if (ok)
m_max_strlen_length = new_value;
}
else if (var_name == GetSettingNameForExecutableSearchPaths())
{
switch (op)
{
case eVarSetOperationReplace:
case eVarSetOperationInsertBefore:
case eVarSetOperationInsertAfter:
case eVarSetOperationRemove:
default:
break;
case eVarSetOperationAssign:
m_exe_search_paths.Clear();
// Fall through to append....
case eVarSetOperationAppend:
{
Args args(value);
const uint32_t argc = args.GetArgumentCount();
if (argc > 0)
{
const char *exe_search_path_dir;
for (uint32_t idx = 0; (exe_search_path_dir = args.GetArgumentAtIndex(idx)) != NULL; ++idx)
{
FileSpec file_spec;
file_spec.GetDirectory().SetCString(exe_search_path_dir);
FileSpec::FileType file_type = file_spec.GetFileType();
if (file_type == FileSpec::eFileTypeDirectory || file_type == FileSpec::eFileTypeInvalid)
{
m_exe_search_paths.Append(file_spec);
}
else
{
err.SetErrorStringWithFormat("executable search path '%s' exists, but it does not resolve to a directory", exe_search_path_dir);
}
}
}
}
break;
case eVarSetOperationClear:
m_exe_search_paths.Clear();
break;
}
}
else if (var_name == GetSettingNameForSourcePathMap ())
{
switch (op)
@ -2487,6 +2565,16 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
else
value.AppendString ("false");
}
else if (var_name == GetSettingNameForExecutableSearchPaths())
{
if (m_exe_search_paths.GetSize())
{
for (size_t i = 0, n = m_exe_search_paths.GetSize(); i < n; ++i)
{
value.AppendString(m_exe_search_paths.GetFileSpecAtIndex (i).GetDirectory().AsCString());
}
}
}
else if (var_name == GetSettingNameForSourcePathMap ())
{
if (m_source_map.GetSize())
@ -2670,6 +2758,7 @@ Target::SettingsController::instance_settings_table[] =
{ TSC_PREFER_DYNAMIC , eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." },
{ TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." },
{ TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." },
{ TSC_EXE_SEARCH_PATHS , eSetVarTypeArray , NULL , NULL, false, false, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
{ TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." },
{ TSC_MAX_STRLENSUMMARY , eSetVarTypeInt , "1024" , NULL, true, false, "Maximum number of characters to show when using %s in summary strings." },
{ TSC_PLATFORM_AVOID , eSetVarTypeBoolean, "true" , NULL, false, false, "Consult the platform module avoid list when setting non-module specific breakpoints." },

View File

@ -92,6 +92,16 @@ TargetList::CreateTarget (Debugger &debugger,
get_dependent_files,
platform_sp,
target_sp);
if (target_sp)
{
if (file.GetDirectory())
{
FileSpec file_dir;
file_dir.GetDirectory() = file.GetDirectory();
target_sp->GetExecutableSearchPaths ().Append (file_dir);
}
}
return error;
}
@ -120,7 +130,12 @@ TargetList::CreateTarget
FileSpec resolved_file(file);
if (platform_sp)
error = platform_sp->ResolveExecutable (file, arch, exe_module_sp);
{
FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
error = platform_sp->ResolveExecutable (file, arch,
exe_module_sp,
executable_search_paths.GetSize() ? &executable_search_paths : NULL);
}
if (error.Success() && exe_module_sp)
{