[lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).
This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).
Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 08:23:27 +01:00
|
|
|
//===-- Platform.cpp ------------------------------------------------------===//
|
2011-03-08 22:40:15 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-03-08 22:40:15 +00:00
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
#include <algorithm>
|
2018-04-05 16:59:36 +00:00
|
|
|
#include <csignal>
|
2015-03-10 01:15:28 +00:00
|
|
|
#include <fstream>
|
2019-02-11 23:13:08 +00:00
|
|
|
#include <memory>
|
2023-01-07 13:43:00 -08:00
|
|
|
#include <optional>
|
2015-03-10 01:15:28 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
2012-05-15 02:33:01 +00:00
|
|
|
#include "lldb/Breakpoint/BreakpointIDList.h"
|
2016-02-22 17:29:56 +00:00
|
|
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
2015-05-13 19:44:24 +00:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2015-03-10 01:15:28 +00:00
|
|
|
#include "lldb/Core/Module.h"
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-29 21:13:06 +00:00
|
|
|
#include "lldb/Core/ModuleSpec.h"
|
2011-03-08 22:40:15 +00:00
|
|
|
#include "lldb/Core/PluginManager.h"
|
2022-04-01 14:38:55 +02:00
|
|
|
#include "lldb/Host/FileCache.h"
|
2014-08-15 22:04:21 +00:00
|
|
|
#include "lldb/Host/FileSystem.h"
|
2011-03-19 01:12:21 +00:00
|
|
|
#include "lldb/Host/Host.h"
|
2014-08-19 17:18:29 +00:00
|
|
|
#include "lldb/Host/HostInfo.h"
|
2017-03-22 23:33:16 +00:00
|
|
|
#include "lldb/Host/OptionParser.h"
|
2020-03-12 21:48:23 +03:00
|
|
|
#include "lldb/Interpreter/OptionValueFileSpec.h"
|
2015-03-10 01:15:28 +00:00
|
|
|
#include "lldb/Interpreter/OptionValueProperties.h"
|
|
|
|
|
#include "lldb/Interpreter/Property.h"
|
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
2017-02-14 19:06:07 +00:00
|
|
|
#include "lldb/Target/ModuleCache.h"
|
2011-04-12 05:54:46 +00:00
|
|
|
#include "lldb/Target/Platform.h"
|
|
|
|
|
#include "lldb/Target/Process.h"
|
2011-03-08 22:40:15 +00:00
|
|
|
#include "lldb/Target/Target.h"
|
2015-07-14 01:09:28 +00:00
|
|
|
#include "lldb/Target/UnixSignals.h"
|
2017-03-04 01:30:05 +00:00
|
|
|
#include "lldb/Utility/DataBufferHeap.h"
|
2017-03-22 18:40:07 +00:00
|
|
|
#include "lldb/Utility/FileSpec.h"
|
2022-02-03 13:26:10 +01:00
|
|
|
#include "lldb/Utility/LLDBLog.h"
|
2017-03-03 20:56:28 +00:00
|
|
|
#include "lldb/Utility/Log.h"
|
2017-05-12 04:51:55 +00:00
|
|
|
#include "lldb/Utility/Status.h"
|
2017-06-27 10:45:31 +00:00
|
|
|
#include "lldb/Utility/StructuredData.h"
|
2022-03-30 10:36:18 -07:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-03-08 17:56:08 +00:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2020-07-14 08:44:40 -07:00
|
|
|
#include "llvm/Support/Path.h"
|
2017-03-08 17:56:08 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// Define these constants from POSIX mman.h rather than include the file so
|
|
|
|
|
// that they will be correct even when compiled on Linux.
|
2015-05-09 15:53:31 +00:00
|
|
|
#define MAP_PRIVATE 2
|
|
|
|
|
#define MAP_ANON 0x1000
|
|
|
|
|
|
2011-03-08 22:40:15 +00:00
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
2015-02-12 18:18:27 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// Use a singleton function for g_local_platform_sp to avoid init constructors
|
|
|
|
|
// since LLDB is often part of a shared library
|
2014-09-19 20:11:50 +00:00
|
|
|
static PlatformSP &GetHostPlatformSP() {
|
|
|
|
|
static PlatformSP g_platform_sp;
|
|
|
|
|
return g_platform_sp;
|
2011-03-08 22:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-13 22:47:15 +00:00
|
|
|
const char *Platform::GetHostPlatformName() { return "host"; }
|
|
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
namespace {
|
|
|
|
|
|
2019-07-25 21:36:37 +00:00
|
|
|
#define LLDB_PROPERTIES_platform
|
2019-07-29 17:22:10 +00:00
|
|
|
#include "TargetProperties.inc"
|
2019-07-25 21:36:37 +00:00
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
#define LLDB_PROPERTIES_platform
|
2019-07-29 17:22:10 +00:00
|
|
|
#include "TargetPropertiesEnum.inc"
|
2019-07-25 21:36:37 +00:00
|
|
|
};
|
2015-03-10 01:15:28 +00:00
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2023-08-30 15:56:54 -07:00
|
|
|
llvm::StringRef PlatformProperties::GetSettingName() {
|
|
|
|
|
static constexpr llvm::StringLiteral g_setting_name("platform");
|
2015-03-10 01:15:28 +00:00
|
|
|
return g_setting_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformProperties::PlatformProperties() {
|
2019-02-11 23:13:08 +00:00
|
|
|
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
|
2019-07-29 16:41:30 +00:00
|
|
|
m_collection_sp->Initialize(g_platform_properties);
|
2015-03-10 01:15:28 +00:00
|
|
|
|
|
|
|
|
auto module_cache_dir = GetModuleCacheDirectory();
|
2015-10-01 17:48:57 +00:00
|
|
|
if (module_cache_dir)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
llvm::SmallString<64> user_home_dir;
|
2020-08-20 11:36:32 -07:00
|
|
|
if (!FileSystem::Instance().GetHomeDirectory(user_home_dir))
|
2015-10-01 17:48:57 +00:00
|
|
|
return;
|
|
|
|
|
|
2018-11-01 21:05:36 +00:00
|
|
|
module_cache_dir = FileSpec(user_home_dir.c_str());
|
2015-10-01 17:48:57 +00:00
|
|
|
module_cache_dir.AppendPathComponent(".lldb");
|
|
|
|
|
module_cache_dir.AppendPathComponent("module_cache");
|
2020-03-12 21:48:23 +03:00
|
|
|
SetDefaultModuleCacheDirectory(module_cache_dir);
|
2015-10-01 17:48:57 +00:00
|
|
|
SetModuleCacheDirectory(module_cache_dir);
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PlatformProperties::GetUseModuleCache() const {
|
|
|
|
|
const auto idx = ePropertyUseModuleCache;
|
2023-05-04 09:26:58 -07:00
|
|
|
return GetPropertyAtIndexAs<bool>(
|
|
|
|
|
idx, g_platform_properties[idx].default_uint_value != 0);
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PlatformProperties::SetUseModuleCache(bool use_module_cache) {
|
2023-05-04 09:26:58 -07:00
|
|
|
return SetPropertyAtIndex(ePropertyUseModuleCache, use_module_cache);
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileSpec PlatformProperties::GetModuleCacheDirectory() const {
|
2023-05-04 22:07:37 -07:00
|
|
|
return GetPropertyAtIndexAs<FileSpec>(ePropertyModuleCacheDirectory, {});
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PlatformProperties::SetModuleCacheDirectory(const FileSpec &dir_spec) {
|
2023-05-04 22:07:37 -07:00
|
|
|
return m_collection_sp->SetPropertyAtIndex(ePropertyModuleCacheDirectory,
|
|
|
|
|
dir_spec);
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-12 21:48:23 +03:00
|
|
|
void PlatformProperties::SetDefaultModuleCacheDirectory(
|
|
|
|
|
const FileSpec &dir_spec) {
|
|
|
|
|
auto f_spec_opt = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(
|
2023-05-02 10:31:21 -07:00
|
|
|
ePropertyModuleCacheDirectory);
|
2020-03-12 21:48:23 +03:00
|
|
|
assert(f_spec_opt);
|
|
|
|
|
f_spec_opt->SetDefaultValue(dir_spec);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-08 22:40:15 +00:00
|
|
|
/// Get the native host platform plug-in.
|
|
|
|
|
///
|
|
|
|
|
/// There should only be one of these for each host that LLDB runs
|
|
|
|
|
/// upon that should be statically compiled in and registered using
|
|
|
|
|
/// preprocessor macros or other similar build mechanisms.
|
|
|
|
|
///
|
|
|
|
|
/// This platform will be used as the default platform when launching
|
|
|
|
|
/// or attaching to processes unless another platform is specified.
|
2014-09-19 20:11:50 +00:00
|
|
|
PlatformSP Platform::GetHostPlatform() { return GetHostPlatformSP(); }
|
|
|
|
|
|
2022-02-25 14:47:27 +01:00
|
|
|
void Platform::Initialize() {}
|
2022-03-09 18:12:28 +01:00
|
|
|
|
2022-02-25 14:47:27 +01:00
|
|
|
void Platform::Terminate() {}
|
2022-03-30 10:36:18 -07:00
|
|
|
|
2021-10-07 15:44:47 +02:00
|
|
|
PlatformProperties &Platform::GetGlobalPlatformProperties() {
|
|
|
|
|
static PlatformProperties g_settings;
|
|
|
|
|
return g_settings;
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
2014-09-19 20:11:50 +00:00
|
|
|
void Platform::SetHostPlatform(const lldb::PlatformSP &platform_sp) {
|
2011-03-08 22:40:15 +00:00
|
|
|
// The native platform should use its static void Platform::Initialize()
|
|
|
|
|
// function to register itself as the native platform.
|
2014-09-19 20:11:50 +00:00
|
|
|
GetHostPlatformSP() = platform_sp;
|
2011-03-08 22:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::GetFileWithUUID(const FileSpec &platform_file,
|
|
|
|
|
const UUID *uuid_ptr, FileSpec &local_file) {
|
2011-03-08 22:40:15 +00:00
|
|
|
// Default to the local case
|
|
|
|
|
local_file = platform_file;
|
2017-05-12 04:51:55 +00:00
|
|
|
return Status();
|
2011-03-08 22:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-11 23:44:27 +00:00
|
|
|
FileSpecList
|
2014-08-16 00:32:58 +00:00
|
|
|
Platform::LocateExecutableScriptingResources(Target *target, Module &module,
|
2023-07-10 13:19:13 -07:00
|
|
|
Stream &feedback_stream) {
|
2013-01-11 23:44:27 +00:00
|
|
|
return FileSpecList();
|
2012-11-08 02:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
[lldb] GetSharedModule: Collect old modules in SmallVector
The various GetSharedModule methods have an optional out parameter for
the old module when a file has changed or been replaced, which the
Target uses to keep its module list current/correct. We've been using
a single ModuleSP to track "the" old module, and this change switches
to using a SmallVector of ModuleSP, which has a couple benefits:
- There are multiple codepaths which may discover an old module, and
this centralizes the code for how to handle multiples in one place,
in the Target code. With the single ModuleSP, each place that may
discover an old module is responsible for how it handles multiples,
and the current code is inconsistent (some code paths drop the first
old module, others drop the second).
- The API will be more natural for identifying old modules in routines
that work on sets, like ModuleList::ReplaceEquivalent (which I plan
on updating to report old module(s) in a subsequent change to fix a
bug).
I'm not convinced we can ever actually run into the case that multiple
old modules are found in the same GetOrCreateModule call, but I think
this change makes sense regardless, in light of the above.
When an old module is reported, Target::GetOrCreateModule calls
m_images.ReplaceModule, which doesn't allow multiple "old" modules; the
new code calls ReplaceModule for the first "old" module, and for any
subsequent old modules it logs the event and calls m_images.Remove.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D89156
2020-10-30 15:12:10 -04:00
|
|
|
Status Platform::GetSharedModule(
|
|
|
|
|
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
|
|
|
|
|
const FileSpecList *module_search_paths_ptr,
|
|
|
|
|
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {
|
2015-03-24 23:45:49 +00:00
|
|
|
if (IsHost())
|
[lldb] GetSharedModule: Collect old modules in SmallVector
The various GetSharedModule methods have an optional out parameter for
the old module when a file has changed or been replaced, which the
Target uses to keep its module list current/correct. We've been using
a single ModuleSP to track "the" old module, and this change switches
to using a SmallVector of ModuleSP, which has a couple benefits:
- There are multiple codepaths which may discover an old module, and
this centralizes the code for how to handle multiples in one place,
in the Target code. With the single ModuleSP, each place that may
discover an old module is responsible for how it handles multiples,
and the current code is inconsistent (some code paths drop the first
old module, others drop the second).
- The API will be more natural for identifying old modules in routines
that work on sets, like ModuleList::ReplaceEquivalent (which I plan
on updating to report old module(s) in a subsequent change to fix a
bug).
I'm not convinced we can ever actually run into the case that multiple
old modules are found in the same GetOrCreateModule call, but I think
this change makes sense regardless, in light of the above.
When an old module is reported, Target::GetOrCreateModule calls
m_images.ReplaceModule, which doesn't allow multiple "old" modules; the
new code calls ReplaceModule for the first "old" module, and for any
subsequent old modules it logs the event and calls m_images.Remove.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D89156
2020-10-30 15:12:10 -04:00
|
|
|
return ModuleList::GetSharedModule(module_spec, module_sp,
|
|
|
|
|
module_search_paths_ptr, old_modules,
|
|
|
|
|
did_create_ptr, false);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2018-08-28 16:32:46 +00:00
|
|
|
// Module resolver lambda.
|
|
|
|
|
auto resolver = [&](const ModuleSpec &spec) {
|
|
|
|
|
Status error(eErrorTypeGeneric);
|
|
|
|
|
ModuleSpec resolved_spec;
|
|
|
|
|
// Check if we have sysroot set.
|
2023-06-06 18:48:31 -07:00
|
|
|
if (!m_sdk_sysroot.empty()) {
|
2018-08-28 16:32:46 +00:00
|
|
|
// Prepend sysroot to module spec.
|
|
|
|
|
resolved_spec = spec;
|
2023-06-06 18:48:31 -07:00
|
|
|
resolved_spec.GetFileSpec().PrependPathComponent(m_sdk_sysroot);
|
2018-08-28 16:32:46 +00:00
|
|
|
// Try to get shared module with resolved spec.
|
[lldb] GetSharedModule: Collect old modules in SmallVector
The various GetSharedModule methods have an optional out parameter for
the old module when a file has changed or been replaced, which the
Target uses to keep its module list current/correct. We've been using
a single ModuleSP to track "the" old module, and this change switches
to using a SmallVector of ModuleSP, which has a couple benefits:
- There are multiple codepaths which may discover an old module, and
this centralizes the code for how to handle multiples in one place,
in the Target code. With the single ModuleSP, each place that may
discover an old module is responsible for how it handles multiples,
and the current code is inconsistent (some code paths drop the first
old module, others drop the second).
- The API will be more natural for identifying old modules in routines
that work on sets, like ModuleList::ReplaceEquivalent (which I plan
on updating to report old module(s) in a subsequent change to fix a
bug).
I'm not convinced we can ever actually run into the case that multiple
old modules are found in the same GetOrCreateModule call, but I think
this change makes sense regardless, in light of the above.
When an old module is reported, Target::GetOrCreateModule calls
m_images.ReplaceModule, which doesn't allow multiple "old" modules; the
new code calls ReplaceModule for the first "old" module, and for any
subsequent old modules it logs the event and calls m_images.Remove.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D89156
2020-10-30 15:12:10 -04:00
|
|
|
error = ModuleList::GetSharedModule(resolved_spec, module_sp,
|
|
|
|
|
module_search_paths_ptr, old_modules,
|
|
|
|
|
did_create_ptr, false);
|
2018-08-28 16:32:46 +00:00
|
|
|
}
|
|
|
|
|
// If we don't have sysroot or it didn't work then
|
|
|
|
|
// try original module spec.
|
|
|
|
|
if (!error.Success()) {
|
|
|
|
|
resolved_spec = spec;
|
[lldb] GetSharedModule: Collect old modules in SmallVector
The various GetSharedModule methods have an optional out parameter for
the old module when a file has changed or been replaced, which the
Target uses to keep its module list current/correct. We've been using
a single ModuleSP to track "the" old module, and this change switches
to using a SmallVector of ModuleSP, which has a couple benefits:
- There are multiple codepaths which may discover an old module, and
this centralizes the code for how to handle multiples in one place,
in the Target code. With the single ModuleSP, each place that may
discover an old module is responsible for how it handles multiples,
and the current code is inconsistent (some code paths drop the first
old module, others drop the second).
- The API will be more natural for identifying old modules in routines
that work on sets, like ModuleList::ReplaceEquivalent (which I plan
on updating to report old module(s) in a subsequent change to fix a
bug).
I'm not convinced we can ever actually run into the case that multiple
old modules are found in the same GetOrCreateModule call, but I think
this change makes sense regardless, in light of the above.
When an old module is reported, Target::GetOrCreateModule calls
m_images.ReplaceModule, which doesn't allow multiple "old" modules; the
new code calls ReplaceModule for the first "old" module, and for any
subsequent old modules it logs the event and calls m_images.Remove.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D89156
2020-10-30 15:12:10 -04:00
|
|
|
error = ModuleList::GetSharedModule(resolved_spec, module_sp,
|
|
|
|
|
module_search_paths_ptr, old_modules,
|
|
|
|
|
did_create_ptr, false);
|
2018-08-28 16:32:46 +00:00
|
|
|
}
|
|
|
|
|
if (error.Success() && module_sp)
|
|
|
|
|
module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());
|
|
|
|
|
return error;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return GetRemoteSharedModule(module_spec, process, module_sp, resolver,
|
2015-03-24 23:45:49 +00:00
|
|
|
did_create_ptr);
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
bool Platform::GetModuleSpec(const FileSpec &module_file_spec,
|
|
|
|
|
const ArchSpec &arch, ModuleSpec &module_spec) {
|
|
|
|
|
ModuleSpecList module_specs;
|
|
|
|
|
if (ObjectFile::GetModuleSpecifications(module_file_spec, 0, 0,
|
|
|
|
|
module_specs) == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
ModuleSpec matched_module_spec;
|
|
|
|
|
return module_specs.FindMatchingModuleSpec(ModuleSpec(module_file_spec, arch),
|
|
|
|
|
module_spec);
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP Platform::Create(llvm::StringRef name) {
|
2011-03-08 22:40:15 +00:00
|
|
|
lldb::PlatformSP platform_sp;
|
2022-02-25 14:47:27 +01:00
|
|
|
if (name == GetHostPlatformName())
|
|
|
|
|
return GetHostPlatform();
|
2022-03-09 18:12:28 +01:00
|
|
|
|
2022-02-25 14:47:27 +01:00
|
|
|
if (PlatformCreateInstance create_callback =
|
|
|
|
|
PluginManager::GetPlatformCreateCallbackForPluginName(name))
|
2023-01-13 08:51:03 -08:00
|
|
|
return create_callback(true, nullptr);
|
2022-02-25 14:47:27 +01:00
|
|
|
return nullptr;
|
2012-03-20 18:34:04 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-31 10:56:03 +00:00
|
|
|
ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple) {
|
|
|
|
|
if (platform)
|
|
|
|
|
return platform->GetAugmentedArchSpec(triple);
|
|
|
|
|
return HostInfo::GetAugmentedArchSpec(triple);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-08 22:40:15 +00:00
|
|
|
/// Default Constructor
|
2016-05-18 01:59:10 +00:00
|
|
|
Platform::Platform(bool is_host)
|
|
|
|
|
: m_is_host(is_host), m_os_version_set_while_connected(false),
|
2022-02-07 14:52:22 +01:00
|
|
|
m_system_arch_set_while_connected(false), m_max_uid_name_len(0),
|
|
|
|
|
m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(),
|
|
|
|
|
m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
|
2019-03-04 18:48:00 +00:00
|
|
|
m_ignores_remote_hostname(false), m_trap_handlers(),
|
|
|
|
|
m_calculated_trap_handlers(false),
|
2019-08-14 22:19:23 +00:00
|
|
|
m_module_cache(std::make_unique<ModuleCache>()) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Object);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "%p Platform::Platform()", static_cast<void *>(this));
|
2011-03-08 22:40:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-10-14 21:36:10 +02:00
|
|
|
Platform::~Platform() = default;
|
|
|
|
|
|
2011-03-24 04:28:38 +00:00
|
|
|
void Platform::GetStatus(Stream &strm) {
|
2021-10-15 13:07:39 +02:00
|
|
|
strm.Format(" Platform: {0}\n", GetPluginName());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-24 04:28:38 +00:00
|
|
|
ArchSpec arch(GetSystemArchitecture());
|
|
|
|
|
if (arch.IsValid()) {
|
2015-10-13 23:41:19 +00:00
|
|
|
if (!arch.GetTriple().str().empty()) {
|
2011-03-24 04:28:38 +00:00
|
|
|
strm.Printf(" Triple: ");
|
2019-12-04 08:27:43 +01:00
|
|
|
arch.DumpTriple(strm.AsRawOstream());
|
2011-03-24 04:28:38 +00:00
|
|
|
strm.EOL();
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-18 15:02:23 +00:00
|
|
|
llvm::VersionTuple os_version = GetOSVersion();
|
|
|
|
|
if (!os_version.empty()) {
|
|
|
|
|
strm.Format("OS Version: {0}", os_version.getAsString());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
if (std::optional<std::string> s = GetOSBuildString())
|
2021-10-25 15:58:29 +02:00
|
|
|
strm.Format(" ({0})", *s);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-10-13 23:41:19 +00:00
|
|
|
strm.EOL();
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-24 04:28:38 +00:00
|
|
|
if (IsHost()) {
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
strm.Printf(" Hostname: %s\n", GetHostname());
|
2011-03-24 04:28:38 +00:00
|
|
|
} else {
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
const bool is_connected = IsConnected();
|
|
|
|
|
if (is_connected)
|
|
|
|
|
strm.Printf(" Hostname: %s\n", GetHostname());
|
|
|
|
|
strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-06 18:48:31 -07:00
|
|
|
if (const std::string &sdk_root = GetSDKRootDirectory(); !sdk_root.empty())
|
|
|
|
|
strm.Format(" Sysroot: {0}\n", sdk_root);
|
|
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
if (GetWorkingDirectory()) {
|
2022-07-25 23:29:30 -07:00
|
|
|
strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str());
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2013-08-26 23:57:52 +00:00
|
|
|
if (!IsConnected())
|
2016-09-06 20:57:50 +00:00
|
|
|
return;
|
|
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
std::string specific_info(GetPlatformSpecificConnectionInformation());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2016-02-18 00:10:17 +00:00
|
|
|
if (!specific_info.empty())
|
2013-08-26 23:57:52 +00:00
|
|
|
strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
|
2020-01-31 14:23:56 -08:00
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
if (std::optional<std::string> s = GetOSKernelDescription())
|
2021-10-26 10:52:39 +02:00
|
|
|
strm.Format(" Kernel: {0}\n", *s);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-18 15:02:23 +00:00
|
|
|
llvm::VersionTuple Platform::GetOSVersion(Process *process) {
|
2016-05-18 01:59:10 +00:00
|
|
|
std::lock_guard<std::mutex> guard(m_mutex);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-19 01:12:21 +00:00
|
|
|
if (IsHost()) {
|
2018-06-18 15:02:23 +00:00
|
|
|
if (m_os_version.empty()) {
|
2011-03-19 01:12:21 +00:00
|
|
|
// We have a local host platform
|
2018-06-18 15:02:23 +00:00
|
|
|
m_os_version = HostInfo::GetOSVersion();
|
|
|
|
|
m_os_version_set_while_connected = !m_os_version.empty();
|
2011-03-24 04:28:38 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2011-03-19 01:12:21 +00:00
|
|
|
// We have a remote platform. We can only fetch the remote
|
|
|
|
|
// OS version if we are connected, and we don't want to do it
|
|
|
|
|
// more than once.
|
2016-09-06 20:57:50 +00:00
|
|
|
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
const bool is_connected = IsConnected();
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-24 04:28:38 +00:00
|
|
|
bool fetch = false;
|
2018-06-18 15:02:23 +00:00
|
|
|
if (!m_os_version.empty()) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We have valid OS version info, check to make sure it wasn't manually
|
|
|
|
|
// set prior to connecting. If it was manually set prior to connecting,
|
|
|
|
|
// then lets fetch the actual OS version info if we are now connected.
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
if (is_connected && !m_os_version_set_while_connected)
|
|
|
|
|
fetch = true;
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
// We don't have valid OS version info, fetch it if we are connected
|
2011-03-24 04:28:38 +00:00
|
|
|
fetch = is_connected;
|
|
|
|
|
}
|
2013-08-26 23:57:52 +00:00
|
|
|
|
2018-06-18 15:02:23 +00:00
|
|
|
if (fetch)
|
|
|
|
|
m_os_version_set_while_connected = GetRemoteOSVersion();
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2011-03-19 01:12:21 +00:00
|
|
|
|
2018-06-18 15:02:23 +00:00
|
|
|
if (!m_os_version.empty())
|
|
|
|
|
return m_os_version;
|
|
|
|
|
if (process) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// Check with the process in case it can answer the question if a process
|
|
|
|
|
// was provided
|
2018-06-18 15:02:23 +00:00
|
|
|
return process->GetHostOSVersion();
|
2015-11-05 22:33:17 +00:00
|
|
|
}
|
2018-06-18 15:02:23 +00:00
|
|
|
return llvm::VersionTuple();
|
2011-03-19 01:12:21 +00:00
|
|
|
}
|
2011-03-24 04:28:38 +00:00
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
std::optional<std::string> Platform::GetOSBuildString() {
|
2021-10-25 15:58:29 +02:00
|
|
|
if (IsHost())
|
|
|
|
|
return HostInfo::GetOSBuildString();
|
|
|
|
|
return GetRemoteOSBuildString();
|
2011-03-24 04:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-01-07 14:18:35 -08:00
|
|
|
std::optional<std::string> Platform::GetOSKernelDescription() {
|
2021-10-26 10:52:39 +02:00
|
|
|
if (IsHost())
|
|
|
|
|
return HostInfo::GetOSKernelDescription();
|
|
|
|
|
return GetRemoteOSKernelDescription();
|
2011-03-24 04:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-01-22 18:25:49 +00:00
|
|
|
void Platform::AddClangModuleCompilationOptions(
|
|
|
|
|
Target *target, std::vector<std::string> &options) {
|
2014-12-05 01:16:31 +00:00
|
|
|
std::vector<std::string> default_compilation_options = {
|
|
|
|
|
"-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc"};
|
|
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
options.insert(options.end(), default_compilation_options.begin(),
|
|
|
|
|
default_compilation_options.end());
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 19:52:29 +00:00
|
|
|
FileSpec Platform::GetWorkingDirectory() {
|
2011-03-19 01:12:21 +00:00
|
|
|
if (IsHost()) {
|
2017-01-23 15:56:45 +00:00
|
|
|
llvm::SmallString<64> cwd;
|
|
|
|
|
if (llvm::sys::fs::current_path(cwd))
|
2018-11-01 21:05:36 +00:00
|
|
|
return {};
|
|
|
|
|
else {
|
|
|
|
|
FileSpec file_spec(cwd);
|
|
|
|
|
FileSystem::Instance().Resolve(file_spec);
|
|
|
|
|
return file_spec;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2013-11-20 21:07:01 +00:00
|
|
|
if (!m_working_dir)
|
|
|
|
|
m_working_dir = GetRemoteWorkingDirectory();
|
|
|
|
|
return m_working_dir;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
struct RecurseCopyBaton {
|
|
|
|
|
const FileSpec &dst;
|
|
|
|
|
Platform *platform_ptr;
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2013-11-20 21:07:01 +00:00
|
|
|
};
|
|
|
|
|
|
2018-11-01 00:33:27 +00:00
|
|
|
static FileSystem::EnumerateDirectoryResult
|
2017-03-08 17:56:08 +00:00
|
|
|
RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
|
2018-11-01 00:33:27 +00:00
|
|
|
llvm::StringRef path) {
|
2013-11-20 21:07:01 +00:00
|
|
|
RecurseCopyBaton *rc_baton = (RecurseCopyBaton *)baton;
|
2018-11-01 21:05:36 +00:00
|
|
|
FileSpec src(path);
|
2017-03-08 17:56:08 +00:00
|
|
|
namespace fs = llvm::sys::fs;
|
|
|
|
|
switch (ft) {
|
|
|
|
|
case fs::file_type::fifo_file:
|
|
|
|
|
case fs::file_type::socket_file:
|
2013-11-20 21:07:01 +00:00
|
|
|
// we have no way to copy pipes and sockets - ignore them and continue
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultNext;
|
2013-11-20 21:07:01 +00:00
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::directory_file: {
|
2013-11-20 21:07:01 +00:00
|
|
|
// make the new directory and get in there
|
|
|
|
|
FileSpec dst_dir = rc_baton->dst;
|
|
|
|
|
if (!dst_dir.GetFilename())
|
2023-05-02 10:05:36 -07:00
|
|
|
dst_dir.SetFilename(src.GetFilename());
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error = rc_baton->platform_ptr->MakeDirectory(
|
2013-11-20 21:07:01 +00:00
|
|
|
dst_dir, lldb::eFilePermissionsDirectoryDefault);
|
|
|
|
|
if (error.Fail()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
rc_baton->error = Status::FromErrorStringWithFormatv(
|
|
|
|
|
"unable to setup directory {0} on remote end", dst_dir.GetPath());
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now recurse
|
|
|
|
|
std::string src_dir_path(src.GetPath());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// Make a filespec that only fills in the directory of a FileSpec so when
|
|
|
|
|
// we enumerate we can quickly fill in the filename for dst copies
|
2013-11-20 21:07:01 +00:00
|
|
|
FileSpec recurse_dst;
|
2022-07-25 23:29:30 -07:00
|
|
|
recurse_dst.SetDirectory(dst_dir.GetPathAsConstString());
|
2017-05-12 04:51:55 +00:00
|
|
|
RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,
|
|
|
|
|
Status()};
|
2018-11-01 00:33:27 +00:00
|
|
|
FileSystem::Instance().EnumerateDirectory(src_dir_path, true, true, true,
|
|
|
|
|
RecurseCopy_Callback, &rc_baton2);
|
2013-11-20 21:07:01 +00:00
|
|
|
if (rc_baton2.error.Fail()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
rc_baton->error = Status::FromErrorString(rc_baton2.error.AsCString());
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultNext;
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
2013-11-20 21:07:01 +00:00
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::symlink_file: {
|
2015-05-29 19:52:29 +00:00
|
|
|
// copy the file and keep going
|
|
|
|
|
FileSpec dst_file = rc_baton->dst;
|
2013-11-20 21:07:01 +00:00
|
|
|
if (!dst_file.GetFilename())
|
2022-07-25 23:29:30 -07:00
|
|
|
dst_file.SetFilename(src.GetFilename());
|
2013-11-20 21:07:01 +00:00
|
|
|
|
|
|
|
|
FileSpec src_resolved;
|
|
|
|
|
|
2018-10-31 21:49:27 +00:00
|
|
|
rc_baton->error = FileSystem::Instance().Readlink(src, src_resolved);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
if (rc_baton->error.Fail())
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-05-29 19:52:29 +00:00
|
|
|
rc_baton->error =
|
|
|
|
|
rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
if (rc_baton->error.Fail())
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultNext;
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::regular_file: {
|
2013-11-20 21:07:01 +00:00
|
|
|
// copy the file and keep going
|
|
|
|
|
FileSpec dst_file = rc_baton->dst;
|
|
|
|
|
if (!dst_file.GetFilename())
|
2022-07-25 23:29:30 -07:00
|
|
|
dst_file.SetFilename(src.GetFilename());
|
2017-05-12 04:51:55 +00:00
|
|
|
Status err = rc_baton->platform_ptr->PutFile(src, dst_file);
|
2013-11-20 21:07:01 +00:00
|
|
|
if (err.Fail()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
rc_baton->error = Status::FromErrorString(err.AsCString());
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultNext;
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
default:
|
2024-08-27 10:59:31 -07:00
|
|
|
rc_baton->error = Status::FromErrorStringWithFormat(
|
2015-05-29 19:52:29 +00:00
|
|
|
"invalid file detected during copy: %s", src.GetPath().c_str());
|
2018-11-01 00:33:27 +00:00
|
|
|
return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2017-03-08 17:56:08 +00:00
|
|
|
llvm_unreachable("Unhandled file_type!");
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
|
|
|
|
|
Status error;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s')",
|
|
|
|
|
src.GetPath().c_str(), dst.GetPath().c_str());
|
2013-11-20 21:07:01 +00:00
|
|
|
FileSpec fixed_dst(dst);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
if (!fixed_dst.GetFilename())
|
2022-07-25 23:29:30 -07:00
|
|
|
fixed_dst.SetFilename(src.GetFilename());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-11-20 21:07:01 +00:00
|
|
|
FileSpec working_dir = GetWorkingDirectory();
|
2016-09-06 20:57:50 +00:00
|
|
|
|
|
|
|
|
if (dst) {
|
2013-11-20 21:07:01 +00:00
|
|
|
if (dst.GetDirectory()) {
|
|
|
|
|
const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
|
|
|
|
|
if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') {
|
2022-07-25 23:29:30 -07:00
|
|
|
fixed_dst.SetDirectory(dst.GetDirectory());
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2018-04-30 16:49:04 +00:00
|
|
|
// If the fixed destination file doesn't have a directory yet, then we
|
|
|
|
|
// must have a relative path. We will resolve this relative path against
|
|
|
|
|
// the platform's working directory
|
2013-11-20 21:07:01 +00:00
|
|
|
if (!fixed_dst.GetDirectory()) {
|
|
|
|
|
FileSpec relative_spec;
|
|
|
|
|
std::string path;
|
|
|
|
|
if (working_dir) {
|
2015-05-29 19:52:29 +00:00
|
|
|
relative_spec = working_dir;
|
2013-11-20 21:07:01 +00:00
|
|
|
relative_spec.AppendPathComponent(dst.GetPath());
|
2022-07-25 23:29:30 -07:00
|
|
|
fixed_dst.SetDirectory(relative_spec.GetDirectory());
|
2013-11-20 21:07:01 +00:00
|
|
|
} else {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat(
|
2013-11-20 21:07:01 +00:00
|
|
|
"platform working directory must be valid for relative path '%s'",
|
|
|
|
|
dst.GetPath().c_str());
|
|
|
|
|
return error;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2013-11-20 21:07:01 +00:00
|
|
|
if (working_dir) {
|
2022-07-25 23:29:30 -07:00
|
|
|
fixed_dst.SetDirectory(working_dir.GetPathAsConstString());
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat(
|
2013-11-20 21:07:01 +00:00
|
|
|
"platform working directory must be valid for relative path '%s'",
|
|
|
|
|
dst.GetPath().c_str());
|
|
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2015-05-29 19:52:29 +00:00
|
|
|
if (working_dir) {
|
2022-07-25 23:29:30 -07:00
|
|
|
fixed_dst.SetDirectory(working_dir.GetPathAsConstString());
|
2013-11-20 21:07:01 +00:00
|
|
|
} else {
|
2024-08-27 10:59:31 -07:00
|
|
|
error =
|
|
|
|
|
Status::FromErrorString("platform working directory must be valid "
|
|
|
|
|
"when destination directory is empty");
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'",
|
|
|
|
|
src.GetPath().c_str(), dst.GetPath().c_str(),
|
|
|
|
|
fixed_dst.GetPath().c_str());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2014-11-17 19:39:20 +00:00
|
|
|
if (GetSupportsRSync()) {
|
2015-05-29 19:52:29 +00:00
|
|
|
error = PutFile(src, dst);
|
2013-11-20 21:07:01 +00:00
|
|
|
} else {
|
2017-03-08 17:56:08 +00:00
|
|
|
namespace fs = llvm::sys::fs;
|
|
|
|
|
switch (fs::get_file_type(src.GetPath(), false)) {
|
|
|
|
|
case fs::file_type::directory_file: {
|
2017-03-21 05:47:57 +00:00
|
|
|
llvm::sys::fs::remove(fixed_dst.GetPath());
|
2018-11-01 15:47:33 +00:00
|
|
|
uint32_t permissions = FileSystem::Instance().GetPermissions(src);
|
2013-11-20 21:07:01 +00:00
|
|
|
if (permissions == 0)
|
|
|
|
|
permissions = eFilePermissionsDirectoryDefault;
|
2013-12-02 19:35:49 +00:00
|
|
|
error = MakeDirectory(fixed_dst, permissions);
|
|
|
|
|
if (error.Success()) {
|
2015-05-29 19:52:29 +00:00
|
|
|
// Make a filespec that only fills in the directory of a FileSpec so
|
|
|
|
|
// when we enumerate we can quickly fill in the filename for dst copies
|
2013-11-20 21:07:01 +00:00
|
|
|
FileSpec recurse_dst;
|
2022-07-25 23:29:30 -07:00
|
|
|
recurse_dst.SetDirectory(fixed_dst.GetPathAsConstString());
|
2013-11-20 21:07:01 +00:00
|
|
|
std::string src_dir_path(src.GetPath());
|
2017-05-12 04:51:55 +00:00
|
|
|
RecurseCopyBaton baton = {recurse_dst, this, Status()};
|
2018-11-01 00:33:27 +00:00
|
|
|
FileSystem::Instance().EnumerateDirectory(
|
|
|
|
|
src_dir_path, true, true, true, RecurseCopy_Callback, &baton);
|
2024-09-05 12:44:13 -07:00
|
|
|
return std::move(baton.error);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::regular_file:
|
2017-03-21 05:47:57 +00:00
|
|
|
llvm::sys::fs::remove(fixed_dst.GetPath());
|
2015-05-29 19:52:29 +00:00
|
|
|
error = PutFile(src, fixed_dst);
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
|
|
|
|
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::symlink_file: {
|
2017-03-21 05:47:57 +00:00
|
|
|
llvm::sys::fs::remove(fixed_dst.GetPath());
|
2015-05-29 19:52:29 +00:00
|
|
|
FileSpec src_resolved;
|
2018-10-31 21:49:27 +00:00
|
|
|
error = FileSystem::Instance().Readlink(src, src_resolved);
|
2013-11-20 21:07:01 +00:00
|
|
|
if (error.Success())
|
2015-05-29 19:52:29 +00:00
|
|
|
error = CreateSymlink(dst, src_resolved);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::fifo_file:
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString("platform install doesn't handle pipes");
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
2017-03-08 17:56:08 +00:00
|
|
|
case fs::file_type::socket_file:
|
2024-08-27 10:59:31 -07:00
|
|
|
error =
|
|
|
|
|
Status::FromErrorString("platform install doesn't handle sockets");
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
2017-03-08 17:56:08 +00:00
|
|
|
default:
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString(
|
2013-11-20 21:07:01 +00:00
|
|
|
"platform install doesn't handle non file or directory items");
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 19:52:29 +00:00
|
|
|
bool Platform::SetWorkingDirectory(const FileSpec &file_spec) {
|
2013-11-20 21:07:01 +00:00
|
|
|
if (IsHost()) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2017-01-25 11:10:52 +00:00
|
|
|
LLDB_LOG(log, "{0}", file_spec);
|
|
|
|
|
if (std::error_code ec = llvm::sys::fs::set_current_path(file_spec.GetPath())) {
|
|
|
|
|
LLDB_LOG(log, "error: {0}", ec.message());
|
|
|
|
|
return false;
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
2017-01-25 11:10:52 +00:00
|
|
|
return true;
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2013-11-20 21:07:01 +00:00
|
|
|
m_working_dir.Clear();
|
2015-05-29 19:52:29 +00:00
|
|
|
return SetRemoteWorkingDirectory(file_spec);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::MakeDirectory(const FileSpec &file_spec,
|
|
|
|
|
uint32_t permissions) {
|
2013-11-20 21:07:01 +00:00
|
|
|
if (IsHost())
|
2017-03-19 05:48:47 +00:00
|
|
|
return llvm::sys::fs::create_directory(file_spec.GetPath(), permissions);
|
2013-11-20 21:07:01 +00:00
|
|
|
else {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"remote platform {0} doesn't support {1}", GetPluginName(),
|
|
|
|
|
LLVM_PRETTY_FUNCTION);
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::GetFilePermissions(const FileSpec &file_spec,
|
|
|
|
|
uint32_t &file_permissions) {
|
2017-03-19 05:49:43 +00:00
|
|
|
if (IsHost()) {
|
|
|
|
|
auto Value = llvm::sys::fs::getPermissions(file_spec.GetPath());
|
|
|
|
|
if (Value)
|
|
|
|
|
file_permissions = Value.get();
|
2017-05-12 04:51:55 +00:00
|
|
|
return Status(Value.getError());
|
2017-03-19 05:49:43 +00:00
|
|
|
} else {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"remote platform {0} doesn't support {1}", GetPluginName(),
|
|
|
|
|
LLVM_PRETTY_FUNCTION);
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::SetFilePermissions(const FileSpec &file_spec,
|
|
|
|
|
uint32_t file_permissions) {
|
2017-03-19 05:49:43 +00:00
|
|
|
if (IsHost()) {
|
|
|
|
|
auto Perms = static_cast<llvm::sys::fs::perms>(file_permissions);
|
|
|
|
|
return llvm::sys::fs::setPermissions(file_spec.GetPath(), Perms);
|
|
|
|
|
} else {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"remote platform {0} doesn't support {1}", GetPluginName(),
|
|
|
|
|
LLVM_PRETTY_FUNCTION);
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2011-04-12 05:54:46 +00:00
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:38:55 +02:00
|
|
|
user_id_t Platform::OpenFile(const FileSpec &file_spec,
|
|
|
|
|
File::OpenOptions flags, uint32_t mode,
|
|
|
|
|
Status &error) {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);
|
|
|
|
|
return UINT64_MAX;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Platform::CloseFile(user_id_t fd, Status &error) {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return FileCache::GetInstance().CloseFile(fd, error);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
user_id_t Platform::GetFileSize(const FileSpec &file_spec) {
|
|
|
|
|
if (!IsHost())
|
|
|
|
|
return UINT64_MAX;
|
|
|
|
|
|
|
|
|
|
uint64_t Size;
|
|
|
|
|
if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))
|
|
|
|
|
return 0;
|
|
|
|
|
return Size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t Platform::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
|
|
|
|
|
uint64_t dst_len, Status &error) {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormatv(
|
2022-04-01 14:38:55 +02:00
|
|
|
"Platform::ReadFile() is not supported in the {0} platform",
|
|
|
|
|
GetPluginName());
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t Platform::WriteFile(lldb::user_id_t fd, uint64_t offset,
|
|
|
|
|
const void *src, uint64_t src_len, Status &error) {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormatv(
|
2022-04-01 14:38:55 +02:00
|
|
|
"Platform::WriteFile() is not supported in the {0} platform",
|
|
|
|
|
GetPluginName());
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UserIDResolver &Platform::GetUserIDResolver() {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return HostInfo::GetUserIDResolver();
|
|
|
|
|
return UserIDResolver::GetNoopResolver();
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-24 04:28:38 +00:00
|
|
|
const char *Platform::GetHostname() {
|
2011-04-13 22:47:15 +00:00
|
|
|
if (IsHost())
|
2014-02-27 19:38:18 +00:00
|
|
|
return "127.0.0.1";
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
|
2022-02-07 14:52:22 +01:00
|
|
|
if (m_hostname.empty())
|
2016-02-18 00:10:17 +00:00
|
|
|
return nullptr;
|
2022-02-07 14:52:22 +01:00
|
|
|
return m_hostname.c_str();
|
2011-03-24 04:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
2015-08-27 00:53:57 +00:00
|
|
|
ConstString Platform::GetFullNameForDylib(ConstString basename) {
|
|
|
|
|
return basename;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-29 19:52:29 +00:00
|
|
|
bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')",
|
2022-07-25 23:29:30 -07:00
|
|
|
working_dir.GetPath().c_str());
|
2015-05-29 19:52:29 +00:00
|
|
|
m_working_dir = working_dir;
|
2013-12-02 19:35:49 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 15:02:23 +00:00
|
|
|
bool Platform::SetOSVersion(llvm::VersionTuple version) {
|
2011-03-19 01:12:21 +00:00
|
|
|
if (IsHost()) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We don't need anyone setting the OS version for the host platform, we
|
|
|
|
|
// should be able to figure it out by calling HostInfo::GetOSVersion(...).
|
2011-03-19 01:12:21 +00:00
|
|
|
return false;
|
|
|
|
|
} else {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We have a remote platform, allow setting the target OS version if we
|
|
|
|
|
// aren't connected, since if we are connected, we should be able to
|
2014-11-17 19:39:20 +00:00
|
|
|
// request the remote OS version from the connected platform.
|
2012-02-26 05:51:37 +00:00
|
|
|
if (IsConnected())
|
|
|
|
|
return false;
|
2011-03-08 22:40:15 +00:00
|
|
|
else {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We aren't connected and we might want to set the OS version ahead of
|
|
|
|
|
// time before we connect so we can peruse files and use a local SDK or
|
|
|
|
|
// PDK cache of support files to disassemble or do other things.
|
2018-06-18 15:02:23 +00:00
|
|
|
m_os_version = version;
|
2011-03-08 22:40:15 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2011-03-08 22:40:15 +00:00
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status
|
|
|
|
|
Platform::ResolveExecutable(const ModuleSpec &module_spec,
|
|
|
|
|
lldb::ModuleSP &exe_module_sp,
|
|
|
|
|
const FileSpecList *module_search_paths_ptr) {
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
|
|
|
|
|
// We may connect to a process and use the provided executable (Don't use
|
|
|
|
|
// local $PATH).
|
|
|
|
|
ModuleSpec resolved_module_spec(module_spec);
|
|
|
|
|
|
|
|
|
|
// Resolve any executable within a bundle on MacOSX
|
|
|
|
|
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
|
|
|
|
|
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) &&
|
|
|
|
|
!module_spec.GetUUID().IsValid())
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"'{0}' does not exist", resolved_module_spec.GetFileSpec());
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
|
|
|
|
|
if (resolved_module_spec.GetArchitecture().IsValid() ||
|
|
|
|
|
resolved_module_spec.GetUUID().IsValid()) {
|
|
|
|
|
Status error =
|
|
|
|
|
ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
|
|
|
|
|
module_search_paths_ptr, nullptr, nullptr);
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
if (exe_module_sp && exe_module_sp->GetObjectFile())
|
|
|
|
|
return error;
|
|
|
|
|
exe_module_sp.reset();
|
|
|
|
|
}
|
|
|
|
|
// No valid architecture was specified or the exact arch wasn't found.
|
|
|
|
|
// Ask the platform for the architectures that we should be using (in the
|
|
|
|
|
// correct order) and see if we can find a match that way.
|
|
|
|
|
StreamString arch_names;
|
|
|
|
|
llvm::ListSeparator LS;
|
|
|
|
|
ArchSpec process_host_arch;
|
|
|
|
|
Status error;
|
|
|
|
|
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
|
|
|
|
|
resolved_module_spec.GetArchitecture() = arch;
|
|
|
|
|
error =
|
|
|
|
|
ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
|
|
|
|
|
module_search_paths_ptr, nullptr, nullptr);
|
|
|
|
|
if (error.Success()) {
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
if (exe_module_sp && exe_module_sp->GetObjectFile())
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
break;
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString("no exe object file");
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
}
|
|
|
|
|
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
arch_names << LS << arch.GetArchitectureName();
|
|
|
|
|
}
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
if (exe_module_sp && error.Success())
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
if (!FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec()))
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"'{0}' is not readable", resolved_module_spec.GetFileSpec());
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
if (!ObjectFile::IsObjectFile(resolved_module_spec.GetFileSpec()))
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
|
|
|
|
"'{0}' is not a valid executable", resolved_module_spec.GetFileSpec());
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
[lldb] Improve error message for unrecognized executables (#97490)
Currently, LLDB prints out a rather unhelpful error message when passed
a file that it doesn't recognize as an executable.
> error: '/path/to/file' doesn't contain any 'host' platform
> architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em,
> armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s,
> thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t,
> thumb, x86_64, x86_64, arm64, arm64e
I did a quick search internally and found at least 24 instances of users
being confused by this. This patch improves the error message when it
doesn't recognize the file as an executable, but keeps the existing
error message otherwise, i.e. when it's an object file we understand,
but the current platform doesn't support.
2024-07-08 09:29:01 -07:00
|
|
|
"'{0}' doesn't contain any '{1}' platform architectures: {2}",
|
|
|
|
|
resolved_module_spec.GetFileSpec(), GetPluginName(),
|
|
|
|
|
arch_names.GetData());
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
|
|
|
|
|
FileSpec &sym_file) {
|
|
|
|
|
Status error;
|
2018-11-01 17:09:25 +00:00
|
|
|
if (FileSystem::Instance().Exists(sym_spec.GetSymbolFileSpec()))
|
2012-09-12 02:03:59 +00:00
|
|
|
sym_file = sym_spec.GetSymbolFileSpec();
|
|
|
|
|
else
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString("unable to resolve symbol file");
|
2012-09-12 02:03:59 +00:00
|
|
|
return error;
|
2016-02-18 00:10:17 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-08-11 16:25:18 +00:00
|
|
|
bool Platform::ResolveRemotePath(const FileSpec &platform_path,
|
|
|
|
|
FileSpec &resolved_platform_path) {
|
|
|
|
|
resolved_platform_path = platform_path;
|
2018-11-01 21:05:36 +00:00
|
|
|
FileSystem::Instance().Resolve(resolved_platform_path);
|
|
|
|
|
return true;
|
2011-08-11 16:25:18 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-19 01:12:21 +00:00
|
|
|
const ArchSpec &Platform::GetSystemArchitecture() {
|
|
|
|
|
if (IsHost()) {
|
|
|
|
|
if (!m_system_arch.IsValid()) {
|
|
|
|
|
// We have a local host platform
|
2014-08-20 16:42:51 +00:00
|
|
|
m_system_arch = HostInfo::GetArchitecture();
|
2011-03-19 01:12:21 +00:00
|
|
|
m_system_arch_set_while_connected = m_system_arch.IsValid();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We have a remote platform. We can only fetch the remote system
|
|
|
|
|
// architecture if we are connected, and we don't want to do it more than
|
|
|
|
|
// once.
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-19 01:12:21 +00:00
|
|
|
const bool is_connected = IsConnected();
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-03-19 01:12:21 +00:00
|
|
|
bool fetch = false;
|
|
|
|
|
if (m_system_arch.IsValid()) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We have valid OS version info, check to make sure it wasn't manually
|
|
|
|
|
// set prior to connecting. If it was manually set prior to connecting,
|
|
|
|
|
// then lets fetch the actual OS version info if we are now connected.
|
2011-03-19 01:12:21 +00:00
|
|
|
if (is_connected && !m_system_arch_set_while_connected)
|
|
|
|
|
fetch = true;
|
|
|
|
|
} else {
|
|
|
|
|
// We don't have valid OS version info, fetch it if we are connected
|
|
|
|
|
fetch = is_connected;
|
|
|
|
|
}
|
2012-03-26 23:03:23 +00:00
|
|
|
|
2014-10-09 01:02:08 +00:00
|
|
|
if (fetch) {
|
2011-03-24 04:28:38 +00:00
|
|
|
m_system_arch = GetRemoteSystemArchitecture();
|
2011-03-19 01:12:21 +00:00
|
|
|
m_system_arch_set_while_connected = m_system_arch.IsValid();
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-03-19 01:12:21 +00:00
|
|
|
return m_system_arch;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-10-31 10:56:03 +00:00
|
|
|
ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) {
|
|
|
|
|
if (triple.empty())
|
|
|
|
|
return ArchSpec();
|
|
|
|
|
llvm::Triple normalized_triple(llvm::Triple::normalize(triple));
|
|
|
|
|
if (!ArchSpec::ContainsOnlyArch(normalized_triple))
|
|
|
|
|
return ArchSpec(triple);
|
|
|
|
|
|
2017-11-13 15:57:20 +00:00
|
|
|
if (auto kind = HostInfo::ParseArchitectureKind(triple))
|
|
|
|
|
return HostInfo::GetArchitecture(*kind);
|
|
|
|
|
|
2017-10-31 10:56:03 +00:00
|
|
|
ArchSpec compatible_arch;
|
|
|
|
|
ArchSpec raw_arch(triple);
|
2022-03-09 16:00:26 +01:00
|
|
|
if (!IsCompatibleArchitecture(raw_arch, {}, ArchSpec::CompatibleMatch,
|
|
|
|
|
&compatible_arch))
|
2017-10-31 10:56:03 +00:00
|
|
|
return raw_arch;
|
|
|
|
|
|
|
|
|
|
if (!compatible_arch.IsValid())
|
|
|
|
|
return ArchSpec(normalized_triple);
|
|
|
|
|
|
|
|
|
|
const llvm::Triple &compatible_triple = compatible_arch.GetTriple();
|
|
|
|
|
if (normalized_triple.getVendorName().empty())
|
|
|
|
|
normalized_triple.setVendor(compatible_triple.getVendor());
|
|
|
|
|
if (normalized_triple.getOSName().empty())
|
|
|
|
|
normalized_triple.setOS(compatible_triple.getOS());
|
|
|
|
|
if (normalized_triple.getEnvironmentName().empty())
|
|
|
|
|
normalized_triple.setEnvironment(compatible_triple.getEnvironment());
|
|
|
|
|
return ArchSpec(normalized_triple);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::ConnectRemote(Args &args) {
|
|
|
|
|
Status error;
|
2014-10-09 01:02:08 +00:00
|
|
|
if (IsHost())
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
2021-10-15 13:07:39 +02:00
|
|
|
"The currently selected platform ({0}) is "
|
|
|
|
|
"the host platform and is always connected.",
|
|
|
|
|
GetPluginName());
|
2016-09-06 20:57:50 +00:00
|
|
|
else
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
2021-10-15 13:07:39 +02:00
|
|
|
"Platform::ConnectRemote() is not supported by {0}", GetPluginName());
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::DisconnectRemote() {
|
|
|
|
|
Status error;
|
2014-10-09 01:02:08 +00:00
|
|
|
if (IsHost())
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
2021-10-15 13:07:39 +02:00
|
|
|
"The currently selected platform ({0}) is "
|
|
|
|
|
"the host platform and is always connected.",
|
|
|
|
|
GetPluginName());
|
2016-09-06 20:57:50 +00:00
|
|
|
else
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormatv(
|
2021-10-15 13:07:39 +02:00
|
|
|
"Platform::DisconnectRemote() is not supported by {0}",
|
|
|
|
|
GetPluginName());
|
2013-11-20 21:07:01 +00:00
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
bool Platform::GetProcessInfo(lldb::pid_t pid,
|
|
|
|
|
ProcessInstanceInfo &process_info) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// Take care of the host case so that each subclass can just call this
|
|
|
|
|
// function to get the host functionality.
|
2013-11-20 21:07:01 +00:00
|
|
|
if (IsHost())
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
return Host::GetProcessInfo(pid, process_info);
|
2011-03-19 01:12:21 +00:00
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,
|
|
|
|
|
ProcessInstanceInfoList &process_infos) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// Take care of the host case so that each subclass can just call this
|
|
|
|
|
// function to get the host functionality.
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
uint32_t match_count = 0;
|
2013-11-20 21:07:01 +00:00
|
|
|
if (IsHost())
|
2014-10-09 01:02:08 +00:00
|
|
|
match_count = Host::FindProcesses(match_info, process_infos);
|
Many improvements to the Platform base class and subclasses. The base Platform
class now implements the Host functionality for a lot of things that make
sense by default so that subclasses can check:
int
PlatformSubclass::Foo ()
{
if (IsHost())
return Platform::Foo (); // Let the platform base class do the host specific stuff
// Platform subclass specific code...
int result = ...
return result;
}
Added new functions to the platform:
virtual const char *Platform::GetUserName (uint32_t uid);
virtual const char *Platform::GetGroupName (uint32_t gid);
The user and group names are cached locally so that remote platforms can avoid
sending packets multiple times to resolve this information.
Added the parent process ID to the ProcessInfo class.
Added a new ProcessInfoMatch class which helps us to match processes up
and changed the Host layer over to using this new class. The new class allows
us to search for processs:
1 - by name (equal to, starts with, ends with, contains, and regex)
2 - by pid
3 - And further check for parent pid == value, uid == value, gid == value,
euid == value, egid == value, arch == value, parent == value.
This is all hookup up to the "platform process list" command which required
adding dumping routines to dump process information. If the Host class
implements the process lookup routines, you can now lists processes on
your local machine:
machine1.foo.com % lldb
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
94727 244 username usergroup username usergroup x86_64-apple-darwin Xcode
92742 92710 username usergroup username usergroup i386-apple-darwin debugserver
This of course also works remotely with the lldb-platform:
machine1.foo.com % lldb-platform --listen 1234
machine2.foo.com % lldb
(lldb) platform create remote-macosx
Platform: remote-macosx
Connected: no
(lldb) platform connect connect://localhost:1444
Platform: remote-macosx
Triple: x86_64-apple-darwin
OS Version: 10.6.7 (10J869)
Kernel: Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386
Hostname: machine1.foo.com
Connected: yes
(lldb) platform process list
PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME
====== ====== ========== ========== ========== ========== ======================== ============================
99556 244 username usergroup username usergroup x86_64-apple-darwin trustevaluation
99548 65539 username usergroup username usergroup x86_64-apple-darwin lldb
99538 1 username usergroup username usergroup x86_64-apple-darwin FileMerge
94943 1 username usergroup username usergroup x86_64-apple-darwin mdworker
94852 244 username usergroup username usergroup x86_64-apple-darwin Safari
The lldb-platform implements everything with the Host:: layer, so this should
"just work" for linux. I will probably be adding more stuff to the Host layer
for launching processes and attaching to processes so that this support should
eventually just work as well.
Modified the target to be able to be created with an architecture that differs
from the main executable. This is needed for iOS debugging since we can have
an "armv6" binary which can run on an "armv7" machine, so we want to be able
to do:
% lldb
(lldb) platform create remote-ios
(lldb) file --arch armv7 a.out
Where "a.out" is an armv6 executable. The platform then can correctly decide
to open all "armv7" images for all dependent shared libraries.
Modified the disassembly to show the current PC value. Example output:
(lldb) disassemble --frame
a.out`main:
0x1eb7: pushl %ebp
0x1eb8: movl %esp, %ebp
0x1eba: pushl %ebx
0x1ebb: subl $20, %esp
0x1ebe: calll 0x1ec3 ; main + 12 at test.c:18
0x1ec3: popl %ebx
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
0x1edb: leal 213(%ebx), %eax
0x1ee1: movl %eax, (%esp)
0x1ee4: calll 0x1f1e ; puts
0x1ee9: calll 0x1f0c ; getchar
0x1eee: movl $20, (%esp)
0x1ef5: calll 0x1e6a ; sleep_loop at test.c:6
0x1efa: movl $12, %eax
0x1eff: addl $20, %esp
0x1f02: popl %ebx
0x1f03: leave
0x1f04: ret
This can be handy when dealing with the new --line options that was recently
added:
(lldb) disassemble --line
a.out`main + 13 at test.c:19
18 {
-> 19 printf("Process: %i\n\n", getpid());
20 puts("Press any key to continue..."); getchar();
-> 0x1ec4: calll 0x1f12 ; getpid
0x1ec9: movl %eax, 4(%esp)
0x1ecd: leal 199(%ebx), %eax
0x1ed3: movl %eax, (%esp)
0x1ed6: calll 0x1f18 ; printf
Modified the ModuleList to have a lookup based solely on a UUID. Since the
UUID is typically the MD5 checksum of a binary image, there is no need
to give the path and architecture when searching for a pre-existing
image in an image list.
Now that we support remote debugging a bit better, our lldb_private::Module
needs to be able to track what the original path for file was as the platform
knows it, as well as where the file is locally. The module has the two
following functions to retrieve both paths:
const FileSpec &Module::GetFileSpec () const;
const FileSpec &Module::GetPlatformFileSpec () const;
llvm-svn: 128563
2011-03-30 18:16:51 +00:00
|
|
|
return match_count;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-10-06 10:43:31 -07:00
|
|
|
ProcessInstanceInfoList Platform::GetAllProcesses() {
|
|
|
|
|
ProcessInstanceInfoList processes;
|
|
|
|
|
ProcessInstanceInfoMatch match;
|
|
|
|
|
assert(match.MatchAllProcesses());
|
|
|
|
|
FindProcesses(match, processes);
|
|
|
|
|
return processes;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {
|
|
|
|
|
Status error;
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s()", __FUNCTION__);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// Take care of the host case so that each subclass can just call this
|
|
|
|
|
// function to get the host functionality.
|
2013-11-20 21:07:01 +00:00
|
|
|
if (IsHost()) {
|
2012-03-26 23:03:23 +00:00
|
|
|
if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
|
2014-10-09 01:02:08 +00:00
|
|
|
launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2012-03-26 23:03:23 +00:00
|
|
|
if (launch_info.GetFlags().Test(eLaunchFlagLaunchInShell)) {
|
2012-04-14 01:42:46 +00:00
|
|
|
const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
|
|
|
|
|
const bool first_arg_is_full_shell_command = false;
|
2014-10-09 01:02:08 +00:00
|
|
|
uint32_t num_resumes = GetResumeCountForLaunchInfo(launch_info);
|
2016-09-06 20:57:50 +00:00
|
|
|
if (log) {
|
2014-10-20 17:46:43 +00:00
|
|
|
const FileSpec &shell = launch_info.GetShell();
|
2019-02-08 23:36:25 +00:00
|
|
|
std::string shell_str = (shell) ? shell.GetPath() : "<null>";
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32
|
|
|
|
|
", shell is '%s'",
|
|
|
|
|
__FUNCTION__, num_resumes, shell_str.c_str());
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-14 01:42:46 +00:00
|
|
|
if (!launch_info.ConvertArgumentsForLaunchingInShell(
|
2020-10-27 12:39:44 +01:00
|
|
|
error, will_debug, first_arg_is_full_shell_command, num_resumes))
|
2011-03-08 22:40:15 +00:00
|
|
|
return error;
|
2011-04-12 05:54:46 +00:00
|
|
|
} else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {
|
|
|
|
|
error = ShellExpandArguments(launch_info);
|
2015-02-20 21:48:38 +00:00
|
|
|
if (error.Fail()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat(
|
|
|
|
|
"shell expansion failed (reason: %s). "
|
|
|
|
|
"consider launching with 'process "
|
|
|
|
|
"launch'.",
|
|
|
|
|
error.AsCString("unknown"));
|
2011-03-08 22:40:15 +00:00
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2012-03-26 23:03:23 +00:00
|
|
|
}
|
2015-02-20 21:48:38 +00:00
|
|
|
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s final launch_info resume count: %" PRIu32,
|
|
|
|
|
__FUNCTION__, launch_info.GetResumeCount());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
error = Host::LaunchProcess(launch_info);
|
2016-09-06 20:57:50 +00:00
|
|
|
} else
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString(
|
2011-04-12 05:54:46 +00:00
|
|
|
"base lldb_private::Platform class can't launch remote processes");
|
2011-03-08 22:40:15 +00:00
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
|
2015-02-04 23:19:15 +00:00
|
|
|
if (IsHost())
|
2015-02-20 22:20:30 +00:00
|
|
|
return Host::ShellExpandArguments(launch_info);
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString(
|
|
|
|
|
"base lldb_private::Platform class can't expand arguments");
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::KillProcess(const lldb::pid_t pid) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s, pid %" PRIu64, __FUNCTION__, pid);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-05-13 19:44:24 +00:00
|
|
|
if (!IsHost()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString(
|
2021-11-04 13:23:12 +01:00
|
|
|
"base lldb_private::Platform class can't kill remote processes");
|
2015-05-13 19:44:24 +00:00
|
|
|
}
|
2021-11-04 13:23:12 +01:00
|
|
|
Host::Kill(pid, SIGKILL);
|
2017-05-12 04:51:55 +00:00
|
|
|
return Status();
|
2015-02-04 23:19:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-16 11:14:16 +02:00
|
|
|
lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,
|
|
|
|
|
Debugger &debugger, Target &target,
|
|
|
|
|
Status &error) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2023-06-27 18:31:23 -07:00
|
|
|
LLDB_LOG(log, "target = {0}", &target);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
ProcessSP process_sp;
|
|
|
|
|
// Make sure we stop at the entry point
|
|
|
|
|
launch_info.GetFlags().Set(eLaunchFlagDebug);
|
2012-06-01 01:22:13 +00:00
|
|
|
// We always launch the process we are going to debug in a separate process
|
2018-04-30 16:49:04 +00:00
|
|
|
// group, since then we can handle ^C interrupts ourselves w/o having to
|
|
|
|
|
// worry about the target getting them as well.
|
2012-06-01 01:22:13 +00:00
|
|
|
launch_info.SetLaunchInSeparateProcessGroup(true);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2016-08-19 04:21:48 +00:00
|
|
|
// Allow any StructuredData process-bound plugins to adjust the launch info
|
|
|
|
|
// if needed
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
bool iteration_complete = false;
|
2018-04-30 16:49:04 +00:00
|
|
|
// Note iteration can't simply go until a nullptr callback is returned, as it
|
|
|
|
|
// is valid for a plugin to not supply a filter.
|
2016-08-19 04:21:48 +00:00
|
|
|
auto get_filter_func = PluginManager::GetStructuredDataFilterCallbackAtIndex;
|
|
|
|
|
for (auto filter_callback = get_filter_func(i, iteration_complete);
|
|
|
|
|
!iteration_complete;
|
|
|
|
|
filter_callback = get_filter_func(++i, iteration_complete)) {
|
|
|
|
|
if (filter_callback) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// Give this ProcessLaunchInfo filter a chance to adjust the launch info.
|
2021-09-16 11:14:16 +02:00
|
|
|
error = (*filter_callback)(launch_info, &target);
|
2016-08-19 04:21:48 +00:00
|
|
|
if (!error.Success()) {
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"Platform::%s() StructuredDataPlugin launch "
|
|
|
|
|
"filter failed.",
|
|
|
|
|
__FUNCTION__);
|
2016-08-19 04:21:48 +00:00
|
|
|
return process_sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2016-08-19 04:21:48 +00:00
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
error = LaunchProcess(launch_info);
|
|
|
|
|
if (error.Success()) {
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")",
|
|
|
|
|
__FUNCTION__, launch_info.GetProcessID());
|
2011-11-15 03:53:30 +00:00
|
|
|
if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
|
|
|
|
|
ProcessAttachInfo attach_info(launch_info);
|
2021-09-16 11:14:16 +02:00
|
|
|
process_sp = Attach(attach_info, debugger, &target, error);
|
2011-04-12 05:54:46 +00:00
|
|
|
if (process_sp) {
|
2021-10-15 13:07:39 +02:00
|
|
|
LLDB_LOG(log, "Attach() succeeded, Process plugin: {0}",
|
|
|
|
|
process_sp->GetPluginName());
|
2014-01-27 23:43:24 +00:00
|
|
|
launch_info.SetHijackListener(attach_info.GetHijackListener());
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2011-11-17 04:46:02 +00:00
|
|
|
// Since we attached to the process, it will think it needs to detach
|
|
|
|
|
// if the process object just goes away without an explicit call to
|
|
|
|
|
// Process::Kill() or Process::Detach(), so let it know to kill the
|
|
|
|
|
// process if this happens.
|
|
|
|
|
process_sp->SetShouldDetach(false);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2018-04-30 16:49:04 +00:00
|
|
|
// If we didn't have any file actions, the pseudo terminal might have
|
2020-06-15 15:36:14 -07:00
|
|
|
// been used where the secondary side was given as the file to open for
|
2021-11-10 08:50:14 -06:00
|
|
|
// stdin/out/err after we have already opened the primary so we can
|
2018-04-30 16:49:04 +00:00
|
|
|
// read/write stdin/out/err.
|
2020-06-15 15:36:14 -07:00
|
|
|
int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();
|
2017-12-11 10:09:14 +00:00
|
|
|
if (pty_fd != PseudoTerminal::invalid_fd) {
|
2011-11-17 22:14:31 +00:00
|
|
|
process_sp->SetSTDIOFileDescriptor(pty_fd);
|
2014-10-09 01:02:08 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s Attach() failed: %s", __FUNCTION__,
|
|
|
|
|
error.AsCString());
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"Platform::%s LaunchProcess() returned launch_info with "
|
|
|
|
|
"invalid process id",
|
|
|
|
|
__FUNCTION__);
|
2014-10-09 01:02:08 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,
|
|
|
|
|
error.AsCString());
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-10-09 01:02:08 +00:00
|
|
|
|
2011-04-12 05:54:46 +00:00
|
|
|
return process_sp;
|
|
|
|
|
}
|
2012-03-20 18:34:04 +00:00
|
|
|
|
2021-11-10 17:44:37 +01:00
|
|
|
std::vector<ArchSpec>
|
|
|
|
|
Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
|
|
|
|
|
llvm::Triple::OSType os) {
|
|
|
|
|
std::vector<ArchSpec> list;
|
|
|
|
|
for(auto arch : archs) {
|
|
|
|
|
llvm::Triple triple;
|
|
|
|
|
triple.setArch(arch);
|
|
|
|
|
triple.setOS(os);
|
|
|
|
|
list.push_back(ArchSpec(triple));
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-20 18:34:04 +00:00
|
|
|
/// Lets a platform answer if it is compatible with a given
|
|
|
|
|
/// architecture and the target triple contained within.
|
2013-01-11 20:49:54 +00:00
|
|
|
bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,
|
2022-03-14 12:14:16 -07:00
|
|
|
const ArchSpec &process_host_arch,
|
2022-03-09 16:00:26 +01:00
|
|
|
ArchSpec::MatchType match,
|
2013-01-11 20:49:54 +00:00
|
|
|
ArchSpec *compatible_arch_ptr) {
|
2012-03-20 18:34:04 +00:00
|
|
|
// If the architecture is invalid, we must answer true...
|
2012-05-08 01:45:38 +00:00
|
|
|
if (arch.IsValid()) {
|
|
|
|
|
ArchSpec platform_arch;
|
2022-03-14 12:14:16 -07:00
|
|
|
for (const ArchSpec &platform_arch :
|
|
|
|
|
GetSupportedArchitectures(process_host_arch)) {
|
2022-03-09 16:00:26 +01:00
|
|
|
if (arch.IsMatch(platform_arch, match)) {
|
2021-11-17 21:13:56 +01:00
|
|
|
if (compatible_arch_ptr)
|
|
|
|
|
*compatible_arch_ptr = platform_arch;
|
|
|
|
|
return true;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2012-03-20 18:34:04 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2012-05-08 01:45:38 +00:00
|
|
|
if (compatible_arch_ptr)
|
|
|
|
|
compatible_arch_ptr->Clear();
|
2012-03-20 18:34:04 +00:00
|
|
|
return false;
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
|
|
|
|
|
uint32_t uid, uint32_t gid) {
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "[PutFile] Using block by block transfer....\n");
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2019-10-14 20:15:34 +00:00
|
|
|
auto source_open_options =
|
2021-07-28 20:07:03 +02:00
|
|
|
File::eOpenOptionReadOnly | File::eOpenOptionCloseOnExec;
|
2017-03-08 17:56:08 +00:00
|
|
|
namespace fs = llvm::sys::fs;
|
|
|
|
|
if (fs::is_symlink_file(source.GetPath()))
|
2016-06-21 00:03:57 +00:00
|
|
|
source_open_options |= File::eOpenOptionDontFollowSymlinks;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
remove File::SetStream(), make new files instead.
Summary:
This patch removes File::SetStream() and File::SetDescriptor(),
and replaces most direct uses of File with pointers to File.
Instead of calling SetStream() on a file, we make a new file and
replace it.
My ultimate goal here is to introduce a new API class SBFile, which
has full support for python io.IOStream file objects. These can
redirect read() and write() to python code, so lldb::Files will
need a way to dispatch those methods. Additionally it will need some
form of sharing and assigning files, as a SBFile will be passed in and
assigned to the main IO streams of the debugger.
In my prototype patch queue, I make File itself copyable and add a
secondary class FileOps to manage the sharing and dispatch. In that
case SBFile was a unique_ptr<File>.
(here: https://github.com/smoofra/llvm-project/tree/files)
However in review, Pavel Labath suggested that it be shared_ptr instead.
(here: https://reviews.llvm.org/D67793)
In order for SBFile to use shared_ptr<File>, everything else should
as well.
If this patch is accepted, I will make SBFile use a shared_ptr
I will remove FileOps from future patches and use subclasses of File
instead.
Reviewers: JDevlieghere, jasonmolenda, zturner, jingham, labath
Reviewed By: labath
Subscribers: lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D67891
llvm-svn: 373090
2019-09-27 14:33:35 +00:00
|
|
|
auto source_file = FileSystem::Instance().Open(source, source_open_options,
|
|
|
|
|
lldb::eFilePermissionsUserRW);
|
2019-09-26 17:54:59 +00:00
|
|
|
if (!source_file)
|
2024-09-05 12:19:31 -07:00
|
|
|
return Status::FromError(source_file.takeError());
|
2019-09-26 17:54:59 +00:00
|
|
|
Status error;
|
2024-04-18 12:24:24 -07:00
|
|
|
|
|
|
|
|
bool requires_upload = true;
|
2024-05-09 15:57:46 -07:00
|
|
|
llvm::ErrorOr<llvm::MD5::MD5Result> remote_md5 = CalculateMD5(destination);
|
|
|
|
|
if (std::error_code ec = remote_md5.getError()) {
|
|
|
|
|
LLDB_LOG(log, "[PutFile] couldn't get md5 sum of destination: {0}",
|
|
|
|
|
ec.message());
|
2024-04-18 12:24:24 -07:00
|
|
|
} else {
|
2024-05-09 15:57:46 -07:00
|
|
|
llvm::ErrorOr<llvm::MD5::MD5Result> local_md5 =
|
|
|
|
|
llvm::sys::fs::md5_contents(source.GetPath());
|
|
|
|
|
if (std::error_code ec = local_md5.getError()) {
|
|
|
|
|
LLDB_LOG(log, "[PutFile] couldn't get md5 sum of source: {0}",
|
|
|
|
|
ec.message());
|
2024-04-18 12:24:24 -07:00
|
|
|
} else {
|
|
|
|
|
LLDB_LOGF(log, "[PutFile] destination md5: %016" PRIx64 "%016" PRIx64,
|
2024-05-09 15:57:46 -07:00
|
|
|
remote_md5->high(), remote_md5->low());
|
2024-04-18 12:24:24 -07:00
|
|
|
LLDB_LOGF(log, "[PutFile] local md5: %016" PRIx64 "%016" PRIx64,
|
2024-05-09 15:57:46 -07:00
|
|
|
local_md5->high(), local_md5->low());
|
|
|
|
|
requires_upload = *remote_md5 != *local_md5;
|
2024-04-18 12:24:24 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!requires_upload) {
|
|
|
|
|
LLDB_LOGF(log, "[PutFile] skipping PutFile because md5sums match");
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-26 17:54:59 +00:00
|
|
|
uint32_t permissions = source_file.get()->GetPermissions(error);
|
2015-01-21 22:42:49 +00:00
|
|
|
if (permissions == 0)
|
2024-05-14 13:57:37 +04:00
|
|
|
permissions = lldb::eFilePermissionsUserRWX;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-01-21 22:42:49 +00:00
|
|
|
lldb::user_id_t dest_file = OpenFile(
|
2021-07-28 20:07:03 +02:00
|
|
|
destination, File::eOpenOptionCanCreate | File::eOpenOptionWriteOnly |
|
2015-02-17 16:07:52 +00:00
|
|
|
File::eOpenOptionTruncate | File::eOpenOptionCloseOnExec,
|
2015-01-21 22:42:49 +00:00
|
|
|
permissions, error);
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "dest_file = %" PRIu64 "\n", dest_file);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-02-20 21:48:38 +00:00
|
|
|
if (error.Fail())
|
2015-01-21 22:42:49 +00:00
|
|
|
return error;
|
|
|
|
|
if (dest_file == UINT64_MAX)
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString("unable to open target file");
|
2022-04-01 15:59:18 -07:00
|
|
|
lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
|
2015-01-21 22:42:49 +00:00
|
|
|
uint64_t offset = 0;
|
2016-09-06 20:57:50 +00:00
|
|
|
for (;;) {
|
2015-01-21 22:42:49 +00:00
|
|
|
size_t bytes_read = buffer_sp->GetByteSize();
|
2019-09-26 17:54:59 +00:00
|
|
|
error = source_file.get()->Read(buffer_sp->GetBytes(), bytes_read);
|
2015-01-21 22:42:49 +00:00
|
|
|
if (error.Fail() || bytes_read == 0)
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
|
|
|
|
|
2015-01-21 22:42:49 +00:00
|
|
|
const uint64_t bytes_written =
|
|
|
|
|
WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);
|
|
|
|
|
if (error.Fail())
|
|
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-01-21 22:42:49 +00:00
|
|
|
offset += bytes_written;
|
|
|
|
|
if (bytes_written != bytes_read) {
|
2018-04-30 16:49:04 +00:00
|
|
|
// We didn't write the correct number of bytes, so adjust the file
|
|
|
|
|
// position in the source file we are reading from...
|
2019-09-26 17:54:59 +00:00
|
|
|
source_file.get()->SeekFromStart(offset);
|
2015-01-21 22:42:49 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2015-01-21 22:42:49 +00:00
|
|
|
CloseFile(dest_file, error);
|
|
|
|
|
|
|
|
|
|
if (uid == UINT32_MAX && gid == UINT32_MAX)
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
|
|
// TODO: ChownFile?
|
|
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::GetFile(const FileSpec &source, const FileSpec &destination) {
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString("unimplemented");
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status
|
|
|
|
|
Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src
|
|
|
|
|
const FileSpec &dst) // The symlink points to dst
|
2013-11-20 21:07:01 +00:00
|
|
|
{
|
2022-04-01 14:38:55 +02:00
|
|
|
if (IsHost())
|
|
|
|
|
return FileSystem::Instance().Symlink(src, dst);
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString("unimplemented");
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 19:52:29 +00:00
|
|
|
bool Platform::GetFileExists(const lldb_private::FileSpec &file_spec) {
|
2022-04-01 14:38:55 +02:00
|
|
|
if (IsHost())
|
|
|
|
|
return FileSystem::Instance().Exists(file_spec);
|
2013-08-26 23:57:52 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::Unlink(const FileSpec &path) {
|
2022-04-01 14:38:55 +02:00
|
|
|
if (IsHost())
|
|
|
|
|
return llvm::sys::fs::remove(path.GetPath());
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString("unimplemented");
|
2013-11-20 21:07:01 +00:00
|
|
|
}
|
|
|
|
|
|
2017-08-16 12:55:02 +00:00
|
|
|
MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,
|
|
|
|
|
addr_t length, unsigned prot,
|
|
|
|
|
unsigned flags, addr_t fd,
|
|
|
|
|
addr_t offset) {
|
2015-05-09 15:53:31 +00:00
|
|
|
uint64_t flags_platform = 0;
|
|
|
|
|
if (flags & eMmapFlagsPrivate)
|
|
|
|
|
flags_platform |= MAP_PRIVATE;
|
|
|
|
|
if (flags & eMmapFlagsAnon)
|
|
|
|
|
flags_platform |= MAP_ANON;
|
2017-08-16 12:55:02 +00:00
|
|
|
|
|
|
|
|
MmapArgList args({addr, length, prot, flags_platform, fd, offset});
|
|
|
|
|
return args;
|
2015-05-09 15:53:31 +00:00
|
|
|
}
|
2013-11-20 21:07:01 +00:00
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status Platform::RunShellCommand(
|
2020-08-28 15:38:39 +02:00
|
|
|
llvm::StringRef command,
|
|
|
|
|
const FileSpec &
|
|
|
|
|
working_dir, // Pass empty FileSpec to use the current working directory
|
|
|
|
|
int *status_ptr, // Pass nullptr if you don't want the process exit status
|
|
|
|
|
int *signo_ptr, // Pass nullptr if you don't want the signal that caused the
|
|
|
|
|
// process to exit
|
|
|
|
|
std::string
|
|
|
|
|
*command_output, // Pass nullptr if you don't want the command output
|
|
|
|
|
const Timeout<std::micro> &timeout) {
|
|
|
|
|
return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
|
|
|
|
|
signo_ptr, command_output, timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb_private::Status Platform::RunShellCommand(
|
|
|
|
|
llvm::StringRef shell, // Pass empty if you want to use the default
|
|
|
|
|
// shell interpreter
|
|
|
|
|
llvm::StringRef command, // Shouldn't be empty
|
2015-05-29 19:52:29 +00:00
|
|
|
const FileSpec &
|
|
|
|
|
working_dir, // Pass empty FileSpec to use the current working directory
|
2016-02-18 00:10:17 +00:00
|
|
|
int *status_ptr, // Pass nullptr if you don't want the process exit status
|
|
|
|
|
int *signo_ptr, // Pass nullptr if you don't want the signal that caused the
|
|
|
|
|
// process to exit
|
|
|
|
|
std::string
|
|
|
|
|
*command_output, // Pass nullptr if you don't want the command output
|
2018-05-10 10:46:03 +00:00
|
|
|
const Timeout<std::micro> &timeout) {
|
2013-08-26 23:57:52 +00:00
|
|
|
if (IsHost())
|
2020-08-28 15:38:39 +02:00
|
|
|
return Host::RunShellCommand(shell, command, working_dir, status_ptr,
|
|
|
|
|
signo_ptr, command_output, timeout);
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString(
|
|
|
|
|
"unable to run a remote command without a platform");
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-09 15:57:46 -07:00
|
|
|
llvm::ErrorOr<llvm::MD5::MD5Result>
|
|
|
|
|
Platform::CalculateMD5(const FileSpec &file_spec) {
|
2017-03-20 23:54:54 +00:00
|
|
|
if (!IsHost())
|
2024-05-09 15:57:46 -07:00
|
|
|
return std::make_error_code(std::errc::not_supported);
|
|
|
|
|
return llvm::sys::fs::md5_contents(file_spec.GetPath());
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Platform::SetLocalCacheDirectory(const char *local) {
|
|
|
|
|
m_local_cache_directory.assign(local);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *Platform::GetLocalCacheDirectory() {
|
|
|
|
|
return m_local_cache_directory.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 18:50:19 +00:00
|
|
|
static constexpr OptionDefinition g_rsync_option_table[] = {
|
2016-02-18 00:10:17 +00:00
|
|
|
{LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr,
|
2018-09-26 18:50:19 +00:00
|
|
|
{}, 0, eArgTypeNone, "Enable rsync."},
|
2016-02-18 00:10:17 +00:00
|
|
|
{LLDB_OPT_SET_ALL, false, "rsync-opts", 'R',
|
2018-09-26 18:50:19 +00:00
|
|
|
OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
|
2016-02-18 00:10:17 +00:00
|
|
|
"Platform-specific options required for rsync to work."},
|
|
|
|
|
{LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P',
|
2018-09-26 18:50:19 +00:00
|
|
|
OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
|
2016-02-18 00:10:17 +00:00
|
|
|
"Platform-specific rsync prefix put before the remote path."},
|
|
|
|
|
{LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i',
|
2018-09-26 18:50:19 +00:00
|
|
|
OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
|
2016-02-18 00:10:17 +00:00
|
|
|
"Do not automatically fill in the remote hostname when composing the "
|
|
|
|
|
"rsync command."},
|
2013-08-26 23:57:52 +00:00
|
|
|
};
|
|
|
|
|
|
2018-09-26 18:50:19 +00:00
|
|
|
static constexpr OptionDefinition g_ssh_option_table[] = {
|
2016-02-18 00:10:17 +00:00
|
|
|
{LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr,
|
2018-09-26 18:50:19 +00:00
|
|
|
{}, 0, eArgTypeNone, "Enable SSH."},
|
2016-02-18 00:10:17 +00:00
|
|
|
{LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument,
|
2018-09-26 18:50:19 +00:00
|
|
|
nullptr, {}, 0, eArgTypeCommandName,
|
2016-02-18 00:10:17 +00:00
|
|
|
"Platform-specific options required for SSH to work."},
|
2013-08-26 23:57:52 +00:00
|
|
|
};
|
|
|
|
|
|
2018-09-26 18:50:19 +00:00
|
|
|
static constexpr OptionDefinition g_caching_option_table[] = {
|
2016-02-18 00:10:17 +00:00
|
|
|
{LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c',
|
2018-09-26 18:50:19 +00:00
|
|
|
OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath,
|
2016-02-18 00:10:17 +00:00
|
|
|
"Path in which to store local copies of files."},
|
2013-08-26 23:57:52 +00:00
|
|
|
};
|
|
|
|
|
|
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
|
|
|
llvm::ArrayRef<OptionDefinition> OptionGroupPlatformRSync::GetDefinitions() {
|
2023-01-09 18:11:07 +01:00
|
|
|
return llvm::ArrayRef(g_rsync_option_table);
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-11 23:51:28 +00:00
|
|
|
void OptionGroupPlatformRSync::OptionParsingStarting(
|
|
|
|
|
ExecutionContext *execution_context) {
|
2013-08-26 23:57:52 +00:00
|
|
|
m_rsync = false;
|
|
|
|
|
m_rsync_opts.clear();
|
|
|
|
|
m_rsync_prefix.clear();
|
|
|
|
|
m_ignores_remote_hostname = false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status
|
2016-08-11 23:51:28 +00:00
|
|
|
OptionGroupPlatformRSync::SetOptionValue(uint32_t option_idx,
|
2016-09-23 17:48:13 +00:00
|
|
|
llvm::StringRef option_arg,
|
2016-08-11 23:51:28 +00:00
|
|
|
ExecutionContext *execution_context) {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2013-08-26 23:57:52 +00:00
|
|
|
char short_option = (char)GetDefinitions()[option_idx].short_option;
|
|
|
|
|
switch (short_option) {
|
|
|
|
|
case 'r':
|
|
|
|
|
m_rsync = true;
|
|
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
case 'R':
|
2020-01-28 20:23:46 +01:00
|
|
|
m_rsync_opts.assign(std::string(option_arg));
|
2013-08-26 23:57:52 +00:00
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
case 'P':
|
2020-01-28 20:23:46 +01:00
|
|
|
m_rsync_prefix.assign(std::string(option_arg));
|
2013-08-26 23:57:52 +00:00
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
case 'i':
|
|
|
|
|
m_ignores_remote_hostname = true;
|
|
|
|
|
break;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
default:
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat("unrecognized option '%c'",
|
|
|
|
|
short_option);
|
2013-08-26 23:57:52 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2013-08-26 23:57:52 +00:00
|
|
|
return error;
|
2012-03-20 18:34:04 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-15 02:33:01 +00:00
|
|
|
lldb::BreakpointSP
|
|
|
|
|
Platform::SetThreadCreationBreakpoint(lldb_private::Target &target) {
|
|
|
|
|
return lldb::BreakpointSP();
|
|
|
|
|
}
|
2012-03-20 18:34:04 +00:00
|
|
|
|
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
|
|
|
llvm::ArrayRef<OptionDefinition> OptionGroupPlatformSSH::GetDefinitions() {
|
2023-01-09 18:11:07 +01:00
|
|
|
return llvm::ArrayRef(g_ssh_option_table);
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-11 23:51:28 +00:00
|
|
|
void OptionGroupPlatformSSH::OptionParsingStarting(
|
|
|
|
|
ExecutionContext *execution_context) {
|
2013-08-26 23:57:52 +00:00
|
|
|
m_ssh = false;
|
|
|
|
|
m_ssh_opts.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status
|
2016-08-11 23:51:28 +00:00
|
|
|
OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx,
|
2016-09-23 17:48:13 +00:00
|
|
|
llvm::StringRef option_arg,
|
2016-08-11 23:51:28 +00:00
|
|
|
ExecutionContext *execution_context) {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2013-08-26 23:57:52 +00:00
|
|
|
char short_option = (char)GetDefinitions()[option_idx].short_option;
|
|
|
|
|
switch (short_option) {
|
|
|
|
|
case 's':
|
|
|
|
|
m_ssh = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'S':
|
2020-01-28 20:23:46 +01:00
|
|
|
m_ssh_opts.assign(std::string(option_arg));
|
2013-08-26 23:57:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat("unrecognized option '%c'",
|
|
|
|
|
short_option);
|
2013-08-26 23:57:52 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-11 23:51:28 +00:00
|
|
|
return error;
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
Convert option tables to ArrayRefs.
This change is very mechanical. All it does is change the
signature of `Options::GetDefinitions()` and `OptionGroup::
GetDefinitions()` to return an `ArrayRef<OptionDefinition>`
instead of a `const OptionDefinition *`. In the case of the
former, it deletes the sentinel entry from every table, and
in the case of the latter, it removes the `GetNumDefinitions()`
method from the interface. These are no longer necessary as
`ArrayRef` carries its own length.
In the former case, iteration was done by using a sentinel
entry, so there was no knowledge of length. Because of this
the individual option tables were allowed to be defined below
the corresponding class (after all, only a pointer was needed).
Now, however, the length must be known at compile time to
construct the `ArrayRef`, and as a result it is necessary to
move every option table before its corresponding class. This
results in this CL looking very big, but in terms of substance
there is not much here.
Differential revision: https://reviews.llvm.org/D24834
llvm-svn: 282188
2016-09-22 20:22:55 +00:00
|
|
|
llvm::ArrayRef<OptionDefinition> OptionGroupPlatformCaching::GetDefinitions() {
|
2023-01-09 18:11:07 +01:00
|
|
|
return llvm::ArrayRef(g_caching_option_table);
|
2013-08-26 23:57:52 +00:00
|
|
|
}
|
|
|
|
|
|
2012-08-22 17:17:09 +00:00
|
|
|
void OptionGroupPlatformCaching::OptionParsingStarting(
|
|
|
|
|
ExecutionContext *execution_context) {
|
|
|
|
|
m_cache_dir.clear();
|
|
|
|
|
}
|
2014-02-13 23:11:45 +00:00
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status OptionGroupPlatformCaching::SetOptionValue(
|
2016-09-23 17:48:13 +00:00
|
|
|
uint32_t option_idx, llvm::StringRef option_arg,
|
2016-08-11 23:51:28 +00:00
|
|
|
ExecutionContext *execution_context) {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2014-02-13 23:11:45 +00:00
|
|
|
char short_option = (char)GetDefinitions()[option_idx].short_option;
|
2013-08-26 23:57:52 +00:00
|
|
|
switch (short_option) {
|
|
|
|
|
case 'c':
|
2020-01-28 20:23:46 +01:00
|
|
|
m_cache_dir.assign(std::string(option_arg));
|
2016-09-06 20:57:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat("unrecognized option '%c'",
|
|
|
|
|
short_option);
|
2014-05-23 23:11:27 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2014-02-13 23:11:45 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:38:55 +02:00
|
|
|
Environment Platform::GetEnvironment() {
|
|
|
|
|
if (IsHost())
|
|
|
|
|
return Host::GetEnvironment();
|
|
|
|
|
return Environment();
|
|
|
|
|
}
|
2015-03-13 18:44:56 +00:00
|
|
|
|
|
|
|
|
const std::vector<ConstString> &Platform::GetTrapHandlerSymbolNames() {
|
2015-03-24 23:45:49 +00:00
|
|
|
if (!m_calculated_trap_handlers) {
|
|
|
|
|
std::lock_guard<std::mutex> guard(m_mutex);
|
2015-03-24 11:15:23 +00:00
|
|
|
if (!m_calculated_trap_handlers) {
|
2016-07-12 03:25:22 +00:00
|
|
|
CalculateTrapHandlerSymbolNames();
|
|
|
|
|
m_calculated_trap_handlers = true;
|
2015-03-24 11:15:23 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2014-05-23 23:11:27 +00:00
|
|
|
return m_trap_handlers;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
Status
|
|
|
|
|
Platform::GetCachedExecutable(ModuleSpec &module_spec,
|
|
|
|
|
lldb::ModuleSP &module_sp,
|
|
|
|
|
const FileSpecList *module_search_paths_ptr) {
|
2021-11-26 09:26:52 +01:00
|
|
|
FileSpec platform_spec = module_spec.GetFileSpec();
|
|
|
|
|
Status error = GetRemoteSharedModule(
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
module_spec, nullptr, module_sp,
|
|
|
|
|
[&](const ModuleSpec &spec) {
|
2024-07-12 20:43:08 +02:00
|
|
|
return Platform::ResolveExecutable(spec, module_sp,
|
|
|
|
|
module_search_paths_ptr);
|
[lldb] Refactor Platform::ResolveExecutable
Module resolution is probably the most complex piece of lldb [citation
needed], with numerous levels of abstraction, each one implementing
various retry and fallback strategies.
It is also a very repetitive, with only small differences between
"host", "remote-and-connected" and "remote-but-not-(yet)-connected"
scenarios.
The goal of this patch (first in series) is to reduce the number of
abstractions, and deduplicate the code.
One of the reasons for this complexity is the tension between the desire
to offload the process of module resolution to the remote platform
instance (that's how most other platform methods work), and the desire
to keep it local to the outer platform class (its easier to subclass the
outer class, and it generally makes more sense).
This patch resolves that conflict in favour of doing everything in the
outer class. The gdb-remote (our only remote platform) implementation of
ResolveExecutable was not doing anything gdb-specific, and was rather
similar to the other implementations of that method (any divergence is
most likely the result of fixes not being applied everywhere rather than
intentional).
It does this by excising the remote platform out of the resolution
codepath. The gdb-remote implementation of ResolveExecutable is moved to
Platform::ResolveRemoteExecutable, and the (only) call site is
redirected to that. On its own, this does not achieve (much), but it
creates new opportunities for layer peeling and code sharing, since all
of the code now lives closer together.
Differential Revision: https://reviews.llvm.org/D113487
2021-11-09 16:32:57 +01:00
|
|
|
},
|
|
|
|
|
nullptr);
|
2021-11-26 09:26:52 +01:00
|
|
|
if (error.Success()) {
|
|
|
|
|
module_spec.GetFileSpec() = module_sp->GetFileSpec();
|
|
|
|
|
module_spec.GetPlatformFileSpec() = platform_spec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return error;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
|
|
|
|
|
Process *process,
|
|
|
|
|
lldb::ModuleSP &module_sp,
|
|
|
|
|
const ModuleResolver &module_resolver,
|
|
|
|
|
bool *did_create_ptr) {
|
2015-03-24 11:15:23 +00:00
|
|
|
// Get module information from a target.
|
|
|
|
|
ModuleSpec resolved_module_spec;
|
2022-03-14 12:14:16 -07:00
|
|
|
ArchSpec process_host_arch;
|
2015-03-24 11:15:23 +00:00
|
|
|
bool got_module_spec = false;
|
|
|
|
|
if (process) {
|
2022-03-14 12:14:16 -07:00
|
|
|
process_host_arch = process->GetSystemArchitecture();
|
2015-03-24 11:15:23 +00:00
|
|
|
// Try to get module information from the process
|
|
|
|
|
if (process->GetModuleSpec(module_spec.GetFileSpec(),
|
2016-07-12 03:25:22 +00:00
|
|
|
module_spec.GetArchitecture(),
|
|
|
|
|
resolved_module_spec)) {
|
2018-12-15 00:15:33 +00:00
|
|
|
if (!module_spec.GetUUID().IsValid() ||
|
2016-07-12 03:25:22 +00:00
|
|
|
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
|
|
|
|
|
got_module_spec = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2016-07-12 03:25:22 +00:00
|
|
|
|
2018-12-15 00:15:33 +00:00
|
|
|
if (!module_spec.GetArchitecture().IsValid()) {
|
2017-05-12 04:51:55 +00:00
|
|
|
Status error;
|
2018-04-30 16:49:04 +00:00
|
|
|
// No valid architecture was specified, ask the platform for the
|
|
|
|
|
// architectures that we should be using (in the correct order) and see if
|
|
|
|
|
// we can find a match that way
|
2016-10-05 02:29:13 +00:00
|
|
|
ModuleSpec arch_module_spec(module_spec);
|
2022-03-14 12:14:16 -07:00
|
|
|
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
|
2021-11-17 21:13:56 +01:00
|
|
|
arch_module_spec.GetArchitecture() = arch;
|
2016-10-05 02:29:13 +00:00
|
|
|
error = ModuleList::GetSharedModule(arch_module_spec, module_sp, nullptr,
|
|
|
|
|
nullptr, nullptr);
|
|
|
|
|
// Did we find an executable using one of the
|
|
|
|
|
if (error.Success() && module_sp)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-23 06:00:50 -07:00
|
|
|
if (module_sp) {
|
|
|
|
|
resolved_module_spec = arch_module_spec;
|
2016-10-05 02:29:13 +00:00
|
|
|
got_module_spec = true;
|
2020-09-23 06:00:50 -07:00
|
|
|
}
|
2016-10-05 02:29:13 +00:00
|
|
|
}
|
|
|
|
|
|
2016-07-12 03:25:22 +00:00
|
|
|
if (!got_module_spec) {
|
|
|
|
|
// Get module information from a target.
|
2020-09-23 06:00:50 -07:00
|
|
|
if (GetModuleSpec(module_spec.GetFileSpec(), module_spec.GetArchitecture(),
|
|
|
|
|
resolved_module_spec)) {
|
2018-12-15 00:15:33 +00:00
|
|
|
if (!module_spec.GetUUID().IsValid() ||
|
2016-07-12 03:25:22 +00:00
|
|
|
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
|
2020-09-23 06:00:50 -07:00
|
|
|
got_module_spec = true;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2015-03-24 11:15:23 +00:00
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2015-03-10 01:15:28 +00:00
|
|
|
|
2020-09-23 06:00:50 -07:00
|
|
|
if (!got_module_spec) {
|
|
|
|
|
// Fall back to the given module resolver, which may have its own
|
|
|
|
|
// search logic.
|
|
|
|
|
return module_resolver(module_spec);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-24 23:45:49 +00:00
|
|
|
// If we are looking for a specific UUID, make sure resolved_module_spec has
|
|
|
|
|
// the same one before we search.
|
|
|
|
|
if (module_spec.GetUUID().IsValid()) {
|
|
|
|
|
resolved_module_spec.GetUUID() = module_spec.GetUUID();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 16:45:57 -07:00
|
|
|
// Call locate module callback if set. This allows users to implement their
|
|
|
|
|
// own module cache system. For example, to leverage build system artifacts,
|
|
|
|
|
// to bypass pulling files from remote platform, or to search symbol files
|
|
|
|
|
// from symbol servers.
|
|
|
|
|
FileSpec symbol_file_spec;
|
|
|
|
|
CallLocateModuleCallbackIfSet(resolved_module_spec, module_sp,
|
|
|
|
|
symbol_file_spec, did_create_ptr);
|
|
|
|
|
if (module_sp) {
|
|
|
|
|
// The module is loaded.
|
|
|
|
|
if (symbol_file_spec) {
|
|
|
|
|
// 1. module_sp:loaded, symbol_file_spec:set
|
|
|
|
|
// The callback found a module file and a symbol file for this
|
|
|
|
|
// resolved_module_spec. Set the symbol file to the module.
|
|
|
|
|
module_sp->SetSymbolFileFileSpec(symbol_file_spec);
|
|
|
|
|
} else {
|
|
|
|
|
// 2. module_sp:loaded, symbol_file_spec:empty
|
|
|
|
|
// The callback only found a module file for this
|
|
|
|
|
// resolved_module_spec.
|
|
|
|
|
}
|
|
|
|
|
return Status();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The module is not loaded by CallLocateModuleCallbackIfSet.
|
|
|
|
|
// 3. module_sp:empty, symbol_file_spec:set
|
|
|
|
|
// The callback only found a symbol file for the module. We continue to
|
|
|
|
|
// find a module file for this resolved_module_spec. and we will call
|
|
|
|
|
// module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.
|
|
|
|
|
// 4. module_sp:empty, symbol_file_spec:empty
|
|
|
|
|
// The callback is not set. Or the callback did not find any module
|
|
|
|
|
// files nor any symbol files. Or the callback failed, or something
|
|
|
|
|
// went wrong. We continue to find a module file for this
|
|
|
|
|
// resolved_module_spec.
|
|
|
|
|
|
2015-03-24 23:45:49 +00:00
|
|
|
// Trying to find a module by UUID on local file system.
|
2024-09-05 12:44:13 -07:00
|
|
|
Status error = module_resolver(resolved_module_spec);
|
2023-07-22 16:45:57 -07:00
|
|
|
if (error.Success()) {
|
|
|
|
|
if (module_sp && symbol_file_spec) {
|
|
|
|
|
// Set the symbol file to the module if the locate modudle callback was
|
|
|
|
|
// called and returned only a symbol file.
|
|
|
|
|
module_sp->SetSymbolFileFileSpec(symbol_file_spec);
|
|
|
|
|
}
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fallback to call GetCachedSharedModule on failure.
|
|
|
|
|
if (GetCachedSharedModule(resolved_module_spec, module_sp, did_create_ptr)) {
|
|
|
|
|
if (module_sp && symbol_file_spec) {
|
|
|
|
|
// Set the symbol file to the module if the locate modudle callback was
|
|
|
|
|
// called and returned only a symbol file.
|
|
|
|
|
module_sp->SetSymbolFileFileSpec(symbol_file_spec);
|
|
|
|
|
}
|
|
|
|
|
return Status();
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorStringWithFormat(
|
|
|
|
|
"Failed to call GetCachedSharedModule");
|
2023-07-22 16:45:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,
|
|
|
|
|
lldb::ModuleSP &module_sp,
|
|
|
|
|
FileSpec &symbol_file_spec,
|
|
|
|
|
bool *did_create_ptr) {
|
|
|
|
|
if (!m_locate_module_callback) {
|
|
|
|
|
// Locate module callback is not set.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileSpec module_file_spec;
|
|
|
|
|
Status error =
|
|
|
|
|
m_locate_module_callback(module_spec, module_file_spec, symbol_file_spec);
|
|
|
|
|
|
|
|
|
|
// Locate module callback is set and called. Check the error.
|
|
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2015-01-21 22:42:49 +00:00
|
|
|
if (error.Fail()) {
|
2023-07-22 16:45:57 -07:00
|
|
|
LLDB_LOGF(log, "%s: locate module callback failed: %s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, error.AsCString());
|
|
|
|
|
return;
|
2015-03-24 23:45:49 +00:00
|
|
|
}
|
|
|
|
|
|
2023-07-22 16:45:57 -07:00
|
|
|
// The locate module callback was succeeded.
|
|
|
|
|
// Check the module_file_spec and symbol_file_spec values.
|
|
|
|
|
// 1. module:empty symbol:empty -> Failure
|
|
|
|
|
// - The callback did not return any files.
|
|
|
|
|
// 2. module:exists symbol:exists -> Success
|
|
|
|
|
// - The callback returned a module file and a symbol file.
|
|
|
|
|
// 3. module:exists symbol:empty -> Success
|
|
|
|
|
// - The callback returned only a module file.
|
|
|
|
|
// 4. module:empty symbol:exists -> Success
|
|
|
|
|
// - The callback returned only a symbol file.
|
|
|
|
|
// For example, a breakpad symbol text file.
|
|
|
|
|
if (!module_file_spec && !symbol_file_spec) {
|
|
|
|
|
// This is '1. module:empty symbol:empty -> Failure'
|
|
|
|
|
// The callback did not return any files.
|
|
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"%s: locate module callback did not set both "
|
|
|
|
|
"module_file_spec and symbol_file_spec",
|
|
|
|
|
LLVM_PRETTY_FUNCTION);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the callback returned a module file, it should exist.
|
|
|
|
|
if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) {
|
|
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"%s: locate module callback set a non-existent file to "
|
|
|
|
|
"module_file_spec: %s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str());
|
|
|
|
|
// Clear symbol_file_spec for the error.
|
|
|
|
|
symbol_file_spec.Clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the callback returned a symbol file, it should exist.
|
|
|
|
|
if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) {
|
|
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"%s: locate module callback set a non-existent file to "
|
|
|
|
|
"symbol_file_spec: %s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());
|
|
|
|
|
// Clear symbol_file_spec for the error.
|
|
|
|
|
symbol_file_spec.Clear();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!module_file_spec && symbol_file_spec) {
|
|
|
|
|
// This is '4. module:empty symbol:exists -> Success'
|
|
|
|
|
// The locate module callback returned only a symbol file. For example,
|
|
|
|
|
// a breakpad symbol text file. GetRemoteSharedModule will use this returned
|
|
|
|
|
// symbol_file_spec.
|
|
|
|
|
LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is one of the following.
|
|
|
|
|
// - 2. module:exists symbol:exists -> Success
|
|
|
|
|
// - The callback returned a module file and a symbol file.
|
|
|
|
|
// - 3. module:exists symbol:empty -> Success
|
|
|
|
|
// - The callback returned Only a module file.
|
|
|
|
|
// Load the module file.
|
|
|
|
|
auto cached_module_spec(module_spec);
|
|
|
|
|
cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5
|
|
|
|
|
// content hash instead of real UUID.
|
|
|
|
|
cached_module_spec.GetFileSpec() = module_file_spec;
|
|
|
|
|
cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();
|
|
|
|
|
cached_module_spec.SetObjectOffset(0);
|
|
|
|
|
|
|
|
|
|
error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr,
|
|
|
|
|
nullptr, did_create_ptr, false);
|
|
|
|
|
if (error.Success() && module_sp) {
|
|
|
|
|
// Succeeded to load the module file.
|
|
|
|
|
LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),
|
|
|
|
|
symbol_file_spec.GetPath().c_str());
|
|
|
|
|
} else {
|
|
|
|
|
LLDB_LOGF(log,
|
|
|
|
|
"%s: locate module callback succeeded but failed to load: "
|
|
|
|
|
"module=%s symbol=%s",
|
|
|
|
|
LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),
|
|
|
|
|
symbol_file_spec.GetPath().c_str());
|
|
|
|
|
// Clear module_sp and symbol_file_spec for the error.
|
|
|
|
|
module_sp.reset();
|
|
|
|
|
symbol_file_spec.Clear();
|
|
|
|
|
}
|
2015-04-15 14:35:10 +00:00
|
|
|
}
|
2015-03-10 01:15:28 +00:00
|
|
|
|
|
|
|
|
bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,
|
2015-03-24 23:45:49 +00:00
|
|
|
lldb::ModuleSP &module_sp,
|
|
|
|
|
bool *did_create_ptr) {
|
2021-10-07 15:44:47 +02:00
|
|
|
if (IsHost() || !GetGlobalPlatformProperties().GetUseModuleCache() ||
|
|
|
|
|
!GetGlobalPlatformProperties().GetModuleCacheDirectory())
|
2015-04-15 14:35:10 +00:00
|
|
|
return false;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2022-01-31 15:57:48 +01:00
|
|
|
Log *log = GetLog(LLDBLog::Platform);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
// Check local cache for a module.
|
2015-04-15 14:35:10 +00:00
|
|
|
auto error = m_module_cache->GetAndPut(
|
2015-03-24 11:15:23 +00:00
|
|
|
GetModuleCacheRoot(), GetCacheHostname(), module_spec,
|
2015-08-12 11:10:25 +00:00
|
|
|
[this](const ModuleSpec &module_spec,
|
|
|
|
|
const FileSpec &tmp_download_file_spec) {
|
2015-04-15 14:35:10 +00:00
|
|
|
return DownloadModuleSlice(
|
2015-03-24 11:15:23 +00:00
|
|
|
module_spec.GetFileSpec(), module_spec.GetObjectOffset(),
|
2015-08-12 11:10:25 +00:00
|
|
|
module_spec.GetObjectSize(), tmp_download_file_spec);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
|
|
|
|
},
|
2015-08-12 11:10:25 +00:00
|
|
|
[this](const ModuleSP &module_sp,
|
|
|
|
|
const FileSpec &tmp_download_file_spec) {
|
|
|
|
|
return DownloadSymbolFile(module_sp, tmp_download_file_spec);
|
2016-09-06 20:57:50 +00:00
|
|
|
},
|
2015-03-24 23:45:49 +00:00
|
|
|
module_sp, did_create_ptr);
|
2013-11-20 21:07:01 +00:00
|
|
|
if (error.Success())
|
2015-03-10 01:15:28 +00:00
|
|
|
return true;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2019-07-24 17:56:10 +00:00
|
|
|
LLDB_LOGF(log, "Platform::%s - module %s not found in local cache: %s",
|
|
|
|
|
__FUNCTION__, module_spec.GetUUID().GetAsString().c_str(),
|
|
|
|
|
error.AsCString());
|
2012-08-22 17:17:09 +00:00
|
|
|
return false;
|
2015-03-10 01:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::DownloadModuleSlice(const FileSpec &src_file_spec,
|
|
|
|
|
const uint64_t src_offset,
|
|
|
|
|
const uint64_t src_size,
|
|
|
|
|
const FileSpec &dst_file_spec) {
|
|
|
|
|
Status error;
|
2015-03-10 01:15:28 +00:00
|
|
|
|
2017-03-21 13:49:50 +00:00
|
|
|
std::error_code EC;
|
2019-08-05 05:43:48 +00:00
|
|
|
llvm::raw_fd_ostream dst(dst_file_spec.GetPath(), EC, llvm::sys::fs::OF_None);
|
2017-03-21 13:49:50 +00:00
|
|
|
if (EC) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat(
|
|
|
|
|
"unable to open destination file: %s", dst_file_spec.GetPath().c_str());
|
2015-03-10 01:15:28 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 20:07:03 +02:00
|
|
|
auto src_fd = OpenFile(src_file_spec, File::eOpenOptionReadOnly,
|
2015-03-10 01:15:28 +00:00
|
|
|
lldb::eFilePermissionsFileDefault, error);
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
if (error.Fail()) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorStringWithFormat("unable to open source file: %s",
|
|
|
|
|
error.AsCString());
|
2015-03-10 01:15:28 +00:00
|
|
|
return error;
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
|
lldb: do more than 1 kilobyte at a time to vastly increase binary sync speed
https://github.com/llvm/llvm-project/issues/62750
I setup a simple test with a large .so (~100MiB) that was only present on the target machine
but not present on the local machine, and ran a lldb server on the target and connectd to it.
LLDB properly downloads the file from the remote, but it does so at a very slow speed, even over a hardwired 1Gbps connection!
Increasing the buffer size for downloading these helps quite a bit.
Test setup:
```
$ cat gen.py
print('const char* hugeglobal = ')
for _ in range(1000*500):
print(' "' + '1234'*50 + '"')
print(';')
print('const char* mystring() { return hugeglobal; }')
$ gen.py > huge.c
$ mkdir libdir
$ gcc -fPIC huge.c -Wl,-soname,libhuge.so -o libdir/libhuge.so -shared
$ cat test.c
#include <string.h>
#include <stdio.h>
extern const char* mystring();
int main() {
printf("%d\n", strlen(mystring()));
}
$ gcc test.c -L libdir -l huge -Wl,-rpath='$ORIGIN' -o test
$ rsync -a libdir remote:~/
$ ssh remote bash -c "cd ~/libdir && /llvm/buildr/bin/lldb-server platform --server --listen '*:1234'"
```
in another terminal
```
$ rm -rf ~/.lldb # clear cache
$ cat connect.lldb
platform select remote-linux
platform connect connect://10.0.0.14:1234
file test
b main
r
image list
c
q
$ time /llvm/buildr/bin/lldb --source connect.lldb
```
Times with various buffer sizes:
1kiB (current): ~22s
8kiB: ~8s
16kiB: ~4s
32kiB: ~3.5s
64kiB: ~2.8s
128kiB: ~2.6s
256kiB: ~2.1s
512kiB: ~2.1s
1MiB: ~2.1s
2MiB: ~2.1s
I choose 512kiB from this list as it seems to be the place where the returns start diminishing and still isn't that much memory
My understanding of how this makes such a difference is ReadFile issues a request for each call, and larger buffer means less round trip times. The "ideal" situation is ReadFile() being async and being able to issue multiple of these, but that is much more work for probably little gains.
NOTE: this is my first contribution, so wasn't sure who to choose as a reviewer. Greg Clayton seems to be the most appropriate of those in CODE_OWNERS.txt
Reviewed By: clayborg, jasonmolenda
Differential Revision: https://reviews.llvm.org/D153060
2023-06-19 09:59:20 +00:00
|
|
|
std::vector<char> buffer(512 * 1024);
|
2015-03-10 01:15:28 +00:00
|
|
|
auto offset = src_offset;
|
|
|
|
|
uint64_t total_bytes_read = 0;
|
|
|
|
|
while (total_bytes_read < src_size) {
|
|
|
|
|
const auto to_read = std::min(static_cast<uint64_t>(buffer.size()),
|
|
|
|
|
src_size - total_bytes_read);
|
|
|
|
|
const uint64_t n_read =
|
|
|
|
|
ReadFile(src_fd, offset, &buffer[0], to_read, error);
|
|
|
|
|
if (error.Fail())
|
|
|
|
|
break;
|
|
|
|
|
if (n_read == 0) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString("read 0 bytes");
|
2015-03-10 01:15:28 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
offset += n_read;
|
|
|
|
|
total_bytes_read += n_read;
|
|
|
|
|
dst.write(&buffer[0], n_read);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
2015-03-10 01:15:28 +00:00
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status close_error;
|
2015-03-10 01:15:28 +00:00
|
|
|
CloseFile(src_fd, close_error); // Ignoring close error.
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
|
|
|
|
|
const FileSpec &dst_file_spec) {
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString(
|
2015-08-12 11:10:25 +00:00
|
|
|
"Symbol file downloading not supported by the default platform.");
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-10 01:15:28 +00:00
|
|
|
FileSpec Platform::GetModuleCacheRoot() {
|
2021-10-07 15:44:47 +02:00
|
|
|
auto dir_spec = GetGlobalPlatformProperties().GetModuleCacheDirectory();
|
2022-02-07 16:21:57 +01:00
|
|
|
dir_spec.AppendPathComponent(GetPluginName());
|
2015-03-10 01:15:28 +00:00
|
|
|
return dir_spec;
|
|
|
|
|
}
|
2015-03-25 17:58:13 +00:00
|
|
|
|
|
|
|
|
const char *Platform::GetCacheHostname() { return GetHostname(); }
|
2015-07-14 01:09:28 +00:00
|
|
|
|
2023-03-27 13:33:06 -07:00
|
|
|
const UnixSignalsSP &Platform::GetRemoteUnixSignals() {
|
2015-07-14 01:09:28 +00:00
|
|
|
static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();
|
|
|
|
|
return s_default_unix_signals_sp;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-06 18:20:23 +00:00
|
|
|
UnixSignalsSP Platform::GetUnixSignals() {
|
2015-07-14 01:09:28 +00:00
|
|
|
if (IsHost())
|
2019-03-06 18:20:23 +00:00
|
|
|
return UnixSignals::CreateForHost();
|
2015-07-14 01:09:28 +00:00
|
|
|
return GetRemoteUnixSignals();
|
|
|
|
|
}
|
2015-12-02 11:58:51 +00:00
|
|
|
|
2015-12-08 13:43:59 +00:00
|
|
|
uint32_t Platform::LoadImage(lldb_private::Process *process,
|
|
|
|
|
const lldb_private::FileSpec &local_file,
|
|
|
|
|
const lldb_private::FileSpec &remote_file,
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status &error) {
|
2015-12-08 13:43:59 +00:00
|
|
|
if (local_file && remote_file) {
|
|
|
|
|
// Both local and remote file was specified. Install the local file to the
|
|
|
|
|
// given location.
|
|
|
|
|
if (IsRemote() || local_file != remote_file) {
|
|
|
|
|
error = Install(local_file, remote_file);
|
|
|
|
|
if (error.Fail())
|
|
|
|
|
return LLDB_INVALID_IMAGE_TOKEN;
|
|
|
|
|
}
|
2018-06-28 20:02:11 +00:00
|
|
|
return DoLoadImage(process, remote_file, nullptr, error);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2015-12-08 13:43:59 +00:00
|
|
|
if (local_file) {
|
|
|
|
|
// Only local file was specified. Install it to the current working
|
|
|
|
|
// directory.
|
|
|
|
|
FileSpec target_file = GetWorkingDirectory();
|
|
|
|
|
target_file.AppendPathComponent(local_file.GetFilename().AsCString());
|
|
|
|
|
if (IsRemote() || local_file != target_file) {
|
|
|
|
|
error = Install(local_file, target_file);
|
|
|
|
|
if (error.Fail())
|
|
|
|
|
return LLDB_INVALID_IMAGE_TOKEN;
|
|
|
|
|
}
|
2018-06-28 20:02:11 +00:00
|
|
|
return DoLoadImage(process, target_file, nullptr, error);
|
2019-07-26 18:14:08 +00:00
|
|
|
}
|
2015-12-08 13:43:59 +00:00
|
|
|
|
|
|
|
|
if (remote_file) {
|
|
|
|
|
// Only remote file was specified so we don't have to do any copying
|
2018-06-28 20:02:11 +00:00
|
|
|
return DoLoadImage(process, remote_file, nullptr, error);
|
2015-12-08 13:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-27 10:59:31 -07:00
|
|
|
error =
|
|
|
|
|
Status::FromErrorString("Neither local nor remote file was specified");
|
2015-12-08 13:43:59 +00:00
|
|
|
return LLDB_INVALID_IMAGE_TOKEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t Platform::DoLoadImage(lldb_private::Process *process,
|
|
|
|
|
const lldb_private::FileSpec &remote_file,
|
2018-06-28 20:02:11 +00:00
|
|
|
const std::vector<std::string> *paths,
|
|
|
|
|
lldb_private::Status &error,
|
|
|
|
|
lldb_private::FileSpec *loaded_image) {
|
2024-08-27 10:59:31 -07:00
|
|
|
error = Status::FromErrorString(
|
|
|
|
|
"LoadImage is not supported on the current platform");
|
2015-12-02 11:58:51 +00:00
|
|
|
return LLDB_INVALID_IMAGE_TOKEN;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-28 20:02:11 +00:00
|
|
|
uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,
|
|
|
|
|
const lldb_private::FileSpec &remote_filename,
|
|
|
|
|
const std::vector<std::string> &paths,
|
|
|
|
|
lldb_private::Status &error,
|
|
|
|
|
lldb_private::FileSpec *loaded_path)
|
|
|
|
|
{
|
|
|
|
|
FileSpec file_to_use;
|
|
|
|
|
if (remote_filename.IsAbsolute())
|
2018-11-01 21:05:36 +00:00
|
|
|
file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
|
|
|
|
|
|
|
|
|
|
remote_filename.GetPathStyle());
|
2018-06-28 20:02:11 +00:00
|
|
|
else
|
|
|
|
|
file_to_use = remote_filename;
|
2019-07-26 18:14:08 +00:00
|
|
|
|
2018-06-28 20:02:11 +00:00
|
|
|
return DoLoadImage(process, file_to_use, &paths, error, loaded_path);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 04:51:55 +00:00
|
|
|
Status Platform::UnloadImage(lldb_private::Process *process,
|
|
|
|
|
uint32_t image_token) {
|
2024-08-27 10:59:31 -07:00
|
|
|
return Status::FromErrorString(
|
|
|
|
|
"UnloadImage is not supported on the current platform");
|
2015-12-02 11:58:51 +00:00
|
|
|
}
|
2015-12-08 14:08:19 +00:00
|
|
|
|
2016-11-17 21:15:14 +00:00
|
|
|
lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,
|
|
|
|
|
llvm::StringRef plugin_name,
|
2020-07-14 08:44:40 -07:00
|
|
|
Debugger &debugger, Target *target,
|
|
|
|
|
Status &error) {
|
|
|
|
|
return DoConnectProcess(connect_url, plugin_name, debugger, nullptr, target,
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb::ProcessSP Platform::ConnectProcessSynchronous(
|
|
|
|
|
llvm::StringRef connect_url, llvm::StringRef plugin_name,
|
|
|
|
|
Debugger &debugger, Stream &stream, Target *target, Status &error) {
|
|
|
|
|
return DoConnectProcess(connect_url, plugin_name, debugger, &stream, target,
|
|
|
|
|
error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,
|
|
|
|
|
llvm::StringRef plugin_name,
|
|
|
|
|
Debugger &debugger, Stream *stream,
|
|
|
|
|
Target *target, Status &error) {
|
2015-12-08 14:08:19 +00:00
|
|
|
error.Clear();
|
|
|
|
|
|
|
|
|
|
if (!target) {
|
2022-08-01 12:36:38 -07:00
|
|
|
ArchSpec arch = Target::GetDefaultArchitecture();
|
2018-10-23 23:45:56 +00:00
|
|
|
|
2022-08-01 12:36:38 -07:00
|
|
|
const char *triple =
|
|
|
|
|
arch.IsValid() ? arch.GetTriple().getTriple().c_str() : "";
|
2018-10-23 23:45:56 +00:00
|
|
|
|
2015-12-08 14:08:19 +00:00
|
|
|
TargetSP new_target_sp;
|
2018-09-20 09:09:05 +00:00
|
|
|
error = debugger.GetTargetList().CreateTarget(
|
2018-10-23 23:45:56 +00:00
|
|
|
debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp);
|
2022-08-01 12:36:38 -07:00
|
|
|
|
2015-12-08 14:08:19 +00:00
|
|
|
target = new_target_sp.get();
|
2022-08-01 12:36:38 -07:00
|
|
|
if (!target || error.Fail()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2015-12-08 14:08:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb::ProcessSP process_sp =
|
2020-11-20 17:12:22 +01:00
|
|
|
target->CreateProcess(debugger.GetListener(), plugin_name, nullptr, true);
|
2020-07-14 08:44:40 -07:00
|
|
|
|
2015-12-08 14:08:19 +00:00
|
|
|
if (!process_sp)
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
2020-07-14 08:44:40 -07:00
|
|
|
// If this private method is called with a stream we are synchronous.
|
|
|
|
|
const bool synchronous = stream != nullptr;
|
|
|
|
|
|
|
|
|
|
ListenerSP listener_sp(
|
|
|
|
|
Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));
|
|
|
|
|
if (synchronous)
|
|
|
|
|
process_sp->HijackProcessEvents(listener_sp);
|
|
|
|
|
|
2020-07-13 13:44:01 -07:00
|
|
|
error = process_sp->ConnectRemote(connect_url);
|
2020-07-14 08:44:40 -07:00
|
|
|
if (error.Fail()) {
|
|
|
|
|
if (synchronous)
|
|
|
|
|
process_sp->RestoreProcessEvents();
|
2015-12-08 14:08:19 +00:00
|
|
|
return nullptr;
|
2020-07-14 08:44:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (synchronous) {
|
|
|
|
|
EventSP event_sp;
|
2022-12-04 16:51:25 -08:00
|
|
|
process_sp->WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp,
|
2020-07-14 08:44:40 -07:00
|
|
|
nullptr);
|
|
|
|
|
process_sp->RestoreProcessEvents();
|
|
|
|
|
bool pop_process_io_handler = false;
|
2023-04-21 13:49:01 -07:00
|
|
|
// This is a user-level stop, so we allow recognizers to select frames.
|
|
|
|
|
Process::HandleProcessStateChangedEvent(
|
|
|
|
|
event_sp, stream, SelectMostRelevantFrame, pop_process_io_handler);
|
2020-07-14 08:44:40 -07:00
|
|
|
}
|
2015-12-08 14:08:19 +00:00
|
|
|
|
|
|
|
|
return process_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t Platform::ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
|
2017-05-12 04:51:55 +00:00
|
|
|
lldb_private::Status &error) {
|
2015-12-08 14:08:19 +00:00
|
|
|
error.Clear();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2016-02-22 17:29:56 +00:00
|
|
|
|
|
|
|
|
size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
|
|
|
|
|
BreakpointSite *bp_site) {
|
|
|
|
|
ArchSpec arch = target.GetArchitecture();
|
2020-04-24 09:03:51 -07:00
|
|
|
assert(arch.IsValid());
|
2016-02-22 17:29:56 +00:00
|
|
|
const uint8_t *trap_opcode = nullptr;
|
|
|
|
|
size_t trap_opcode_size = 0;
|
|
|
|
|
|
|
|
|
|
switch (arch.GetMachine()) {
|
2019-10-16 19:14:49 +00:00
|
|
|
case llvm::Triple::aarch64_32:
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::aarch64: {
|
|
|
|
|
static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};
|
|
|
|
|
trap_opcode = g_aarch64_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_aarch64_opcode);
|
2016-04-14 14:28:34 +00:00
|
|
|
} break;
|
|
|
|
|
|
2019-10-17 15:16:21 +00:00
|
|
|
case llvm::Triple::arc: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = { 0xff, 0x7f };
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
|
|
|
|
} break;
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
// TODO: support big-endian arm and thumb trap codes.
|
2016-04-14 14:28:34 +00:00
|
|
|
case llvm::Triple::arm: {
|
2018-04-30 16:49:04 +00:00
|
|
|
// The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
|
|
|
|
|
// linux kernel does otherwise.
|
2016-04-14 14:28:34 +00:00
|
|
|
static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
|
|
|
|
|
static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
|
2016-02-22 17:29:56 +00:00
|
|
|
|
[lldb] [mostly NFC] Large WP foundation: WatchpointResources (#68845)
This patch is rearranging code a bit to add WatchpointResources to
Process. A WatchpointResource is meant to represent a hardware
watchpoint register in the inferior process. It has an address, a size,
a type, and a list of Watchpoints that are using this
WatchpointResource.
This current patch doesn't add any of the features of
WatchpointResources that make them interesting -- a user asking to watch
a 24 byte object could watch this with three 8 byte WatchpointResources.
Or a Watchpoint on 1 byte at 0x1002 and a second watchpoint on 1 byte at
0x1003, these must both be served by a single WatchpointResource on that
doubleword at 0x1000 on a 64-bit target, if two hardware watchpoint
registers were used to track these separately, one of them may not be
hit. Or if you have one Watchpoint on a variable with a condition set,
and another Watchpoint on that same variable with a command defined or
different condition, or ignorecount, both of those Watchpoints need to
evaluate their criteria/commands when their WatchpointResource has been
hit.
There's a bit of code movement to rearrange things in the direction I'll
need for implementing this feature, so I want to start with reviewing &
landing this mostly NFC patch and we can focus on the algorithmic
choices about how WatchpointResources are shared and handled as they're
triggeed, separately.
This patch also stops printing "Watchpoint <n> hit: old value: <x>, new
vlaue: <y>" for Read watchpoints. I could make an argument for print
"Watchpoint <n> hit: current value <x>" but the current output doesn't
make any sense, and the user can print the value if they are
particularly interested. Read watchpoints are used primarily to
understand what code is reading a variable.
This patch adds more fallbacks for how to print the objects being
watched if we have types, instead of assuming they are all integral
values, so a struct will print its elements. As large watchpoints are
added, we'll be doing a lot more of those.
To track the WatchpointSP in the WatchpointResources, I changed the
internal API which took a WatchpointSP and devolved it to a Watchpoint*,
which meant touching several different Process files. I removed the
watchpoint code in ProcessKDP which only reported that watchpoints
aren't supported, the base class does that already.
I haven't yet changed how we receive a watchpoint to identify the
WatchpointResource responsible for the trigger, and identify all
Watchpoints that are using this Resource to evaluate their conditions
etc. This is the same work that a BreakpointSite needs to do when it has
been tiggered, where multiple Breakpoints may be at the same address.
There is not yet any printing of the Resources that a Watchpoint is
implemented in terms of ("watchpoint list", or
SBWatchpoint::GetDescription).
"watchpoint set var" and "watchpoint set expression" take a size
argument which was previously 1, 2, 4, or 8 (an enum). I've changed this
to an unsigned int. Most hardware implementations can only watch 1, 2,
4, 8 byte ranges, but with Resources we'll allow a user to ask for
different sized watchpoints and set them in hardware-expressble terms
soon.
I've annotated areas where I know there is work still needed with
LWP_TODO that I'll be working on once this is landed.
I've tested this on aarch64 macOS, aarch64 Linux, and Intel macOS.
https://discourse.llvm.org/t/rfc-large-watchpoint-support-in-lldb/72116
(cherry picked from commit fc6b72523f3d73b921690a713e97a433c96066c6)
2023-11-27 13:28:59 -08:00
|
|
|
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetConstituentAtIndex(0));
|
2018-06-26 13:06:54 +00:00
|
|
|
AddressClass addr_class = AddressClass::eUnknown;
|
2016-02-22 17:29:56 +00:00
|
|
|
|
|
|
|
|
if (bp_loc_sp) {
|
|
|
|
|
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
|
2018-06-26 13:06:54 +00:00
|
|
|
if (addr_class == AddressClass::eUnknown &&
|
2016-02-22 17:29:56 +00:00
|
|
|
(bp_loc_sp->GetAddress().GetFileAddress() & 1))
|
2018-06-26 13:06:54 +00:00
|
|
|
addr_class = AddressClass::eCodeAlternateISA;
|
2016-02-22 17:29:56 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-26 13:06:54 +00:00
|
|
|
if (addr_class == AddressClass::eCodeAlternateISA) {
|
2016-02-22 17:29:56 +00:00
|
|
|
trap_opcode = g_thumb_breakpoint_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} else {
|
2016-02-22 17:29:56 +00:00
|
|
|
trap_opcode = g_arm_breakpoint_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
|
2020-02-07 22:39:56 +01:00
|
|
|
case llvm::Triple::avr: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = {0x98, 0x95};
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
|
|
|
|
} break;
|
|
|
|
|
|
2016-02-26 15:11:01 +00:00
|
|
|
case llvm::Triple::mips:
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::mips64: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = {0x00, 0x00, 0x00, 0x0d};
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2016-02-26 15:11:01 +00:00
|
|
|
case llvm::Triple::mipsel:
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::mips64el: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = {0x0d, 0x00, 0x00, 0x00};
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2023-04-17 15:26:48 -07:00
|
|
|
case llvm::Triple::msp430: {
|
|
|
|
|
static const uint8_t g_msp430_opcode[] = {0x43, 0x43};
|
|
|
|
|
trap_opcode = g_msp430_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_msp430_opcode);
|
|
|
|
|
} break;
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::systemz: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = {0x00, 0x01};
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::hexagon: {
|
|
|
|
|
static const uint8_t g_hex_opcode[] = {0x0c, 0xdb, 0x00, 0x54};
|
|
|
|
|
trap_opcode = g_hex_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_hex_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::ppc:
|
|
|
|
|
case llvm::Triple::ppc64: {
|
|
|
|
|
static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08};
|
|
|
|
|
trap_opcode = g_ppc_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_ppc_opcode);
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2017-10-05 19:44:05 +00:00
|
|
|
case llvm::Triple::ppc64le: {
|
|
|
|
|
static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
|
|
|
|
|
trap_opcode = g_ppc64le_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_ppc64le_opcode);
|
|
|
|
|
} break;
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
case llvm::Triple::x86:
|
|
|
|
|
case llvm::Triple::x86_64: {
|
|
|
|
|
static const uint8_t g_i386_opcode[] = {0xCC};
|
|
|
|
|
trap_opcode = g_i386_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_i386_opcode);
|
2022-08-10 21:36:48 +08:00
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case llvm::Triple::riscv32:
|
|
|
|
|
case llvm::Triple::riscv64: {
|
|
|
|
|
static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak
|
2022-10-20 23:05:37 +08:00
|
|
|
static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak
|
|
|
|
|
if (arch.GetFlags() & ArchSpec::eRISCV_rvc) {
|
|
|
|
|
trap_opcode = g_riscv_opcode_c;
|
|
|
|
|
trap_opcode_size = sizeof(g_riscv_opcode_c);
|
|
|
|
|
} else {
|
|
|
|
|
trap_opcode = g_riscv_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_riscv_opcode);
|
|
|
|
|
}
|
2016-09-06 20:57:50 +00:00
|
|
|
} break;
|
|
|
|
|
|
2022-11-10 13:48:22 +08:00
|
|
|
case llvm::Triple::loongarch32:
|
|
|
|
|
case llvm::Triple::loongarch64: {
|
|
|
|
|
static const uint8_t g_loongarch_opcode[] = {0x05, 0x00, 0x2a,
|
|
|
|
|
0x00}; // break 0x5
|
|
|
|
|
trap_opcode = g_loongarch_opcode;
|
|
|
|
|
trap_opcode_size = sizeof(g_loongarch_opcode);
|
|
|
|
|
} break;
|
|
|
|
|
|
2016-09-06 20:57:50 +00:00
|
|
|
default:
|
2020-04-24 09:03:51 -07:00
|
|
|
return 0;
|
2016-09-06 20:57:50 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
assert(bp_site);
|
|
|
|
|
if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
|
|
|
|
|
return trap_opcode_size;
|
2016-09-06 20:57:50 +00:00
|
|
|
|
2016-02-22 17:29:56 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2022-01-19 20:16:07 +01:00
|
|
|
|
|
|
|
|
CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) {
|
|
|
|
|
return CompilerType();
|
|
|
|
|
}
|
2022-02-25 14:47:27 +01:00
|
|
|
|
2022-05-11 15:10:16 -07:00
|
|
|
Args Platform::GetExtraStartupCommands() {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 11:18:03 -04:00
|
|
|
void Platform::SetLocateModuleCallback(LocateModuleCallback callback) {
|
|
|
|
|
m_locate_module_callback = callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {
|
|
|
|
|
return m_locate_module_callback;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {
|
2022-02-25 14:47:27 +01:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
|
for (const PlatformSP &platform_sp : m_platforms) {
|
|
|
|
|
if (platform_sp->GetName() == name)
|
|
|
|
|
return platform_sp;
|
|
|
|
|
}
|
2023-01-13 08:51:03 -08:00
|
|
|
return Create(name);
|
2022-02-25 14:47:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,
|
|
|
|
|
const ArchSpec &process_host_arch,
|
2023-01-13 08:51:03 -08:00
|
|
|
ArchSpec *platform_arch_ptr,
|
|
|
|
|
Status &error) {
|
2022-02-25 14:47:27 +01:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
|
// First try exact arch matches across all platforms already created
|
|
|
|
|
for (const auto &platform_sp : m_platforms) {
|
2022-03-09 16:00:26 +01:00
|
|
|
if (platform_sp->IsCompatibleArchitecture(
|
|
|
|
|
arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr))
|
2022-02-25 14:47:27 +01:00
|
|
|
return platform_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Next try compatible arch matches across all platforms already created
|
|
|
|
|
for (const auto &platform_sp : m_platforms) {
|
2022-03-09 16:00:26 +01:00
|
|
|
if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch,
|
|
|
|
|
ArchSpec::CompatibleMatch,
|
2022-02-25 14:47:27 +01:00
|
|
|
platform_arch_ptr))
|
|
|
|
|
return platform_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformCreateInstance create_callback;
|
|
|
|
|
// First try exact arch matches across all platform plug-ins
|
|
|
|
|
uint32_t idx;
|
|
|
|
|
for (idx = 0;
|
|
|
|
|
(create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
|
|
|
|
|
++idx) {
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP platform_sp = create_callback(false, &arch);
|
2022-03-09 16:00:26 +01:00
|
|
|
if (platform_sp &&
|
|
|
|
|
platform_sp->IsCompatibleArchitecture(
|
|
|
|
|
arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr)) {
|
2022-02-25 14:47:27 +01:00
|
|
|
m_platforms.push_back(platform_sp);
|
|
|
|
|
return platform_sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Next try compatible arch matches across all platform plug-ins
|
|
|
|
|
for (idx = 0;
|
|
|
|
|
(create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
|
|
|
|
|
++idx) {
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP platform_sp = create_callback(false, &arch);
|
2022-02-25 14:47:27 +01:00
|
|
|
if (platform_sp && platform_sp->IsCompatibleArchitecture(
|
2022-03-09 16:00:26 +01:00
|
|
|
arch, process_host_arch, ArchSpec::CompatibleMatch,
|
|
|
|
|
platform_arch_ptr)) {
|
2022-02-25 14:47:27 +01:00
|
|
|
m_platforms.push_back(platform_sp);
|
|
|
|
|
return platform_sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (platform_arch_ptr)
|
|
|
|
|
platform_arch_ptr->Clear();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,
|
|
|
|
|
const ArchSpec &process_host_arch,
|
2023-01-13 08:51:03 -08:00
|
|
|
ArchSpec *platform_arch_ptr) {
|
2022-02-25 14:47:27 +01:00
|
|
|
Status error;
|
|
|
|
|
if (arch.IsValid())
|
2023-01-13 08:51:03 -08:00
|
|
|
return GetOrCreate(arch, process_host_arch, platform_arch_ptr, error);
|
2022-02-25 14:47:27 +01:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs,
|
|
|
|
|
const ArchSpec &process_host_arch,
|
2023-01-13 08:51:03 -08:00
|
|
|
std::vector<PlatformSP> &candidates) {
|
2022-02-25 14:47:27 +01:00
|
|
|
candidates.clear();
|
|
|
|
|
candidates.reserve(archs.size());
|
|
|
|
|
|
|
|
|
|
if (archs.empty())
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
PlatformSP host_platform_sp = Platform::GetHostPlatform();
|
|
|
|
|
|
|
|
|
|
// Prefer the selected platform if it matches at least one architecture.
|
|
|
|
|
if (m_selected_platform_sp) {
|
|
|
|
|
for (const ArchSpec &arch : archs) {
|
|
|
|
|
if (m_selected_platform_sp->IsCompatibleArchitecture(
|
2022-03-09 16:00:26 +01:00
|
|
|
arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))
|
2022-02-25 14:47:27 +01:00
|
|
|
return m_selected_platform_sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prefer the host platform if it matches at least one architecture.
|
|
|
|
|
if (host_platform_sp) {
|
|
|
|
|
for (const ArchSpec &arch : archs) {
|
2022-03-09 16:00:26 +01:00
|
|
|
if (host_platform_sp->IsCompatibleArchitecture(
|
|
|
|
|
arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))
|
2022-02-25 14:47:27 +01:00
|
|
|
return host_platform_sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect a list of candidate platforms for the architectures.
|
|
|
|
|
for (const ArchSpec &arch : archs) {
|
2023-01-13 08:51:03 -08:00
|
|
|
if (PlatformSP platform = GetOrCreate(arch, process_host_arch, nullptr))
|
2022-02-25 14:47:27 +01:00
|
|
|
candidates.push_back(platform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The selected or host platform didn't match any of the architectures. If
|
|
|
|
|
// the same platform supports all architectures then that's the obvious next
|
|
|
|
|
// best thing.
|
|
|
|
|
if (candidates.size() == archs.size()) {
|
2022-08-14 16:25:36 -07:00
|
|
|
if (llvm::all_of(candidates, [&](const PlatformSP &p) -> bool {
|
|
|
|
|
return p->GetName() == candidates.front()->GetName();
|
|
|
|
|
})) {
|
2022-02-25 14:47:27 +01:00
|
|
|
return candidates.front();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// At this point we either have no platforms that match the given
|
|
|
|
|
// architectures or multiple platforms with no good way to disambiguate
|
|
|
|
|
// between them.
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP PlatformList::Create(llvm::StringRef name) {
|
2022-02-25 14:47:27 +01:00
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP platform_sp = Platform::Create(name);
|
2022-02-25 14:47:27 +01:00
|
|
|
m_platforms.push_back(platform_sp);
|
|
|
|
|
return platform_sp;
|
|
|
|
|
}
|
2022-09-09 14:52:59 -07:00
|
|
|
|
|
|
|
|
bool PlatformList::LoadPlatformBinaryAndSetup(Process *process,
|
|
|
|
|
lldb::addr_t addr, bool notify) {
|
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
|
|
|
|
|
|
PlatformCreateInstance create_callback;
|
|
|
|
|
for (int idx = 0;
|
|
|
|
|
(create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));
|
|
|
|
|
++idx) {
|
|
|
|
|
ArchSpec arch;
|
2023-01-13 08:51:03 -08:00
|
|
|
PlatformSP platform_sp = create_callback(true, &arch);
|
2022-09-09 14:52:59 -07:00
|
|
|
if (platform_sp) {
|
|
|
|
|
if (platform_sp->LoadPlatformBinaryAndSetup(process, addr, notify))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|